Since we want to keep things strongly typed (but without the ugly complicated notation of generics) we want to declare typed lists and maps. Plus having lists and maps as part of the builtin language is a must have (as Ruby and Python have proved).
The syntax for declaring List types:
Str[] // List of Str
Str[][] // List of List of Str
It matches the Java/C# array syntax exactly, so should be easy to grok - just like arrays except dynamic and with cool methods!
The syntax for declaring Map types:
Int:Str // Map of Str keyed by Int
Str:Obj // Map of Obj keyed by Str
Int:Str[] // Map of List of Str keyed by Int
Note with this syntax there is no way to declare a List of Maps, since the [] always binds to the value type. But we decided this was an acceptable compromise since who the hell really needs a strongly typed list of maps anyways in their public API. If we did support it, it would be some really ugly kludge like (Int:Str)[].
Furthermore Fan provides direct support for List and Map literals:
Note that if no type declaration precedes the bracket, then we assume the type to be the most specific common type among the elements (using straight extends, not interfaces). You can optionally specify a List/Map type before the opening bracket, which is useful if you if want to downcast the collections declared type (especially if using in combo with def-assign).
You cannot use the new operator with lists or maps, because that could lead to confusion. The following would be a list containing the number 4, not a list sized to 4:
Int[] x = new Int[4] // wrong, compile time error
Int[] x = [] // right
x := Int[] // right
I think that will help keep Java/C# coders straight.
brianThu 8 Dec 2005
Ok, I checked in basic support end to end for list literals. I also have the parser/ast updated to support Maps, just not the assembler.
The problem I am having is that explicit typing such as Str[...] creates an ambiguous grammer since it is possible that it conflicts with the index operator foo[i]. Eventually I could figure it out once I resolve the types and know that it is a type, not a variable - but that is way too late in the pipeline.
So basically we need some other syntax to explicitly type lists, some options:
I don't really have that problem with maps, since it is clear with the KeyType:ValueType grammar.
Ideas?
andyThu 8 Dec 2005
You know, I have been thinking about this - and I am just not sure that we have this syntax down right - especially given the issues that came up with lists of maps (which I think we actually should allow).
Did we decide that we didn't want to use new?
myArray := new Obj[0, 1, 2]
myArray := new [0, 1, 2] // This case is weird though, or
// is new only used when declaring a type?
myArray := [0, 1, 2]
Though, I don't like the random character like you have above. Maybe it looks something like this:
You are missing one of THE most important points - to make lists and maps as easy to use as int, real, and str literals. One of the reasons people love python, ruby, etc is that declaring lists is really really easy. Any syntax required beyond the base [] is a nonstarter. Would you stand for requiring every string literal to use the new operator - hell no!
The only case we need to handle is the special case of when the type of the list's items can't be inferred correctly (which should be rare). The reason I don't want to use the new operator is because C/Java/C# developers will be confused by this code:
Int[] x := new Int[2]
That declares list containing 2 as the only element - not an int array sized to 2. So I think we ought to scratch new off our list of ideas.
andyThu 8 Dec 2005
Well I agree - but doesn't Ruby use Array.new? Though either way, we have talked about inferring type - how often will we really be able to do that. I think this is by far the most common case for how I create arrays (at least for me):
In these types of cases - I am starting with an empty array, so I will always need to specify my type.
brianThu 8 Dec 2005
We will stick with my original grammar I proposed and I will just deal with the ambiguity (actually after some thought it won't be a very big deal).
brianSat 10 Dec 2005
Ok, I checked in support for explicitly typed list literals. Figuring out the ambiguity of Str["a"] was actually pretty trival.
When we brainstorm next, we need to decide how much to carry list/map typing thru. For example we definitly can have type checking at the compiler level.
We probably want to make this work correctly:
x := ["a", "b"]
assert(x is Str[])
assert(x isnot Int[])
BTW I am not sure if there is actually an "isnot" operator, but do I hate having to do this all the time: !(x is Int[]) and it is pretty common. Although maybe having an unless statement to inverse if would solve that problem.
Anyways, I digress... so that means we pass the Class around with the List instance. I am already doing this when I construct the List literal in bytecode. However, should I actually use that class to check sets and adds at runtime? It could be a pretty bit performance hit, and I question it's value given partial type checking at compile time.
andySat 10 Dec 2005
I think we definitly want compile-time type-checking for maps and lists.
I'm not sure what you mean about checking at runtime - somone has to do that check? Do you mean letting the VM do it?
brianSat 10 Dec 2005
Well everything is just a List at runtime, but that doesn't mean we can't something like this:
void add(Object x)
{
if (!listOfClass.isAssignable(x))
throw new ClassCastException();
// add to list
}
brianSun 29 Jan 2006
I ran into some ambiguity problems with empty lists, so I decided to fix it at the grammar level:
Str[] -> this is the typename for List<Str>
Str[,] -> this is an empty list typed as Str[]
Without an explicit type:
[] -> this is never valid
[,] -> same as Obj[,]
Carries thru:
Str[].type -> this is type literal resulting in LoadType
Str[,].type -> this creates a new List, and calls type()
brian Wed 7 Dec 2005
Since we want to keep things strongly typed (but without the ugly complicated notation of generics) we want to declare typed lists and maps. Plus having lists and maps as part of the builtin language is a must have (as Ruby and Python have proved).
The syntax for declaring List types:
It matches the Java/C# array syntax exactly, so should be easy to grok - just like arrays except dynamic and with cool methods!
The syntax for declaring Map types:
Note with this syntax there is no way to declare a List of Maps, since the [] always binds to the value type. But we decided this was an acceptable compromise since who the hell really needs a strongly typed list of maps anyways in their public API. If we did support it, it would be some really ugly kludge like (Int:Str)[].
Furthermore Fan provides direct support for List and Map literals:
Note that if no type declaration precedes the bracket, then we assume the type to be the most specific common type among the elements (using straight extends, not interfaces). You can optionally specify a List/Map type before the opening bracket, which is useful if you if want to downcast the collections declared type (especially if using in combo with def-assign).
You cannot use the new operator with lists or maps, because that could lead to confusion. The following would be a list containing the number 4, not a list sized to 4:
I think that will help keep Java/C# coders straight.
brian Thu 8 Dec 2005
Ok, I checked in basic support end to end for list literals. I also have the parser/ast updated to support Maps, just not the assembler.
The problem I am having is that explicit typing such as Str[...] creates an ambiguous grammer since it is possible that it conflicts with the index operator foo[i]. Eventually I could figure it out once I resolve the types and know that it is a type, not a variable - but that is way too late in the pipeline.
So basically we need some other syntax to explicitly type lists, some options:
I don't really have that problem with maps, since it is clear with the KeyType:ValueType grammar.
Ideas?
andy Thu 8 Dec 2005
You know, I have been thinking about this - and I am just not sure that we have this syntax down right - especially given the issues that came up with lists of maps (which I think we actually should allow).
Did we decide that we didn't want to use
new
?Though, I don't like the random character like you have above. Maybe it looks something like this:
Though that still doesn't solve this case:
brian Thu 8 Dec 2005
You are missing one of THE most important points - to make lists and maps as easy to use as int, real, and str literals. One of the reasons people love python, ruby, etc is that declaring lists is really really easy. Any syntax required beyond the base [] is a nonstarter. Would you stand for requiring every string literal to use the new operator - hell no!
The only case we need to handle is the special case of when the type of the list's items can't be inferred correctly (which should be rare). The reason I don't want to use the new operator is because C/Java/C# developers will be confused by this code:
That declares list containing 2 as the only element - not an int array sized to 2. So I think we ought to scratch new off our list of ideas.
andy Thu 8 Dec 2005
Well I agree - but doesn't Ruby use Array.new? Though either way, we have talked about inferring type - how often will we really be able to do that. I think this is by far the most common case for how I create arrays (at least for me):
In these types of cases - I am starting with an empty array, so I will always need to specify my type.
brian Thu 8 Dec 2005
We will stick with my original grammar I proposed and I will just deal with the ambiguity (actually after some thought it won't be a very big deal).
brian Sat 10 Dec 2005
Ok, I checked in support for explicitly typed list literals. Figuring out the ambiguity of Str["a"] was actually pretty trival.
When we brainstorm next, we need to decide how much to carry list/map typing thru. For example we definitly can have type checking at the compiler level.
We probably want to make this work correctly:
BTW I am not sure if there is actually an "isnot" operator, but do I hate having to do this all the time: !(x is Int[]) and it is pretty common. Although maybe having an unless statement to inverse if would solve that problem.
Anyways, I digress... so that means we pass the Class around with the List instance. I am already doing this when I construct the List literal in bytecode. However, should I actually use that class to check sets and adds at runtime? It could be a pretty bit performance hit, and I question it's value given partial type checking at compile time.
andy Sat 10 Dec 2005
I think we definitly want compile-time type-checking for maps and lists.
I'm not sure what you mean about checking at runtime - somone has to do that check? Do you mean letting the VM do it?
brian Sat 10 Dec 2005
Well everything is just a List at runtime, but that doesn't mean we can't something like this:
brian Sun 29 Jan 2006
I ran into some ambiguity problems with empty lists, so I decided to fix it at the grammar level:
Without an explicit type:
Carries thru: