lua-users home
lua-l archive

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


On 02/06/2021 20:09, Tim Hill wrote:


On Jun 1, 2021, at 11:34 AM, Egor Skriptunoff
<egor.skriptunoff@gmail.com> wrote:

On Tue, Jun 1, 2021 at 5:58 PM Paul Ducklin wrote: local func =
function() ... end ...looks nicer than... local function func() ...
end

It seems there exist two groups of Lua users.

1) First group - users who prefer to emphasize that Lua functions
as just regular objects. The "natural inclination" of 1nd group
users is to use the "function" keyword for producing R-values
only. They would be happy with named-functions-syntax completely
removed from Lua (despite the small problem with local recursive
functions).

2) Second group - users who prefer to write Lua scripts in a way
similar to programming in other languages. The "natural
inclination" of 2nd group users is to always see a function's name
after the keyword "function". From their point of view the existing
Lua syntax for defining local and global functions is nice. But
when they try to define a function inside an object they are forced
to use incongruous "name=function" syntax. Mixing the two styles in
one Lua program is ugly.


I don’t understand the “problem” you are trying to solve

The problem is: the users from 1st and 2nd groups do not have
"equal rights". The former are quite happy in the current Lua, they
can always follow their favorite "all-functions-are-anonymous"
style. The latter are unable to always follow their favorite
"each-function-is-defined-with-a-name" style.

Please note that most Lua newcomers are in the second group.


But the “conventional” function definition syntax is syntactic sugar
to ease beginners into Lua. By the time they are doing advanced
things like tables of functions, they *should* be aware of first
class functions, and in that case the existing syntax *is* the more
natural way to go.

Almost everything that is deeper in Lua is based around first-class
functions .. I dont think postponing people having to grasp this is a
good thing, once they get beyond the basics.


I completely agree. IMO syntactic sugar is really useful if:

- It captures very common patterns, thus allowing *substantially* reducing *complex* (i.e. difficult to read/understand at a glance) boilerplate code.

- It is expressed in a non-confusing syntax that minimizes the risks of ambiguities.

- It is general enough to be widely applicable in many contexts with the same semantics.

- It doesn't obscures fundamental language concepts.
"Dont' fight the language, embrace it": if you keep wanting to write something in Lua the way you are accustomed in another language, maybe you haven't embraced Lua (or any new language you are learning) enough.

OTOH, sugar shouldn't be something that:

- Just covers corner cases or scenarios for limited applications/domains.

- Just saves you a little bit of extra typing.

- Adds visual clutter and "ambiguity": even if it is not a real language ambiguity, human brain doesn't process text in the same way as a parser does, so introducing non-language-ambiguous "sugar" could still result in constructs that are difficult or confusing to parse by humans when scanning code visually.


I agree with the earlier post, its far too easy to mistake { function
a() … end } for { function() .. end }, and this is a bad thing imho.


Yep!

One of the big hurdle in understanding Lua is understanding that functions are basically anonymous entities, i.e. values.

This sometimes is inconvenient, since we all want some functions to be named. The error message systems goes a long way to infer the "name" of an offending function, but still this is "sugar" atop the "nameless function/closure" concept.

The sugar

function f() ... end

at chunk level is useful because it captures an extremely common pattern: the "named function" pattern (and reduce clutter for recursive functions as well).

Inside table ctors it would be confusing because tables hold key-value pairs, so there `f = function()...end is really what you want. The pattern is clearly "the function is a nameless value".

The proposed syntax has very few advantages and a big potential for confusion. By the time you are building tables with function values frequently, you should be well beyond "Lua beginner"-level, so you should well grasp the "function is a value" concept and not be confused any longer by the current syntax.

Moreover, Egor proposed this syntax to simplify metatable definitions, but I respectfully disagree it would be a real simplification.

In fact this would benefit only *short* metatables ctors or ctors with many very short functions (i.e. almost one-liners).

For MTs with longer function definitions, it is really better, IMHO, to use the pattern:

MT = {}
MT.a = function()... end

or

function MT.a()... end


because otherwise you end up with the braces of the ctor being spaced hundreds of LOCs apart, which is terrible when reading code.

Compare:

MT = {

  function a()

  -- ... lots of LOCs ...

  end,  -- very hard to spot comma
  -- ... a dozen more function definitions with 50 LOCs bodies

  function z()
  -- ... more LOCs..
  end
}

The closing brace is many editor screens away from the opening brace, and when looking at the intermediate function definitions you have no indication you are examining functions inside a table, even if you look at their "name", because the braces are not visible and the only hint is an added level of indentation.


—Tim


-- Lorenzo