Lightweight syntax: a dissident view

classic Classic list List threaded Threaded
115 messages Options
1234 ... 6
Reply | Threaded
Open this post in threaded view
|

Lightweight syntax: a dissident view

Dirk Laurie
What I like about Lua is just the same thing I like about Pascal:
it is immediately readable, especially when syntax highlighted in
a good editor, and you can code in Lua quite rapidly because while
typing long words like 'function' and statements requiring two keywords
like 'if'...'then', your brain is racing ahead.

What puts me off from the current spate of lightweight syntax
proposals is just the same thing I hate about C and Perl: they
are cryptic and the saving in keystrokes now is not worth the
brain pain later.  

The Pascal model has served Lua well so far: keep the language
itself simple and sweet, and put all the power into libraries.

The only lightweight syntax I would be prepared to support is one
that is in Pascal but not in Lua: s[i] == s:sub(i,i) for strings,
not because it saves six characters, but because it enhances
readability.  

Dirk


Reply | Threaded
Open this post in threaded view
|

Re: Lightweight syntax: a dissident view

James Rhodes
With regards to your last note about accessing characters through s[i], you can actually already do this by setting the metatable for all strings; like so:

mt = {}
mt["__index"] = function(str, i)
    if (type(i) == "number") then
        return string.sub(str, i, i)
    else
        return string[i]
    end
end

debug.setmetatable("", mt)

str = "abc"
print(str[2])
print(str:sub(2, 2))

This will output two 'b's.  Just thought you might like to know :)

Regards, James.


On Wed, Nov 24, 2010 at 8:44 PM, Dirk Laurie <[hidden email]> wrote:
What I like about Lua is just the same thing I like about Pascal:
it is immediately readable, especially when syntax highlighted in
a good editor, and you can code in Lua quite rapidly because while
typing long words like 'function' and statements requiring two keywords
like 'if'...'then', your brain is racing ahead.

What puts me off from the current spate of lightweight syntax
proposals is just the same thing I hate about C and Perl: they
are cryptic and the saving in keystrokes now is not worth the
brain pain later.

The Pascal model has served Lua well so far: keep the language
itself simple and sweet, and put all the power into libraries.

The only lightweight syntax I would be prepared to support is one
that is in Pascal but not in Lua: s[i] == s:sub(i,i) for strings,
not because it saves six characters, but because it enhances
readability.

Dirk



Reply | Threaded
Open this post in threaded view
|

Re: Lightweight syntax: a dissident view

steve donovan
On Wed, Nov 24, 2010 at 12:10 PM, James Rhodes
<[hidden email]> wrote:
> With regards to your last note about accessing characters through s[i], you
> can actually already do this by setting the metatable for all strings; like

OK, so the question would be: how much does this slow down regular
method dispatch like s:sub(i,i)?

I'm ambivalent about 'global subclassing' because it can be very cool
for small programs but doesn't play nice with other people's code
(especially if they have decided to override the string metatable for
their own purposes ;))

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Lightweight syntax: a dissident view

Axel Kittenberger
In reply to this post by Dirk Laurie
> What puts me off from the current spate of lightweight syntax
> proposals is just the same thing I hate about C and Perl: they
> are cryptic and the saving in keystrokes now is not worth the
> brain pain later.

If anybody is out to save keystrokes, you are right, this is completly
the wrong track that wrecked so many languages already.

> The only lightweight syntax I would be prepared to support is one
> that is in Pascal but not in Lua: s[i] == s:sub(i,i) for strings,
> not because it saves six characters, but because it enhances
> readability.

Thats exactly what IMHO the light-function-syntax proposals are about,
its about readability. Since if you like to code with a few lambda's
code piles up that might be better readable otherwise. I agree many of
the proposals might make things worse, and I'm not sure about if I
really want my own propals :-) And I only like to discuss about it,
since it is ambigous and not as clear as continue ;-)

But take for example a replacement function for select() call it
selectF, it takes lambdas as arguments so they are only evaluated if
an argument is really selected.

Right now in default Lua this works, but as far i realized it will
evaluate tableB and tableC as well even if select is 1, and thus fail
if they are nil.
select(x, tableA.foo, tableB.foo, tableC.foo)

So we have this:

selectF(x, function() return tableA.foo end, function() return
tableB.foo end, function() return tableC.foo end)

wouldn't these be more readable?  Say,

selectF(x, (<=tableA.foo), (<=tableB.foo), (<=tableC.foo))

or

selectF(x, \(tableA.foo), \(tableB.foo), \(tableC.foo))

?

Reply | Threaded
Open this post in threaded view
|

Re: Lightweight syntax: a dissident view

James Rhodes
In reply to this post by steve donovan
On Wed, Nov 24, 2010 at 9:13 PM, steve donovan <[hidden email]> wrote:
On Wed, Nov 24, 2010 at 12:10 PM, James Rhodes
<[hidden email]> wrote:
> With regards to your last note about accessing characters through s[i], you
> can actually already do this by setting the metatable for all strings; like

OK, so the question would be: how much does this slow down regular
method dispatch like s:sub(i,i)?

No idea, I just got it working in the Lua live demo :P
 
I'm ambivalent about 'global subclassing' because it can be very cool
for small programs but doesn't play nice with other people's code
(especially if they have decided to override the string metatable for
their own purposes ;))

Although not displayed in the code example I posted, you could and probably
should always grab the existing __index metamethod and call that if you can't
or don't want to handle a specific situation (instead of returning string[i]).

That said, I can't see many other uses for __index in the context of string access,
so I doubt you'll see any conflicts.
 
steve d.


Reply | Threaded
Open this post in threaded view
|

Re: Lightweight syntax: a dissident view

Duncan Cross
In reply to this post by James Rhodes
On Wed, Nov 24, 2010 at 10:10 AM, James Rhodes
<[hidden email]> wrote:

> With regards to your last note about accessing characters through s[i], you
> can actually already do this by setting the metatable for all strings; like
> so:
> mt = {}
> mt["__index"] = function(str, i)
>     if (type(i) == "number") then
>         return string.sub(str, i, i)
>     else
>         return string[i]
>     end
> end
> debug.setmetatable("", mt)

This is a bit of a tangent but you can actually do this without
needing to use the debug library - the standard getmetatable() does
work on strings (in a standard Lua setup) so you could do:

 getmetatable("").__index = function(str, i)
   -- (... code ...)
 end

-Duncan

Reply | Threaded
Open this post in threaded view
|

Re: Lightweight syntax: a dissident view

James Rhodes
On Wed, Nov 24, 2010 at 9:24 PM, Duncan Cross <[hidden email]> wrote:
On Wed, Nov 24, 2010 at 10:10 AM, James Rhodes
<[hidden email]> wrote:
> With regards to your last note about accessing characters through s[i], you
> can actually already do this by setting the metatable for all strings; like
> so:
> mt = {}
> mt["__index"] = function(str, i)
>     if (type(i) == "number") then
>         return string.sub(str, i, i)
>     else
>         return string[i]
>     end
> end
> debug.setmetatable("", mt)

This is a bit of a tangent but you can actually do this without
needing to use the debug library - the standard getmetatable() does
work on strings (in a standard Lua setup) so you could do:

 getmetatable("").__index = function(str, i)
  -- (... code ...)
 end

I did try using setmetatable on strings, but I didn't think of just changing the __index value from the result of getmetatable() :P  That is definitely a better solution than using debug.setmetatable.

Regards, James.
Reply | Threaded
Open this post in threaded view
|

Re: Re: Lightweight syntax: a dissident view

Gunnar Zötl
In reply to this post by Dirk Laurie

> selectF(x, function() return tableA.foo end, function() return
> tableB.foo end, function() return tableC.foo end)
>
> wouldn't these be more readable?  Say,
>
> selectF(x, (<=tableA.foo), (<=tableB.foo), (<=tableC.foo))
>
> or
>
> selectF(x, \(tableA.foo), \(tableB.foo), \(tableC.foo))

actually they are all not very readable, but at least in the first version I can readily tell what the code does. ALL of the syntax proposals for lightweight function syntax have one  thing in common: they do look like perl (or APL or other line noise languages). Don't get me wrong, I like perl a lot, and I use it a lot, but I would not want lua to look like perl. This sort of thing works in perl, because its entire syntax is a convoluted and probably nondeterministic mess, but lua syntax is rather clean, eloquent and very readable, so having line noise in there creates a WTF moment... at least for me.

I would consider this entire matter to be a case for something like metalua, not for the core syntax.

Gunnar

Reply | Threaded
Open this post in threaded view
|

Re: Lightweight syntax: a dissident view

steve donovan
In reply to this post by Axel Kittenberger
On Wed, Nov 24, 2010 at 12:14 PM, Axel Kittenberger <[hidden email]> wrote:
> selectF(x, \(tableA.foo), \(tableB.foo), \(tableC.foo))

And there's a similar problem with the current assert;  it always
evaluates the message, which might involve a costly calculation that
by definition only has to be evaluated under exceptional
circumstances.

assertF(condition,\(costly result))

Naturally, any 'short cut' can lead to Perl-ism, but there the answer
is not restricting the language, but encouraging good style. I know
people get overexcited with new features but common sense prevails -
Bjarne Stroustrup gave that advice about C++, don't try to use it all
at once.

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Re: Lightweight syntax: a dissident view

steve donovan
In reply to this post by Gunnar Zötl
On Wed, Nov 24, 2010 at 12:31 PM, Gunnar Zötl <[hidden email]> wrote:
> I would consider this entire matter to be a case for something like metalua, not for the core syntax.

and there the syntax is |x| x+1, etc.

Fair enough; is the problem here that we are using strange symbols?
Would an explicit lambda keyword help?

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Re: Lightweight syntax: a dissident view

Juris Kalnins
On Wed, 24 Nov 2010 12:35:00 +0200, steve donovan  
<[hidden email]> wrote:

> Fair enough; is the problem here that we are using strange symbols?
> Would an explicit lambda keyword help?

Existing 'return' keyword is good enough:

s:gsub("_(%l)", return ...:upper())

Reply | Threaded
Open this post in threaded view
|

Re: Lightweight syntax: a dissident view

Pierre-Yves Gérardy
In reply to this post by Dirk Laurie
On Wed, Nov 24, 2010 at 10:44, Dirk Laurie <[hidden email]> wrote:
> What puts me off from the current spate of lightweight syntax
> proposals is just the same thing I hate about C and Perl: they
> are cryptic and the saving in keystrokes now is not worth the
> brain pain later.

It's not about keystrokes, but about readability, actually.

The first part of a function literal looks like a function call, and,
for short functions, the `(function( ... ) ... end)` overweights the
content of the function.

In functional or callback heavy code, it really breaks readability.

All the proposed syntaxes depart from the keyword-based syntax, it's
true. It's hard to find a good syntax (one that doesn't generate too
much line noise) for short functions with the current parsing strategy
which isn't going out any time soon.

> The Pascal model has served Lua well so far: keep the language
> itself simple and sweet, and put all the power into libraries.

Adding another syntax for function could be seen as bloat, and
replacing the current syntax for function expressions (not for
statements) would probably result in an outcry on the list.

The Lua authors remain conspicuously silent on the matter. They care a
lot about the look and feel of the language, and the programming
styles that its features enable.

However, they seem to be ambivalent on functions. Their semantics and
implementation is excellent (first class, lexical scope with closure,
tail call elimination) and invite to write functional code, yet the
syntax makes it look like mud.

The aesthetics discussion on the list is a matter of bikeshedding.
I've been trying a slew of different legal syntaxes in order to find
one that doesn't suck too much (legal, unambiguous, distinctive, and
as simple as possible yet as versatile as the long syntax) for the use
cases described above. My favourite one so far is a combination of

    @ [arglist] `(` [explist] `)`
and
    @ [arglist] `[` {statements} => [explist] `]`
or perhaps
    @ [arglist] do {statements} return [explist] end

Other, equivalent or more restrictive ones have been proposed, and as
I said before, its a matter of taste. I don't think we'll get a
consensus on the list on a given syntax.

Kind regards,
-- Pierre-Yves

Reply | Threaded
Open this post in threaded view
|

Re: Lightweight syntax: a dissident view

Axel Kittenberger
>@ [arglist] do {statements} return [explist] end
I'm against this one, as this one saves hardly anything compared to this:
>function(arglist) {statements} return [explist] end

Reply | Threaded
Open this post in threaded view
|

Re: Lightweight syntax: a dissident view

steve donovan
On Wed, Nov 24, 2010 at 1:23 PM, Axel Kittenberger <[hidden email]> wrote:
>>@ [arglist] do {statements} return [explist] end
> I'm against this one, as this one saves hardly anything compared to this:
>>function(arglist) {statements} return [explist] end

Yes, I think it's unnecessary and weird.  Somehow I don't like these
@, they seem to shout out and say 'preprocessor!' to me.

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Lightweight syntax: a dissident view

Gunnar Zötl
In reply to this post by Dirk Laurie

> On Wed, Nov 24, 2010 at 12:31 PM, Gunnar Zötl <[hidden email]> wrote:
> > I would consider this entire matter to be a case for something like
> metalua, not for the core syntax.
>
> and there the syntax is |x| x+1, etc.
>
> Fair enough; is the problem here that we are using strange symbols?

in a way... yes. For me, it is about consistency. I do see the problem people are trying to tackle here, but I fear all solutions proposed so far open an entirely different can of worms.

> Would an explicit lambda keyword help?

not sure. What yould be the semantics of this? A lambda defining a one-expression function? Because, if you go

lambda(x) do something_with(x) end

that really is not shorter or more concise than function(x) something_with(x) end... but in the case of a one expression function, you would have to think about multiple value returns and stuff, probably resulting in an end delimiter for the lambda statement, which for consistencys sake should be end, in which case nothing is really won, or lambdas only being able to return one value, which would be somewhat weird.

I dunno, I think it would be a proper start to determine what is actually wanted here. There seem to be two major use cases that keep coming up, one being delayed evaluation as illustrated in a previous post, and one being the ability to define function arguments to other functions in place. Maybe they should be tackled separately.

To be honest, I haven't given this matter the necessary bit of thought, because I think it will go away, as usual ;) I ignored the thread until the "dissident" view came along, which, in my opinion, is probably not all that dissident. But, having kinda joined in now, some sort of excuse for a proposal from me might be to actually implement some form of delayed evaluation, and leave function definition as it is. I kinda like the delayed evaluation thing, but I still think short function definitiion things, at least as proposed so far, should not be part of the core syntax. Yes, because they're ugly.

Gunnar


Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Lightweight syntax: a dissident view

steve donovan
On Wed, Nov 24, 2010 at 1:51 PM, Gunnar Zötl <[hidden email]> wrote:
> I dunno, I think it would be a proper start to determine what is actually wanted here. There seem to be two major use cases that keep coming up, one being delayed evaluation as illustrated in a previous post, and one being the ability to define function arguments to other functions in place. Maybe they should be tackled separately.

This is a good point.  One criticism of lightweight syntax (whether
delayed/lazy evaluation or short-form functions) is that there is a
distinct cost in creating closures. I actually think my example would
be bad in practice, because it would generate a lot of closures; I've
heard that Lua 5.2 can optimize closure re-use but this is something
to bear in mind.

Personally, I'd settle for a mature version of the token-filter patch
being accepted. Then one can do just about anything (which is probably
the most common criticism ;)) including \x(x+1).

(apart from it being so 1980s etc)

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Lightweight syntax: a dissident view

Luis Carvalho
In reply to this post by Gunnar Zötl
<snip>
> > Would an explicit lambda keyword help?
>
> not sure. What yould be the semantics of this? A lambda defining a one-expression function? Because, if you go
>
> lambda(x) do something_with(x) end
<snip>

Sorry for jumping in late and following the discussion closely, but what about
not allowing statements and having something like below?

lambda `(' [parlist] `)' explist

I think this would cover most of the needs for a lightweight syntax. Taking a
recent snippet from Mark Hamburg, for example:

stream:map(lambda(x) x * x)
      :filter(lambda(x) x % 2 == 0)
      :subscribe(function(x)
        total = total + x
        log:writef("%d %d", x, total)
      end)

Cheers,
Luis

--
Computers are useless. They can only give you answers.
                -- Pablo Picasso

--
Luis Carvalho (Kozure)
lua -e 'print((("[hidden email]"):gsub("(%u+%.)","")))'

Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Re: Lightweight syntax: a dissident view

Gunnar Zötl
In reply to this post by Dirk Laurie

> Personally, I'd settle for a mature version of the token-filter patch
> being accepted. Then one can do just about anything (which is probably
> the most common criticism ;)) including \x(x+1).

I think this might actually be the best solution for the problem at hand... and probably a whole slew of other problems ;) And it would simplify the adaption of lua for all sorts of domain specific stuff. Plus, I'd love to have this :)

> (apart from it being so 1980s etc)

well, it isn't as bad as the haircuts in the 80s... ;)

Gunnar


Reply | Threaded
Open this post in threaded view
|

Re: Re: Lightweight syntax: a dissident view

Pierre-Yves Gérardy
In reply to this post by Gunnar Zötl
On Wed, Nov 24, 2010 at 11:31, Gunnar Zötl <[hidden email]> wrote:
> I would consider this entire matter to be a case for something like metalua, not for the core syntax.

The problem with Metalua is that it is not compatible with LuaJIT2,
nor with any other implementation using its own bytecode.

Is Metalua able to emit Lua source files rather than bytecode? Is it
possible to use it without compiling it to bytecode as well? I've
skimmed the documentation, but I didn't find any pointer about it.

I'll try to write a string.gsub-based source filter and see if I can
get what I want.

-- Pierre-Yves

Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Lightweight syntax: a dissident view

Axel Kittenberger
In reply to this post by Luis Carvalho
> filter(lambda(x) x % 2 == 0)

hmm also some uses not claerly defined, not nice:

myfunc(lambda(x) x, x)

is this:
myfunc(function(x) return x, x end)
or
myfunc(function(x) return x end, x)
?




>      :subscribe(function(x)
>        total = total + x
>        log:writef("%d %d", x, total)
>      end)
>
> Cheers,
> Luis
>
> --
> Computers are useless. They can only give you answers.
>                -- Pablo Picasso
>
> --
> Luis Carvalho (Kozure)
> lua -e 'print((("[hidden email]"):gsub("(%u+%.)","")))'
>
>

1234 ... 6