Syntactical ugliness - does it matter?

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

Re: Syntactical ugliness - does it matter?

Dibyendu Majumdar
On Wed, 5 Jun 2019 at 16:02, Paul K <[hidden email]> wrote:
>
> >> local resource x = 5
> > So what you showed appears invalid grammatically ... but the parser allows it?
>
> It's interpreted as `local resource; x = 5`, which is valid.
>

Okay I understand now. Goes to show one never stops learning.
So yes I agree that there is a backward compatibility issue - not
because resource will become a keyword, but because of the way the
parser handles this case.

Thanks and regards
Dibyendu

Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Matthew Wild
In reply to this post by Dibyendu Majumdar
On Wed, 5 Jun 2019 at 15:59, Dibyendu Majumdar <[hidden email]> wrote:

>
> On Wed, 5 Jun 2019 at 15:53, Matthew Wild <[hidden email]> wrote:
> > $ cat resource.lua
> > local resource x = 5
> > print(resource, x)
> >
> > $ lua5.3 resource.lua
> > nil        5
> >
>
> Okay, I am a bit puzzled. The grammar says:
>
> local namelist [‘=’ explist]
>
> namelist ::= Name {‘,’ Name}
>
> So what you showed appears invalid grammatically ... but the parser allows it?

The Lua grammar is not line-based. Usually these two statements would
be written:

```
local resource
x = 5
```

But Lua would also accept it as:

```
local
resource
x
=
5
```

with the exact same semantics. Check luac -l if it helps.

The proposal of how to handle 'resource' as a semi-keyword would
change the meaning of this block of code, however it was written.

Designing language syntax is not trivial :)

Regards,
Matthew

Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Xavier Wang
In reply to this post by Dibyendu Majumdar


Dibyendu Majumdar <[hidden email]> 于2019年6月2日周日 下午11:33写道:
I hate the syntax for the Rust language. It kind of spoils it for me.

Do people find anything ugly about current Lua syntax?
What about the proposed new syntax <toclose> and <const>?

Regards
Dibyendu


I still insist to suggest the colon syntax:

local x: toclose = reosurce

x:anno syntax can used in expressions, just because currently x:anno is not a valid Lua syntax. Lua requires a '(' after Name:

prefixexp ':' Name '('

So, we just do not append a '(' after the name, like this:

local x = a:integer + b:integer

It's invalid in current Lua.

or like this:

(a:integer[])[10]

for multiple annotations, this should works:

local x:toclose:MyClass = MyClass.new()



--
regards,
Xavier Wang.
Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Dibyendu Majumdar
In reply to this post by Matthew Wild
On Wed, 5 Jun 2019 at 16:07, Matthew Wild <[hidden email]> wrote:

> The Lua grammar is not line-based. Usually these two statements would
> be written:
>
> ```
> local resource
> x = 5
> ```
>
> But Lua would also accept it as:
>
> ```
> local
> resource
> x
> =
> 5
> ```
>
> with the exact same semantics. Check luac -l if it helps.
>
> The proposal of how to handle 'resource' as a semi-keyword would
> change the meaning of this block of code, however it was written.
>
> Designing language syntax is not trivial :)
>

You are absolutely right. I am feeling really stupid now. Time to shut up.

Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Hakki Dogusan-3
In reply to this post by Luiz Henrique de Figueiredo
Hi,

On 3.06.2019 14:13, Luiz Henrique de Figueiredo wrote:

>> local const x = 5
>> local toclose f = ...
>
> The only way to make this work is to add reserved words.
> Otherwise, these already have a meaning in Lua. They are equivalent to
>
> local const ; x = 5
> local toclose ; f = ...
>
>

local x = 5
setattribute(x, {const=true}) -- or setattribute(x, "const")
local f = ...
setattribute(f, {toclose=true}) -- or setattribute(f, "toclose")

No change required in syntax, may backward compatible...

Does it work?


--
Regards,
Hakki Dogusan

Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Xavier Wang


Hakki Dogusan <[hidden email]>于2019年6月6日 周四00:19写道:
Hi,

On 3.06.2019 14:13, Luiz Henrique de Figueiredo wrote:
>> local const x = 5
>> local toclose f = ...
>
> The only way to make this work is to add reserved words.
> Otherwise, these already have a meaning in Lua. They are equivalent to
>
> local const ; x = 5
> local toclose ; f = ...
>
>

local x = 5
setattribute(x, {const=true}) -- or setattribute(x, "const")
local f = ...
setattribute(f, {toclose=true}) -- or setattribute(f, "toclose")

No change required in syntax, may backward compatible...

Does it work?


--
Regards,
Hakki Dogusan

No, it doesn’t work. There are attributes for variables, but not for value.

--
regards,
Xavier Wang.
Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Philippe Verdy
In reply to this post by Dibyendu Majumdar


Le mer. 5 juin 2019 à 16:42, Dibyendu Majumdar <[hidden email]> a écrit :
On Wed, 5 Jun 2019 at 15:35, Matthew Wild <[hidden email]> wrote:
>
>   local resource x = foo()
>
> to be interpreted as
>   local <toclose> x = foo()
> or
>   local resource; x = foo()
>

The former as the latter is impossible.
So if you say:

local resource = 0

Then resource is a variable.

But if you say:
local resource x = 0
Then x is a variable, and resource is a qualifier.
No because it is also equivalent to
  local resource
  x = 0
which declares a new variable named "resource" (without an initialiser, so initialized to nil) and then performs an assignment to the variable named "x" in the current scope.
Writing it on one line as
  local resource x = 0
does not change things.

Let's remember that ";" separators of statements are already optional in Lua; they are suggested only in some cases where disambiguation is needed (caused by the already permitted currification of function calls):
  print f; (x)(y)[0] = 1
  print f(x); (y)[0] = 1
where you have to wonder what is the meaning of:
   print f(x)(y)[0] = 1
It's true that Lua instructions must either start by a keyword, otherwise they are assignments or function calls; currification without required ";" complicates the separation when there are multiple assignments or function calls. So the ";" was finally introduced (the Lua designer most probably wanted to avoid the ";" need everywhere, but introducing the currified syntax required the addition of ";" to separate ambiguous statements.

Ambiguous statements are not permitted in Lua syntax, or have a mandatory associativity (in a LR parser, normally the parser should should choose the "shift" action instead of "reduce", to favor longer instructions (however the parser can still rollback if needed to retry with a "reduce" action); if it chooses the "reduce" action, it favors smaller instructions but once the reduce action has been performed, the parser can no longer rollback to use a "shift" instead, because "reduce" actions cannot be easily rolled back; rolling back from a "shift" is trivial, it just means pushing back the unprocess tokens in excess to a cache of the token input stream)

Adding the ";" (which remains optional) allows the parser to "reduce" immediately without trying a "shift" and processing a (possibly infinite) stream, which it will do by default. And no rollback is ever needed. The currification of function calls becomes possible and safe.

Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Philippe Verdy
Note: this is exactly the same problem as in the syntax of Fortran (where it was evern more critical): Fortran had keywords for its instructions or some operators, and also allowed identifiers to have multiple letters; but whitespaces separators between them were optional (to save precious encoding size on punchcards...). This had a consequence: a very slow parser, very complex to write and maintain (even if the compiler produced a very fast program). Novel dialects of Fortran disallowed this practice of optional whitespaces between keywords and/or identifiers, forcing to use whitespaces everywhere it would create an ambiguity.

The Lua syntax is normally made to be parsed very esasily and efficiently with minimal code, so having to use rollbacks from a previous "shift" attempt to retry with a "reduce" was disallowed by design. This simplifies a lot the treatment of syntax error in the input, and requires simpler data structures if it does not have to maintain the possibility of rolling back.
As a consequence, we have a ";" in Lua, and we must use it everytime there's a possible ambiguity.

As well, Lua does not support "f(x=0)" because of currification, and then chosed to sacrifice the possibility of performing assignments in the middle of expressions.
C/C++/Java do not have currification, they still have ";" needed between statements but not always at end of them (if the statement is terminated by a "}" at end of a block), so they can have assignments in the middle of expressions (which can be statements by themselves like in Lua).

Lua could have chosen to use a keyword (like "void") to start a statement performing a function call without assigning its return value(s) in an assignment statement, this would also have solved the ambiguity of currified function calls. But it preferred to use ";" when needed (following the common pratice and because it was just simpler to type and read).

Lua also allowed parentheses around parameters of function to be discarded. But with currification it would have been even more problematic to disambiguite things without rolling back, if there was no ";" or "void" keyword before the next instruction. Still Lua is ambiguous about the parentheses surrounding the function parameters: it chooses to favor the "shift" action (and then parses the first opening parenthese after any leading subexpression, as meaning it marks a function call and not parentheses surrounding an expression (the disambiguation is then needed when expressions are used in list of expressions for table initialisers or for fuinction parameters; Lua solved the problem by requiring a "," between expressions as as members an initializer list for a table, or expressions given as function parameters).




Le mer. 5 juin 2019 à 21:47, Philippe Verdy <[hidden email]> a écrit :


Le mer. 5 juin 2019 à 16:42, Dibyendu Majumdar <[hidden email]> a écrit :
On Wed, 5 Jun 2019 at 15:35, Matthew Wild <[hidden email]> wrote:
>
>   local resource x = foo()
>
> to be interpreted as
>   local <toclose> x = foo()
> or
>   local resource; x = foo()
>

The former as the latter is impossible.
So if you say:

local resource = 0

Then resource is a variable.

But if you say:
local resource x = 0
Then x is a variable, and resource is a qualifier.
No because it is also equivalent to
  local resource
  x = 0
which declares a new variable named "resource" (without an initialiser, so initialized to nil) and then performs an assignment to the variable named "x" in the current scope.
Writing it on one line as
  local resource x = 0
does not change things.

Let's remember that ";" separators of statements are already optional in Lua; they are suggested only in some cases where disambiguation is needed (caused by the already permitted currification of function calls):
  print f; (x)(y)[0] = 1
  print f(x); (y)[0] = 1
where you have to wonder what is the meaning of:
   print f(x)(y)[0] = 1
It's true that Lua instructions must either start by a keyword, otherwise they are assignments or function calls; currification without required ";" complicates the separation when there are multiple assignments or function calls. So the ";" was finally introduced (the Lua designer most probably wanted to avoid the ";" need everywhere, but introducing the currified syntax required the addition of ";" to separate ambiguous statements.

Ambiguous statements are not permitted in Lua syntax, or have a mandatory associativity (in a LR parser, normally the parser should should choose the "shift" action instead of "reduce", to favor longer instructions (however the parser can still rollback if needed to retry with a "reduce" action); if it chooses the "reduce" action, it favors smaller instructions but once the reduce action has been performed, the parser can no longer rollback to use a "shift" instead, because "reduce" actions cannot be easily rolled back; rolling back from a "shift" is trivial, it just means pushing back the unprocess tokens in excess to a cache of the token input stream)

Adding the ";" (which remains optional) allows the parser to "reduce" immediately without trying a "shift" and processing a (possibly infinite) stream, which it will do by default. And no rollback is ever needed. The currification of function calls becomes possible and safe.

Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Coda Highland

On Wed, Jun 5, 2019 at 3:16 PM Philippe Verdy <[hidden email]> wrote:
As well, Lua does not support "f(x=0)" because of currification, and then chosed to sacrifice the possibility of performing assignments in the middle of expressions.

That's not why Lua doesn't support it. Lua doesn't support it because assignment is intentionally a statement, not an expression, and function parameters must be expressions. This was a design decision, not a parser simplification -- a way to prevent the "if (x = 0) { ... }" issue that affects C-like languages.

/s/ Adam 
Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Philippe Verdy
The "if(x=0){ ... }" is an "issue" only because the assignment uses the operator "=" which is easily confused with "==" for the equality test.

It was still possible to write the assignment with ":=" (like in Pascal) and still use "==" for the equality test and still not "=" (unlike Pascal), to avoid the second issue with "x=0;" which would have been an expression statement testing x but not using the result.

The final solution was to use ":=" for the assignment, "=" for the equality test, but allow expression statements only after a keyword marking the fact we don't need to store the result, such as "void := x=0;" (needlesss) or "void := f();"; in that case "if(x=0){...}" is correctly performing a test of equality, and "if(x:=0){...}" is an assignment (whose result is false for if so that the block after it is not executed).

That "issue" is not really one, it does not "affect" the langages using "=" and "==". Assignments in the middle of expressions are very useful, and saves lots of lines of code.


Le mer. 5 juin 2019 à 22:28, Coda Highland <[hidden email]> a écrit :

On Wed, Jun 5, 2019 at 3:16 PM Philippe Verdy <[hidden email]> wrote:
As well, Lua does not support "f(x=0)" because of currification, and then chosed to sacrifice the possibility of performing assignments in the middle of expressions.

That's not why Lua doesn't support it. Lua doesn't support it because assignment is intentionally a statement, not an expression, and function parameters must be expressions. This was a design decision, not a parser simplification -- a way to prevent the "if (x = 0) { ... }" issue that affects C-like languages.

/s/ Adam 
Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Coda Highland

On Wed, Jun 5, 2019 at 10:01 PM Philippe Verdy <[hidden email]> wrote:
The "if(x=0){ ... }" is an "issue" only because the assignment uses the operator "=" which is easily confused with "==" for the equality test.

It was still possible to write the assignment with ":=" (like in Pascal) and still use "==" for the equality test and still not "=" (unlike Pascal), to avoid the second issue with "x=0;" which would have been an expression statement testing x but not using the result.

The final solution was to use ":=" for the assignment, "=" for the equality test, but allow expression statements only after a keyword marking the fact we don't need to store the result, such as "void := x=0;" (needlesss) or "void := f();"; in that case "if(x=0){...}" is correctly performing a test of equality, and "if(x:=0){...}" is an assignment (whose result is false for if so that the block after it is not executed).

That "issue" is not really one, it does not "affect" the langages using "=" and "==". Assignments in the middle of expressions are very useful, and saves lots of lines of code.

That's debatable, and it's also irrelevant. I'm not saying this as a direct "this is bad so it shouldn't be allowed" statement. I actually like assignments as expressions.

But what I described is the history of Lua and the rationale that went into it. Is there another way that it could have been addressed? Sure. But that's not the decision that was made.

It's also a debate that has no bearing on the fact that f(x=0) isn't allowed because assignment is a statement, not an expression. The ability to chain function calls has nothing to do with it.

/s/ Adam
Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Philippe Verdy
an expression can be viewed mathematically as needing a "definition" of the subexpressions used. the expression (x=f()) is still an expression that can be used as a subexpression that must be evaluated only once like in (x=f() and x or 0), which cannot be written equivalently as  (x=f() and x=(f) or 0) because f() would be called twice

So we have to break the whole expression in several parts using a prior statement (possibly within a "begin...end"); this seriously complicates the use of chained exclusive branches (with if...elsif... elsif...else...end) that must be written in embedded subblocks to perform intermediate assignments needed for tests.

Not allowing "if(x=0)" is then clearly not an "issue" (and C/C++/Java compilers or IDE's already help programmers detecting it by seeing that it generates a value that is constant, making one branch of the "if" to be never or always taken: they provide easily warnings, and there's a way to write it explicitly so that this is the intended goal of the programmer and not an unexpected bug), and in fact very useful to get clear code without excessive intrication and embedding of subblocks.
This prohibition in Lua does not really make the code more "readable" and "errorproof" (the risk of programming errors is just moved by forcing them to use a syntax  that is even more errorprone). It just makes the code longer than necessary.

But allowing it now in Lua would cause some problems in some existing instructions, including in simple assignments like: "x, y = 0, z = 1" which assigns 0 to x, and the value of (z=1) to y...

And I still think that the following in Lua: "local x = 0, y = 1" is far superior and much more readable than "local x,y = 0,1" which uses "expression lists" to "explode" them from the first one up to the trailing ones kept in a temporary virtual array that is then "virtually" garbage collected ; actually the array is in a closure (itself in the call stack), not in a Lua table, so there's no garbage collection as the sie of the closure is predetermined.

When Lua functions return multiple values, there's no way to call these functions as subexpressions because it will drop the multiple values (except the first one), you have to use a separate assignement instruction to assign multiple variables from the function call. This means that function calls are not really "legit" subexpressions, using a function call as a subexpression transforms the call by silently applying a destructive typecast (that changes the multivalued type into a single-valued type).

The support of expressions in Lua is in fact quite deceptive, inferior to mathematics, as they are not generalized to all types (the multivalued type in Lua is not a real type we can use, it is bound to the source syntax, just like the special expression "..." which is unusable as a subexpression without silently typecasting it to a single-valued type).

This also made the syntax parsing of Lua expressions more tricky than needed (e.g. for parsing table constructors with "{...}", or for assignments like "x,y=..." allowed but not "x,y=...,0").
This forced Lua to treat specially the "expression list" (created syntaxically with ",", or returned by "..."), and not allowing it as an "expression statement".



Le jeu. 6 juin 2019 à 05:08, Coda Highland <[hidden email]> a écrit :

On Wed, Jun 5, 2019 at 10:01 PM Philippe Verdy <[hidden email]> wrote:
The "if(x=0){ ... }" is an "issue" only because the assignment uses the operator "=" which is easily confused with "==" for the equality test.

It was still possible to write the assignment with ":=" (like in Pascal) and still use "==" for the equality test and still not "=" (unlike Pascal), to avoid the second issue with "x=0;" which would have been an expression statement testing x but not using the result.

The final solution was to use ":=" for the assignment, "=" for the equality test, but allow expression statements only after a keyword marking the fact we don't need to store the result, such as "void := x=0;" (needlesss) or "void := f();"; in that case "if(x=0){...}" is correctly performing a test of equality, and "if(x:=0){...}" is an assignment (whose result is false for if so that the block after it is not executed).

That "issue" is not really one, it does not "affect" the langages using "=" and "==". Assignments in the middle of expressions are very useful, and saves lots of lines of code.

That's debatable, and it's also irrelevant. I'm not saying this as a direct "this is bad so it shouldn't be allowed" statement. I actually like assignments as expressions.

But what I described is the history of Lua and the rationale that went into it. Is there another way that it could have been addressed? Sure. But that's not the decision that was made.

It's also a debate that has no bearing on the fact that f(x=0) isn't allowed because assignment is a statement, not an expression. The ability to chain function calls has nothing to do with it.

/s/ Adam
Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Egor Skriptunoff-2
In reply to this post by Xavier Wang
On Wed, Jun 5, 2019 at 6:17 PM Xavier Wang wrote:
So, we just do not append a '(' after the name, like this:
local x = a:integer + b:integer
It's invalid in current Lua.
or like this:
(a:integer[])[10]
for multiple annotations, this should works:
local x:toclose:MyClass = MyClass.new()



How the following should be interpreted:
   local x = a:MyClass(b:MyAnotherClass)
Does it mean
   local x = a.MyClass(a, b)
or
   local x = a(b)
?

 
Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Egor Skriptunoff-2
In reply to this post by Dibyendu Majumdar
On Tue, Jun 4, 2019 at 10:52 PM Dibyendu Majumdar wrote:

Now, the issue with a dynamic language like Lua is that you don't know
the return types of functions because functions are values that may
change over time. Also interoperability with dynamic types requires
you to have the ability to sometimes convert (or assert) a type is a
particular one. When trying to implement this I found that
grammatically it was not simple to do this, unless I used a special
character to introduce the type. So then I chose to use '@' to signify
a cast operator. So you can write:

local n: number = @number math.sqrt(5.0)

The '@number' is a unary operator that binds to the right and asserts
that whatever expression is there can be converted to the required
type. Else an error is raised.





Why do you need additional operator "@number"?
IMO, assignment to a typed variable must check value's type in runtime.
JIT-compiled code may have this check removed if value's type could be proven (by code analysis) to be always correct.
 
Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Xavier Wang
In reply to this post by Egor Skriptunoff-2


Egor Skriptunoff <[hidden email]> 于2019年6月7日周五 下午2:20写道:
On Wed, Jun 5, 2019 at 6:17 PM Xavier Wang wrote:
So, we just do not append a '(' after the name, like this:
local x = a:integer + b:integer
It's invalid in current Lua.
or like this:
(a:integer[])[10]
for multiple annotations, this should works:
local x:toclose:MyClass = MyClass.new()



How the following should be interpreted:
   local x = a:MyClass(b:MyAnotherClass)
Does it mean
   local x = a.MyClass(a, b)
or
   local x = a(b)
?


It should be x = a.MyClass(a, b), and makes an error (because there is no MyClass in a), the correct way to write it:

local x = (a:MyClass)(b:MyAnotherClass)

It's just like "foo":format() is an error, you must write ("foo"):format()

and, you want call a as a function? why you need type annotation in this case?

--
regards,
Xavier Wang.
Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Philippe Verdy
In reply to this post by Egor Skriptunoff-2
The ":" is a binary operator used in expressions, it is bound to a specific function that creates a binding between to object, that binding being a new object that can be used to perform a function call in a special way (which modifies the list of operands by prepending the first parameter of the binding). The ":" can be used between any pair of objects.

Syntactically "a:integer" is just equivalent to a (meta-)function call like "__bind(a, integer)", just like the syntax using "." or "[]" binary operators, which are also equivalent to a (meta-)function calls. And note that "a" and "integer" are just regular identifiers for objects/variables of any type.

Given the extended scope of usage of ":", ".", and "[]", they cannot be reused to mark a new kind of operation or annotation as this will necessarily be ambiguous.

We can reuse ":" or "." ONLY if it does not follow what could be an expression, for example immediately after some specific keywords (for example simple statement keywords like "local" or "return", or keywords starting compound statement constructs like "for", "while", "if", "else", "begin",  "function") or in specific places inside expressions where it cannot have its existing role of binary operator (for example immediately after "(", or after "=" inside assignment/"for" statements).

The same applies to "<" and "*" that have also been proposed to create such annotations: such reuse however limits severely the possibility of inserting annotations within expressions (only possibility left: surround the annotation starting by these "<" or "*" or ":" or "." by placing the whole annotation in parentheses)

So if you want to reuse the ":" for annotations, then it should be unambiguously:
  local x = (:integer)a + (:integer)b
and certainly not:
  local x = a:integer + b:integer

If you want to reuse the "<" or "*" that have also been proposed, it should be:
  local (*toclose) a = expression
  local (<toclose>) a = expression
and not:
  local *toclose a = expression
  local <toclose> a = expression
so that it can be generalized for use even outside the "local" declaration, in statement expressions notably:
  (*toclose) a = expression
  (<toclose>) a = expression
Finaly the proposed syntax using the pair "<" ... ">" is the worst solution.

Why this nightmare ? Can't we just use "@" and completely avoid the parentheses and all ambiguities at the same time, while preserving also the simplicity and efficiency of the syntax parser (no need to implement the complexity of rollbacks, with their additional cost in memory, that are needed to conditionnally resolve the shift/reduce conflicts by two successive retries) ?


Le ven. 7 juin 2019 à 08:20, Egor Skriptunoff <[hidden email]> a écrit :
On Wed, Jun 5, 2019 at 6:17 PM Xavier Wang wrote:
So, we just do not append a '(' after the name, like this:
local x = a:integer + b:integer
It's invalid in current Lua.
or like this:
(a:integer[])[10]
for multiple annotations, this should works:
local x:toclose:MyClass = MyClass.new()



How the following should be interpreted:
   local x = a:MyClass(b:MyAnotherClass)
Does it mean
   local x = a.MyClass(a, b)
or
   local x = a(b)
?

 
Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Coda Highland
On Fri, Jun 7, 2019 at 3:02 AM Philippe Verdy <[hidden email]> wrote:
The ":" is a binary operator used in expressions, it is bound to a specific function that creates a binding between to object, that binding being a new object that can be used to perform a function call in a special way (which modifies the list of operands by prepending the first parameter of the binding). The ":" can be used between any pair of objects.


No, that's not true. That's how it works in Python, but in Lua it is NOT a binary operator but rather a part of a ternary function call operator.

There have been who-knows-how-many discussions in MAKING it a binary operator that creates a binding, but none of them have ever gained traction.

/s/ Adam 
Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Egor Skriptunoff-2
In reply to this post by Xavier Wang
On Fri, Jun 7, 2019 at 10:26 AM Xavier Wang wrote:

It should be x = a.MyClass(a, b), and makes an error (because there is no MyClass in a), the correct way to write it:
local x = (a:MyClass)(b:MyAnotherClass)
It's just like "foo":format() is an error, you must write ("foo"):format()
and, you want call a as a function? why you need type annotation in this case?



 Because it's a common practice to construct a new instance by invoking its class having __call metamethod.
   local inst = Class()
is often the same as
   local inst = Class.new()

Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Philippe Verdy
In reply to this post by Coda Highland
Le ven. 7 juin 2019 à 17:56, Coda Highland <[hidden email]> a écrit :
On Fri, Jun 7, 2019 at 3:02 AM Philippe Verdy <[hidden email]> wrote:
The ":" is a binary operator used in expressions, it is bound to a specific function that creates a binding between to object, that binding being a new object that can be used to perform a function call in a special way (which modifies the list of operands by prepending the first parameter of the binding). The ":" can be used between any pair of objects.


No, that's not true. That's how it works in Python, but in Lua it is NOT a binary operator but rather a part of a ternary function call operator.

But when you parse it, that's what happens: you have to take care of the associativity.

It's just that for now there are additional limitations on the second operand (which can only be a single identifier, limiting its usability, much like "." is limited unless rewritten as "[string expression]". The third operand(s) (with or without parentheses around them) do not play any syntaxic role for recognizing ":".

And I don't know if there's any future plan to allow the syntax "a:[string expression]()" or allow "a:b" alone or "a:[string expression]()" to be a new "functor" object type, i.e. without opening parentheses after it, to generalize the concept of function calls. Arbitrary example showing all cases of use:

   local functor = a:max or a
   x = functor() + functor c + functor(c + 1, x -2)

But that's not what I propose. I'm just limiting myself to the syntactic role (binary associativity) only, rather than semantic (only operators in expressions) which just comes next.

Reply | Threaded
Open this post in threaded view
|

Re: Syntactical ugliness - does it matter?

Jim-2
In reply to this post by Rodrigo Azevedo
03.06.2019, 13:43, "Rodrigo Azevedo" <[hidden email]>:
> Alternative, we can __band them:
> local & constant = 5
> local & catched = 10 -- alternative name, because all 'local' are
> lexically 'scoped' and 'toclose' is ugly.

why "&" ? it is already used for bitwise AND. what about "$" ?


1234