I've gotten most of the code base switched from with-blocks to it-blocks. However I am at a bit of a roadblock regarding how to handle the implicit add inside of with-blocks. There is a ton of code using this feature, so it isn't easy to work past.
Previously any expression which wasn't an assignment was assumed to be either a call on the with-block target or an implicit add. That worked ok because with-blocks weren't actually closures, and had a very limited internal grammar.
Now it-blocks are general purpose closures and can contain any statement. So we can't just implicitly assume any expression with a non-Void result should be blindly added to the it parameter.
So I think it is a requirement that add is somehow explicitly declared. The way we have talked about this in the past is using the comma as a postfix operator.
I propose that comma is treated as syntax sugar for it.add:
a, => it.add(a)
a,b => it.add(b).add(b)
a,b, => same as above
a,b,c => it.add(b).add(b).add(c)
Note that a comma separated list of expressions is parsed as a single expression by chaining the add call. That simplifies the compiler and management of the stack.
It isn't the greatest solution because it requires you add a weird trailing comma:
GridPane { Label { text="hi" }, }
But it does give you the syntactic power to create custom collection literals. So seems like a reasonable trade-off.
andyMon 6 Apr 2009
I'm not crazy about it, and seems like an common mistake to leave off. But to avoid the method call, you would have to have some type of prefix/suffix, so the comma probably makes the most sense. I could live with it unless someone floats a better solution, which we really haven't been able to come up with yet.
jodastephenMon 6 Apr 2009
My preference has been a general append operator, as seen in other languages:
list.add(a).add(b)
list << a << b
In general, I wouldn't expect to see this have too wide a use. However, it-blocks are just a special case then:
GridPane { << Label { text="hi" } }
Or, you could just go with the method call:
GridPane { add Label { text="hi" } }
Whatever the choice, I think the comma suffix is way too easy to forget, and far too subtle to read.
brianMon 6 Apr 2009
Whatever the choice, I think the comma suffix is way too easy to forget, and far too subtle to read.
Remember that any syntax we choose for the language will be mimicked in the serialization syntax. While I don't love the comma, the more verbose syntaxes take away Fan's clean JSON-like serialization syntax.
JohnDGMon 6 Apr 2009
But it does give you the syntactic power to create custom collection literals. So seems like a reasonable trade-off.
I like the comma. It's a single character and it's already used for list construction in nearly all languages. Plus, like you say, it allows custom collections.
brianTue 7 Apr 2009
One of the subtle changes I made related to this feature is that now I report a stand alone constructor call as a "Not a statement" error. This will allow the compiler to catch the common case when you forget a comma. The only reason to allow constructors to be stand alone statements is if your ctor has side effects (which seems like something to prevent anyhow).
I also added a compiler check for when you attempt to assign the same variable to itself. This catches the other case it-blocks reveal:
x := 5
Foo { x = x } // now illegal
Foo { it.x = x } // required syntax if locals hide this/it
That is actually a really nice error - I've definitely hit that in Java where I do something like this:
// self assignment b/c of typo on param name
Foo(int someVarx) { this.someVar = someVar }
cheeserTue 7 Apr 2009
what about
y := 5
Foo { x = y }
Is that still legal without the it qualifier?
tacticsTue 7 Apr 2009
I think a prefix operator might be a good idea. Maybe * instead of <<, which makes it look like a bulleted list.
GridPane
{
* Label { text="hi" }
* Text {}
}
For multiple add statements on a single line, you could use a single bullet with commas:
GridPane
{
* Label { text="hi" }, Text {}
}
brianTue 7 Apr 2009
Is that still legal without the it qualifier?
The it qualifier is only required in the same circumstances as this - only when a local variable hides a slot name. So if your case, assuming y was neither a slot on this nor it, then no qualifiers are required. The twist from Java is really that you implicitly scope the slots on both it and this.
I think a prefix operator might be a good idea. Maybe * instead of <<, which makes it look like a bulleted list
I have already implemented using the comma - it actually looks pretty good.
brian Mon 6 Apr 2009
I've gotten most of the code base switched from with-blocks to it-blocks. However I am at a bit of a roadblock regarding how to handle the implicit add inside of with-blocks. There is a ton of code using this feature, so it isn't easy to work past.
Previously any expression which wasn't an assignment was assumed to be either a call on the with-block target or an implicit add. That worked ok because with-blocks weren't actually closures, and had a very limited internal grammar.
Now it-blocks are general purpose closures and can contain any statement. So we can't just implicitly assume any expression with a non-Void result should be blindly added to the
it
parameter.So I think it is a requirement that
add
is somehow explicitly declared. The way we have talked about this in the past is using the comma as a postfix operator.I propose that comma is treated as syntax sugar for
it.add
:Note that a comma separated list of expressions is parsed as a single expression by chaining the
add
call. That simplifies the compiler and management of the stack.It isn't the greatest solution because it requires you add a weird trailing comma:
But it does give you the syntactic power to create custom collection literals. So seems like a reasonable trade-off.
andy Mon 6 Apr 2009
I'm not crazy about it, and seems like an common mistake to leave off. But to avoid the method call, you would have to have some type of prefix/suffix, so the comma probably makes the most sense. I could live with it unless someone floats a better solution, which we really haven't been able to come up with yet.
jodastephen Mon 6 Apr 2009
My preference has been a general
append
operator, as seen in other languages:In general, I wouldn't expect to see this have too wide a use. However, it-blocks are just a special case then:
Or, you could just go with the method call:
Whatever the choice, I think the comma suffix is way too easy to forget, and far too subtle to read.
brian Mon 6 Apr 2009
Remember that any syntax we choose for the language will be mimicked in the serialization syntax. While I don't love the comma, the more verbose syntaxes take away Fan's clean JSON-like serialization syntax.
JohnDG Mon 6 Apr 2009
I like the comma. It's a single character and it's already used for list construction in nearly all languages. Plus, like you say, it allows custom collections.
brian Tue 7 Apr 2009
One of the subtle changes I made related to this feature is that now I report a stand alone constructor call as a "Not a statement" error. This will allow the compiler to catch the common case when you forget a comma. The only reason to allow constructors to be stand alone statements is if your ctor has side effects (which seems like something to prevent anyhow).
I also added a compiler check for when you attempt to assign the same variable to itself. This catches the other case it-blocks reveal:
That is actually a really nice error - I've definitely hit that in Java where I do something like this:
cheeser Tue 7 Apr 2009
what about
Is that still legal without the
it
qualifier?tactics Tue 7 Apr 2009
I think a prefix operator might be a good idea. Maybe * instead of <<, which makes it look like a bulleted list.
For multiple add statements on a single line, you could use a single bullet with commas:
brian Tue 7 Apr 2009
The
it
qualifier is only required in the same circumstances asthis
- only when a local variable hides a slot name. So if your case, assumingy
was neither a slot onthis
norit
, then no qualifiers are required. The twist from Java is really that you implicitly scope the slots on bothit
andthis
.I have already implemented using the comma - it actually looks pretty good.