Closed hikari-no-yume closed 9 years ago
I really like the Coffeescript closure syntax more than Hack's.
If we solved it with a scope change we would need to add some complexity to the AST parser, which wouldn't be too bad but I'd like to stay away from now. Maybe adding some syntax for function calls like that... We'll I'm open to suggestions :stuck_out_tongue:
Should we add context to all functions? Compile functions like Snowscript do? Create a new syntax rule?
I really like this syntax
myClosure = (bar) -> a + bar
myClosure = (bar) -> do
return a + b + bar
end
That works well :)
Main issue is the implicit variable capture.
Yeah I think it's going to have to be
myClosure = (bar) use (a) -> a + bar
myClosure = (bar) use (a, b) -> do
return a + b + bar
end
Maybe.
As for calling variable functions... Certainly a()
would get compiled to a();
. I'd say the simplest solution is add some syntax construct to know when it's supposed to be a regular function call and when a variable function call.
For example, $a()
could get compiled to $a();
. But adding the $
character, might be confusing. Something I thought maybe was doing call(a, "arg1", 2, 3)
and compile that to $a('arg1', 2, 3);
.
Okay I implemented it the hard way in 664073591ec5c334db676fb1b1fc649105e6af80. I added a very simple scope collector/state manager. So now we have access to all assigned variables, and also the ones in the parameters. Just a note: Class attributes cannot be closures, because it would be just silly.
Summing it up, right now you can do
a = () -> 2
a()
b()
And it will compile to
$a = function () { return 2; };
$a();
b();
Awesome :)
Does this do implicit variable capture too? Because with the same infrastructure you can do that.
You mean like adding the variables in the current scope to the closure's use
automatically?
No, just the ones you choose to use, e.g.
a = 3
b = 2
c = (z) -> z + b
which would result in
<?php
$a = 3;
$b = 2;
$c = function ($z) use ($b) { return $z + $b; };
or
a = 3
b = (i) -> (j) -> i + j + a
resulting in
<?php
$a = 3;
$b = function ($i) use ($a) { return function ($j) use ($a, $i) { return $i + $j + $a; }; };
This would work similarly to Hack's lambda functions which have the ==>
syntax:
Ah I see now. I'll give that a shot later today.
Interesting! This was harder than I expected. Mostly because I have to parse a block, and actually see what variables that block uses, and the context that block is run. I implemented a dummy solution in a6d76a98506a39fb1c425b1ee1c1309a55d6135e. If no use
is specified it will just include all the variables defined in the parent context. Will look at this closer eventually. For now I'd like to give the languages some other features such as static methods :)
Moved discussion to #39
Blueberry doesn't support PHP's closures yet, which is a shame, because they're really cool. Perhaps something like the following could work:
We could also clone Hack's
==>
, perhaps just making it->
like CoffeeScript since we don't have the conflict PHP does. It auto-imports referenced variables from surrounding scope:The connected issue is variable functions. In PHP, you can do this:
But in Blueberry, it's currently not possible to do this, since there aren't any sigils. That's really quite a shame. I'm not sure how to solve this.
One approach would be, like CoffeeScript, to change how variables are scoped. If you had earlier declared a variable called
foobar
in your script, then we'd compile the Blueberry codefoobar()
to PHP$foobar()
, but if you hadn't, we'd compile it to PHPfoobar()
. This would mean we'd have to explicitly declare variables global at the top level... which would probably be good thing! That, or get rid of them entirely.Another approach is what Snowscript does, where all function declarations are done as variables. I really don't like that idea, though.