lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

I too have wanted something easier to work with than function() ... end. For
example, let's say I want to write code that will lock a mutex around the
execution of some other code. What I can write in Lua right now is:

    Mutexes.withMutexDo( mutex, function()
        -- do stuff while holding the mutex
    end )

What I would like to write is something more like:

    Mutexes.withMutex( mutex ) do
        -- do stuff while holding the mutex

This avoids the line extending function() and avoids the closing ) after the

[What I really want is:

    Mutexes.withMutex mutex do
        -- do stuff while holding the mutex

But I have no idea what syntactic rule makes that sort of construct work.]

>From an implementation standpoint, the rule might be that a "do" that
appears on the same line as the end of a function call defines a function to
be passed as an extra parameter to the function call. (If one doesn't like
changing the meaning of "do", then consider using something like "begin".)
That convoluted specification is intended to support constructs like:

    profileSection "Section Name" do
        -- do work to be profiled

This sort of construct could also change Lua's module construct such that
modules would have explicit rather than implicit ends:

    module( "MyModuleName" ) do
        -- module guts

In looking a bit at Ruby on Rails, I was appreciating how Ruby's syntax
supports data description by allowing one to execute code in the midst of a
definition which allows for adding multiple fields at once. Using the above
Lua-ish notation:

    ORB.entity "MyEntity" do
        field "myField"
        hasOne{ fieldName = "childName", childType = "ChildType" }

[The do above looks a bit odd and could be an argument for using some other
lexeme, but I don't have a good proposal in that regard. Colon would
probably be my first choice were it not already in use.]

What's nice about the Ruby definitions is that they exploit what amounts to
a change of global environment but it is essentially transparent to coders
unless they look underneath at how the syntax manages to do what it does.

Adding this feature, however, probably opens up a variety of pressure

1. Do these actually work like strings and table declarations with respect
to function calls so that one can write:

    myFunction do
        -- do stuff under the control of myFunction

I haven't done a syntax review, but that still seems tenable.

2. There will be a natural pressure to figure out how to add argument list
support. We could say that one has to fallback to function() to get that or
we probably end up looking at further rules about line breaks so that one
can write:

    myFunction( argument ) do( x ) end

but just as the meaning of do has been transformed, so has the meaning of
the parentheses in this context.

3. This is designed to look like a syntactic construct but note that it
changes the meaning of "return" in that a return inside some do..end blocks
returns from the do..end block and inside some other blocks returns from the
enclosing function. How much of a problem is that in practice? Does the use
of a separate keyword like "begin" solve the problem? Is there pressure
created for non-local returns with the policy that they become invalid upon
exiting the relevant stack frame?

4. It makes creating closures "cheaper" and more invisibly syntactically.
That will probably tend to create pressure to make their actual creation and
destruction cheaper. Generational garbage collection or some form of
reference counting is probably the answer here though I could also see more
constrained support specifically for stack scoped entities.

Finally, my guess is that this isn't something that can be done with token
filters unless one builds in support for the whole grammar.