0

In Python, we can do this.

board = {'us': {'name': 'USA', 'govern': 'good'}, 
         'canada': {'name': 'Canada', 'govern': 'good'},
         'uk': {'name': 'UK', 'govern': 'good', 'recruit': 3},
         'spain': {'name': 'Spain', 'govern': 'good', 'schengen': True, 'recruit': 2},
         'france': {'name': 'France', 'govern': 'good', 'schengen': True, 'recruit': 2},
         'italy': {'name': 'italy', 'govern': 'good', 'schengen': True} }

to create a dictionary of name value pairs for easy lookup. Can I the the same in Stanza language, like:

deftype Countries <: Table<String,Table<String,?>>  
; value could be anything. we see Int|String|True|False here
    
val board : Countries = to-table( "us" => ( "name" => "USA", "govern" => "good" ), ....)

?

Ken White
  • 123,280
  • 14
  • 225
  • 444
S2000Erwin
  • 11
  • 1

2 Answers2

2

The closest data structure to a python dictionary in stanza is Hashtable, from collections. You can do something like :


; to-hashtable<K,V> can be found in collections, too!
val board = to-hashtable<String, HashTable<String, ?>> $ [
  "us" => to-hashtable<String, ?> $ [
    "name" => "USA"
  ],
  "fr" => to-hashtable<String, ?> $ [
    "name" => "France"
  ]
  ; .. etc ... 
]

println(board["us"])

This will output :

HashTable(
  "name" => "USA")

deftype Countries <: Table<...> doesn't create an alias for Table, it declares a new type. In order to use it like a table, you would need to implement the required methods for Table.


But normally we like to add more type information, not less!

defenum Government : 
  Democracy
  Republic
  Monarchy  

defstruct Country :
  name:String,
  gov:Government
  ; ... etc ... 

val board = to-hashtable<String,Country> $ [
  "us" => Country(name, gov) where : 
    val name = "USA"
    val gov  = Republic
  "fr" => Country(name, gov) where : 
    val name = "France"
    val gov  = Republic
]
  • Thanks, I did come up with a solution that used HashTable. See my answer to myself below. The information requires that each country may have different KeyValue pairs. For example some may have "recruit" => Int while other may be "schengen" => true. Can we do a variable data structure similar to JSON? Or is there a JSON importer? – S2000Erwin Mar 16 '22 at 00:12
  • Can't find defenum. Is it a new feature? – S2000Erwin Mar 16 '22 at 00:44
  • `defenum` is a recent feature of stanza, I'm not sure if it's documented in LB Stanza by example! The `?` type can be used for representing any type, so `HashTable` means, "a hash table with keys of type `String` and values of any type." For this specific case you would prefer to have it typed more explicitly, however : ``` defstruct Country : name:String recruit:Int schengen:True|False ; ... and so on ... ``` `defstruct` acts like a record type where the fields are all named and typed (although struct fields may be typed `?`). – Mike Hilgendorf Mar 16 '22 at 03:16
  • Thanks. How to signify if some keys are not always there. e.g. some countries do not have "recruit" key; it is meaningless for a non-European country to have "schengen" attribute. Some keys may be added or removed during the life cycle of the record dynamically. – S2000Erwin Mar 16 '22 at 05:46
  • The convention for optional fields in a struct is `field?: T|False`. There is also the `Maybe` type, for the case where `T` may be a boolean. – Mike Hilgendorf Mar 16 '22 at 13:59
  • Thanks, Mike. That is really useful. – S2000Erwin Mar 17 '22 at 17:16
0

I kind of come up with a solution:

defpackage labyrinth :
   import core
   import collections

deftype Countries <: HashTable<String,?>

defn print-deep ( xs : HashTable<String,?> ) :
   for x in xs do :
      val k = key(x)
      val v = value(x)
      print("%_ => " % [k])
      match(v):
         (v: HashTable<String,?>) : (print("[ "), print-deep(v), println("]"))
         (v) : ( print(v), print(", ") )

defn to-hashtable ( t : HashTable<String,?>, kvs : Tuple<KeyValue<?,?>> ) -> False :
   for kv in kvs do :
      val k = key(kv)
      val v = value(kv)
      match(k) :
         (k : String) : 
            if v is Tuple<?> :
               var d : HashTable<String,?> = HashTable<String,?>()
               to-hashtable(d, v)
               set(t, k, d)
            else :
               t[k] = v               
  

defn to-countries ( kvs : Tuple<KeyValue<String,?>> ) -> HashTable<String,?> :
   val t : HashTable<String,?> = HashTable<String,?>()
   to-hashtable(t, kvs)
   t
   
   
defn test () -> HashTable<String,?> :
   val c : Tuple<KeyValue<String,?>> = 
   [ "us" => ["name" => "us", "govern" => "good"]
     "canada" => [ "name" => "Canada" "govern" => "good" ]
     "uk" => [ "name" => "UK" "govern" => "good" "recruit" => 3 ]
     "spain" => [ "name" => "Spain" "govern" => "good" "schengen" => true "recruit" => 2 ]
     "france" => [ "name" => "France" "govern" => "good" "schengen" => true "recruit" => 2 ]
     "italy" => [ "name" => "italy" "govern" => "good" "schengen" => true ]
   ]
   val countries = to-countries(c)
   countries
   
   
val board = test()
print-deep(board)
Dharman
  • 30,962
  • 25
  • 85
  • 135
S2000Erwin
  • 11
  • 1