[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Another example for syntactically lightweight closures
- From: Mark Hamburg <mhamburg@...>
- Date: Tue, 05 Feb 2008 00:38:10 -0800
on 2/4/08 10:53 AM, David Given at dg@cowlark.com wrote:
> Mark Hamburg wrote:
> [...]
>> unwind_protect( io.close, f ) do
>> print( f:read( "*a" ) )
>> end
>
> That's ambiguous --- the compiler can't distinguish this from:
>
> unwing_protect(io.close, f);
> do
> print(f:read("*a"));
> end;
>
> OTOH it would be nice to have some way of avoiding the ugly end) after a
> function closure in a parameter list.
It wouldn't be the first time that Lua made a distinction based on line
breaks.
As for the arguments issue, one could treat a left parenthesis following the
do on the same line as introducing an argument list.
But yes, this does all get tricky. Basically, it ends up saying if we're on
a line where we could expect another expression as a function argument and
we see a "do" then treat it as starting a function.
That said, I rather like the # function notation proposed by Jean-Claude and
could see some variation on it being a better approach. My experiments just
now with abusing the arithmetic operators took me a while to figure out why
they wouldn't compile -- statements aren't expressions. Abusing __newindex
just seems to go too far...
unwind_protect[ function() io.close( f ) end ] = function()
print( f:read '*a' )
end
This also doesn't support arguments to the cleanup function.
Maybe it would be simpler just to extend the rule that allows parenthesis
free calls of functions with strings and tables to support passing functions
that way as well.
As Miles Bader put it, what I'm essentially looking for is a way to get the
same sort of syntactic extension benefits as Ruby gets out of blocks. What
I'm hoping is that there's some reasonably small extension/change to the Lua
syntax that delivers a big chunk of the common case value of a macro system
without introducing the compile time and linguistic complexity of macros.
And some of this is clearly torn between balancing between people knowing
that they are creating function scopes and not having people get hung up on
the fact that we create a function scope.
In the unwind_protect case, the scope isn't really an issue and a
parenthesis free function call that allowed one to write:
unwind_protect( io.close, f ) function()
print( f:read "*a" )
end
isn't too bad. Scopes with cleanup blocks exits become something like:
scope function()
finally function()
-- cleanup
end
end
For that matter, one can then write:
local success = pcall function()
-- Something that might fail
end
Where this doesn't fit as comfortably is when trying to use it for things
like class construction.
class "Foo" function()
read_write_accessor( "name", "_name" )
end
Most naïve users would seem likely to get hung up on why there's a function
here.
(There's a whole separate analysis to explore what one needs to do to make
these sort of constructs at least moderately straightforward to write. For
example, how does "finally" above find the structures managed by "scope"?)
Mark