Can I declare an empty list of mixed types?


#1

For example,
!myList : {Real! String!} // creates a non-empty list of mixed types
!myList : Real{} // creates an empty list of a single type
!myList : Real|String{} // ???


#2

(I was just writing a docs entry on List right now.)

To answer your question:

!myList : {0.0 ""}             // Infers <Real|String> as item type
!myList : List{<Real|String>}! // empty and can add Real or String

List initialization can be tricky as far as its syntax is concerned since there is the type of the list, the type(s) of the items in the list and initial items in optional list literals.

Here are a bunch of ways to create/initialize a List:

// Simple list literals
{}        // empty with list type: List and item type: Object
{1 2}     // 2 items - Integer type inferred for items
{1 "hi"}  // 2 items - <Integer|String> type inferred

// Specify item type (using non list class)
// with `List` for list class type
Integer{}     // empty List of Integer objects
Integer{1 2}  // List of 2 Integer objects

// Create list of List type without item type specified
List!
List!{}        // empty item list
List!{1 2}     // 2 items - Integer type inferred
List!{1 "hi"}  // 2 items - <Integer|String> type inferred

// Create list using empty item type specifier
List{}!
List{}!{}        // empty item list
List{}!{1 2}     // 2 items - Integer type inferred
List{}!{1 "hi"}  // 2 items - <Integer|String> type inferred

// Create list with Integer item type specified
List{Integer}!
List{Integer}!{}                 // empty item list
List{Integer}!{1 2}              // 2 items
List{<Integer|String>}!          // can add String or Integer
List{<Integer|String>}!{1 2}     // 2 items, can add String
List{<Integer|String>}!{1 "hi"}  // 2 mixed Integer or String

// `List` can be replaced with any subclass of `List`.
// For example:
ListStates{Symbol}!                     // empty
ListStates!{'state1' 'state2'}          // 2 items type inferred
ListStates{Symbol}!{'state1' 'state2'}  // 2 items

Feel free to ask more List questions.


#3

Example:

!myList : List{<Real|String>}!
!myItem : {1.5 "hello"}
myList.append(myItem)
myList.do [println(item.at(0))] // Error 'item' was expected to be <Real|String> but it's type 'List{<Real|String>}'

But this works:

!myItem : {1.5 "hello"}
!myList : {myItem}
myList.empty()
myList.append(myItem)
myList.do [println(item.at(0))] // prints "1.5" correctly

#4

My mistake. The first part should read:
!myList : {List{<Real|String>}!}
Fixed!


#5

This works because the parser infers the type, though it also creates a list with an initial item:

!myItem : {1.5 "hello"}
!myList : {myItem}

Result: {{1.5, "hello"}}

This creates a list with an initial empty list item - which also infers the list type:

!myList : {List{<Real|String>}!}

Result: {{}}

This creates an empty list of list items.

!myList : List{List{<Real|String>}}!

// Same thing though somewhat simpler - Type{}
!myList : List{<Real|String>}{}

Result: {}


#6

Even better! Thanks.