RFC: "in place" return from imperative function calls

classic Classic list List threaded Threaded
26 messages Options
12
Reply | Threaded
Open this post in threaded view
|

RFC: "in place" return from imperative function calls

Griffin Rock
Proposed ability to 'mark' an argument in an imperative function call to transform it into an assignment statement.
Can be implemented as a purely syntactic translation with no change to the behaviour of the function or interpreter.
Syntax below uses unary '&' like c pointers and c++ reference signatures.

examples of use:
"trim(x, & veryLongName, z)" => "veryLongName = trim(x, veryLongName, z)"
"string.gsub(& line, '%s+', ' ')" => "line = string.gsub(line, '%s+', ' ')"

probably only useful on locals, since you can already "manually" translate
"trim(& veryLongName[complexLValue])" => "zap(trim, veryLongName, complexLValue)"

Criticism welcome.
Reply | Threaded
Open this post in threaded view
|

Re: RFC: "in place" return from imperative function calls

Sean Conner
It was thus said that the Great Griffin Rock once stated:

> Proposed ability to 'mark' an argument in an imperative function call to
> transform it into an assignment statement. Can be implemented as a purely
> syntactic translation with no change to the behaviour of the function or
> interpreter. Syntax below uses unary '&' like c pointers and c++ reference
> signatures.

  '&' is used in Lua 5.3+ as the logical AND operator, so it might be a poor
choice.  Perhaps '@' (the AT symbol) is better.

> examples of use:

> "trim(x, & veryLongName, z)" => "veryLongName = trim(x, veryLongName, z)"
> "string.gsub(& line, '%s+', ' ')" => "line = string.gsub(line, '%s+', ' ')"

        trim(x,@veryLongName,z)
        string.gsub(@line,'%s+',' ')

> probably only useful on locals, since you can already "manually" translate
>
> "trim(& veryLongName[complexLValue])" => "zap(trim, veryLongName, complexLValue)"

  Well, another pain point is

        veryLongNmae[complexLValue] = veryLongName[complexLValue] + 1

so if the intent is to somehow reference these, you could probably extend
the syntax with the following:

        veryLongName = trim(x,@,z)
        line = @:gsub('%s+',' ')
        veryLongName[complexLValue] = @ + 1

This still shows the assignment, which in my book is still important. And
further more:

        veryLongName,complexLValue = @2,@1

where, in this case:

        @1 = veryLongName
        @2 = complexLValue

  I'm not sure if I like it though.  Part of me loves the idea of not having
to type "veryLongName[complexLValue]" several times (avoiding typos), but
the other half of me keeps saying "You hate Perl and it's implicit magic ..."

  -spc

 

Reply | Threaded
Open this post in threaded view
|

Re: RFC: "in place" return from imperative function calls

Philippe Verdy


Le mar. 13 août 2019 à 06:45, Sean Conner <[hidden email]> a écrit :
It was thus said that the Great Griffin Rock once stated:

> Proposed ability to 'mark' an argument in an imperative function call to
> transform it into an assignment statement. Can be implemented as a purely
> syntactic translation with no change to the behaviour of the function or
> interpreter. Syntax below uses unary '&' like c pointers and c++ reference
> signatures.

  '&' is used in Lua 5.3+ as the logical AND operator, so it might be a poor
choice.  Perhaps '@' (the AT symbol) is better.
 
in my opinion using '='  as a unary operator (instead of the normal binary infix operator) would even be better; either as a prefix:
    trim(x, =veryLongName, z)
    string.gsub(=line, '%s+', ' ')
or suffix:
    trim(x, veryLongName=, z)
    string.gsub(line=, '%s+', ' ')

Reply | Threaded
Open this post in threaded view
|

Re: RFC: "in place" return from imperative function calls

Griffin Rock
In reply to this post by Griffin Rock
>     veryLongName = trim(x,@,z)
>     line = @:gsub('%s+',' ')
>     veryLongName[complexLValue] = @ + 1
>
> This still shows the assignment, which in my book is still important.

Agreed - I like your idea better.

> [I] hate Perl and it's implicit magic ...

Same, though I don't think this is much more magic than
the existing method call syntax.
Reply | Threaded
Open this post in threaded view
|

Re: RFC: "in place" return from imperative function calls

Dennis Fischer
In reply to this post by Griffin Rock
Okay, criticism:

1. You don't save much typing
2. It's more syntax to learn
3. It's more logic in the parser
4. It hides assignment operations
5. It goes against how Lua is otherwise designed

The fourth point is probably my biggest problem with the proposal.
In Lua, assignment to variables always looks the same: variable(s) to
the left, equal sign, values to the right.
It's easy to visually parse and makes it clear that the value changes.

Adding a new syntax that assigns a value to a variable seems like a bad
idea to me because it means there's
another syntax structure that you need to scan for when looking for
where a variable is changed.
Even worse is the fact that it's a single character, which is very easy
to miss. Missing one & character
could completely change the meaning of a piece of code.

The fifth point may also need some explaining: I don't think it's a very
"Lua" way of writing code.
It looks a lot like C, in a bad way. Lua has always leaned more towards
the functional side when
it comes to syntax, while allowing imperative code more than encouraging it.
I believe this has worked well because it lets newcomers write codes as
simple sequences of
instructions but directing them towards a more robust coding style as
they dig deeper into the language.
This proposal would have the opposite effect; directing them to more
imperative C-style code,
which eventually would lead to more frustration because a) the code
quality would be worse and b)
they'd hit the limits of the language at a later point, because Lua
still wouldn't be a very good language
for expressing complex logic in an imperative way; but from that point
it would be harder to find back
to a better style that fits the languages strengths.

I do see a similarity with the table:method() syntax here, but while
that one basically makes an entire
programming paradigm (OOP) available to Lua, your proposal would really
just be a very situational thing,
so there's not as much reason for adding it. The trade-off is just not
worth it in this case.

I do see your point and don't believe it's a bad idea per se, I just
don't think there's a strong enough case
for adding it to a language that aims to be as small as possible.

On 13/08/2019 06:11, Griffin Rock wrote:

> Proposed ability to 'mark' an argument in an imperative function call to transform it into an assignment statement.
> Can be implemented as a purely syntactic translation with no change to the behaviour of the function or interpreter.
> Syntax below uses unary '&' like c pointers and c++ reference signatures.
>
> examples of use:
> "trim(x, & veryLongName, z)" => "veryLongName = trim(x, veryLongName, z)"
> "string.gsub(& line, '%s+', ' ')" => "line = string.gsub(line, '%s+', ' ')"
>
> probably only useful on locals, since you can already "manually" translate
> "trim(& veryLongName[complexLValue])" => "zap(trim, veryLongName, complexLValue)"
>
> Criticism welcome.

Reply | Threaded
Open this post in threaded view
|

+= operator

Oliver Schmidt
In reply to this post by Sean Conner

On 13.08.19 06:45, Sean Conner wrote:
> veryLongNmae[complexLValue] = veryLongName[complexLValue] + 1

every time I type the above line, I wish Lua had the += operator. It depends on
the kind of program, but in some use cases (e.g. statistically evaluating large
data files) I need to type this kind of line frequently.

> veryLongName = trim(x,@,z)
> line = @:gsub('%s+',' ')
> veryLongName[complexLValue] = @ + 1
>
> This still shows the assignment, which in my book is still important. And
>   I'm not sure if I like it though.  Part of me loves the idea of not having
> to type "veryLongName[complexLValue]" several times (avoiding typos), but
> the other half of me keeps saying "You hate Perl and it's implicit magic ..."

yes, interesting idea, but I also think that this would be too magic. I would
prefer simple +=. I know from time to time this comes up in this list but I
never understood why Lua does not have +=.

-- Oliver

Reply | Threaded
Open this post in threaded view
|

Re: RFC: "in place" return from imperative function calls

pocomane
In reply to this post by Griffin Rock
On Wed, Aug 14, 2019 at 4:05 AM Griffin Rock <[hidden email]> wrote:
>
> >     veryLongName = trim(x,@,z)
> >     line = @:gsub('%s+',' ')
> >     veryLongName[complexLValue] = @ + 1
> >
> > This still shows the assignment, which in my book is still important.
>
> Agreed - I like your idea better.

Summarizing the proposal to: An `@` on the right side of an assignment
is replaced with the old value of the first variable on the left side.
(Another token instead of `@` can be used).

As you, I also think that it solves several "Ugliness" of the code,
e.g. the long identifier repetition, or the "a = a + 1" lines due to
the absence of "+=" operator.

The only conceptual drawback that I can find is the following. Right
now I can easily recognize the places where a variable is read, but it
could become tricky in lines like `long_name_1 = func( long_name_2,
long_name_3, @, long_name_4 )`.

Moreover, there are the usual criticisms: it is another syntax to
learn, does it worth? Does it introduce too complexity to the parser?
And so on.

Probably we need a patch to give it a try.

Reply | Threaded
Open this post in threaded view
|

Re: RFC: "in place" return from imperative function calls

Soni "They/Them" L.


On 2019-08-14 3:50 p.m., pocomane wrote:

> On Wed, Aug 14, 2019 at 4:05 AM Griffin Rock <[hidden email]> wrote:
> >
> > >     veryLongName = trim(x,@,z)
> > >     line = @:gsub('%s+',' ')
> > >     veryLongName[complexLValue] = @ + 1
> > >
> > > This still shows the assignment, which in my book is still important.
> >
> > Agreed - I like your idea better.
>
> Summarizing the proposal to: An `@` on the right side of an assignment
> is replaced with the old value of the first variable on the left side.
> (Another token instead of `@` can be used).
>
> As you, I also think that it solves several "Ugliness" of the code,
> e.g. the long identifier repetition, or the "a = a + 1" lines due to
> the absence of "+=" operator.
>
> The only conceptual drawback that I can find is the following. Right
> now I can easily recognize the places where a variable is read, but it
> could become tricky in lines like `long_name_1 = func( long_name_2,
> long_name_3, @, long_name_4 )`.
>
> Moreover, there are the usual criticisms: it is another syntax to
> learn, does it worth? Does it introduce too complexity to the parser?
> And so on.
>
> Probably we need a patch to give it a try.
>

how about @self (returns the currently executing function object), @var
(returns the value of the variable being assigned to) and @table
(returns the table being currently constructed)?

(@table would be particularly useful for some DSLs. note that all of
these only affect the local lexical scope and don't work across
modules/function call boundaries.)

Reply | Threaded
Open this post in threaded view
|

Re: += operator

szbnwer@gmail.com
In reply to this post by Oliver Schmidt
hi there! :)

im sure that this had to came up like a 1000 times before, and
actually i dunno the very reason behind not accepting this. i think
its about embedding, size and complexity, maybe also about speed, but
as it is just sugar, only the parsing can put on some extra weight,
and if size matters, then the script size also matters, that is a
valid reason for this idea, even if bytecode can partially(!)
invalidate this reason. however these kinda changes can be solved
without any compatibility issues and anything like that, as this, or
`{}:fun()` or `a<b<c` (fine, that wont always work, like if
non-idempotent function calls there, except if ugly variables comes up
like `local _pre6125314=f() if a<b<_pre6125314 then whatever() end`)
can be achieved with a preprocessor, or even better, some compiler
flags to make them included in lua (for faster parsing during
development) optionally, without making real bloatware (just from the
binary perspective, but embedding have right that perspective).

i think people like these kinda things (to a certain degree and to the
right direction! :D ), and this makes scripting languages popular.
however, on the contrary, there are too much possibilities and there
are preprocessors and forks out there because this very reason... i
think the two real solutions for resolving this is either or both of
gain the lua team over to make the compiler flags become reality, and
a (compatible) preprocessor with options to cherry pick various
options, because some of these could conflict (and cuz speed). so my
idea is something like a fast preprocessor that gets a bunch of
options and a source (that can have a custom file extension) and that
way, compatibility wont get lost, making lua being the next bloatware
wont be our nightmare, compatibility wont go away, and only some
formatting error can come with that, if someone dont wanna use the
original source, but only pure lua, when a script is only available in
its state before it is preprocessed. btw i think i could even like
such a thing around! :)

and finally, as a footnote, making this happen from the side of lua
could ask for some rewriting that can still take away some speed.

bests! :)

Reply | Threaded
Open this post in threaded view
|

Re: += operator

szbnwer@gmail.com
hmm actually too much nasty stuffs could born, like the backslash
notation for lambda functions really hurt my eyes (but no offense!!!),
however things like `+=` and such essentials could go down to lua
level, while other hardcore ugly blackmagic sugar things can still
exists in an external preprocessor, but compatibility is still a thing
that i would like to see in this case. and maybe an another reason is
that accepting such things could start an avalanche (just the way we
can see that in usual :D )

Reply | Threaded
Open this post in threaded view
|

Re: += operator

Michal Kottman
In reply to this post by Oliver Schmidt
On Wed, Aug 14, 2019, 20:32 Oliver <[hidden email]> wrote:

On 13.08.19 06:45, Sean Conner wrote:
>       veryLongNmae[complexLValue] = veryLongName[complexLValue] + 1

every time I type the above line, I wish Lua had the += operator.

See "Compound Assignment Operators (5.2)" in http://lua-users.org/wiki/LuaPowerPatches to try it out.
Reply | Threaded
Open this post in threaded view
|

Re: += operator

Oliver Schmidt
On 15.08.19 08:59, Michal Kottman wrote:
> See "Compound Assignment Operators (5.2)"
> in http://lua-users.org/wiki/LuaPowerPatches to try it out.

These patche demonstrate that it would be possible to have += operator in lua
and that there are others also needing this.

But I still do not understand why this is not included in official lua, since
this is a useful standard feature known from many languages that does IMHO fit
into the lua way of programming, especially because it does not hide assignment
in larger expressions like ++ operator would do. IMHO += is useful for a larger
range of application types that are typical use cases for scripting languages,
e.g. adhoc-quick-and-easy statistical analysis of large data files (log files,
tcpdump etc). Whereas features like <close> are IMHO nice to have features but
are not so often used in typical fire-and-forget scripting use cases, they are
IMHO more frequently used in larger applications that are running a longer time,
e.g. servers. But as I said, all this depends on the type of application, I bet
there are many type of applications where += would seldom be useful.

-- Oliver

Reply | Threaded
Open this post in threaded view
|

append to list operator

Oliver Schmidt
In reply to this post by Sean Conner
On 13.08.19 06:45, Sean Conner wrote:
>   Well, another pain point is
> veryLongNmae[complexLValue] = veryLongName[complexLValue] + 1

a similar and common use case is appending an element to an array: it's also
painful to write:

        complexLValue[#complexLValue + 1] = newElement;

One can circumvent this by having a append function:

        append(complexLValue, newElement);

but this makes the assignment not as visible as the first approach does.

A solution for current official lua with explicit assignment:

        local list = complexLValue; list[#list + 1] = newElement;

Can this be rewritten using the imaginary @ operator?

        complexLValue[#@ + 1] = newElement;

Now the @ would be on the left side of the assignment, this looks weird.

-- Oliver

Reply | Threaded
Open this post in threaded view
|

Re: append to list operator

Sean Conner
It was thus said that the Great Oliver once stated:

> On 13.08.19 06:45, Sean Conner wrote:
> >   Well, another pain point is
> > veryLongNmae[complexLValue] = veryLongName[complexLValue] + 1
>
> a similar and common use case is appending an element to an array: it's also
> painful to write:
>
> complexLValue[#complexLValue + 1] = newElement;
>
> One can circumvent this by having a append function:
>
> append(complexLValue, newElement);
>
> but this makes the assignment not as visible as the first approach does.
>
> A solution for current official lua with explicit assignment:
>
> local list = complexLValue; list[#list + 1] = newElement;
>
> Can this be rewritten using the imaginary @ operator?
>
> complexLValue[#@ + 1] = newElement;
>
> Now the @ would be on the left side of the assignment, this looks weird.

  Well ...

        complexLValue = @[#@ + 1] = newElement

  -spc (Still looks weird ... )

Reply | Threaded
Open this post in threaded view
|

Re: += operator

Scott Morgan
In reply to this post by Oliver Schmidt
On 15/08/2019 08:25, Oliver wrote:
> On 15.08.19 08:59, Michal Kottman wrote:
>> See "Compound Assignment Operators (5.2)"
>> in http://lua-users.org/wiki/LuaPowerPatches to try it out.
>
> These patche demonstrate that it would be possible to have += operator in lua
> and that there are others also needing this.
>

The "RFC: "in place" return from imperative function calls" thread had
an idea that could handle the += requirement and much more:

http://lua-users.org/lists/lua-l/2019-08/msg00088.html

Like Sean there, I'm torn between the handiness of the suggested syntax
sugar and worried about turning the language into an obtuse mess of symbols.

Scott

Reply | Threaded
Open this post in threaded view
|

chained assignment

Oliver Schmidt
In reply to this post by Sean Conner
On 15.08.19 10:04, Sean Conner wrote:
>   Well ...
> complexLValue = @[#@ + 1] = newElement
>   -spc (Still looks weird ... )

yes looks weird, but this reminds my of another interesting and possible common
use case:

Chained assignment:
        a = b = c = expression;
would be equivalent to:
        local e = expression; a=e; b=e; c=e;

This would not imply that x = y is an expression. The chained assignment
statement would be a generalized case of normal assignment statement.

Example:
        local x =  complexLValue[y]
        if not x then
                x = {}
                complexLValue[y] = x
        end
        -- ... continue operating on x ...

With chained assignment:

                x = complexLValue[y] = {}

However this would only save one line in the above example.

-- Oliver

Reply | Threaded
Open this post in threaded view
|

Re: append to list operator

Sean Conner
In reply to this post by Sean Conner
It was thus said that the Great Sean Conner once stated:

> It was thus said that the Great Oliver once stated:
> > Can this be rewritten using the imaginary @ operator?
> >
> > complexLValue[#@ + 1] = newElement;
> >
> > Now the @ would be on the left side of the assignment, this looks weird.
>
>   Well ...
>
> complexLValue = @[#@ + 1] = newElement

  And that wouldn't work.  I'd say "What was I thinking?" but I actually
know what I was thinking when I wrote the above.  

  I initially started to reply by stating one could just as easily use the
__concat metamethod (assuming one had been assigned to complexLValue):

        complexLValue .. newElement

but I realized that wouldn't work, it would have to be:

        complexLValue = complexLValue .. newElement --[1]

which takes us to the proposal under consideration, and I ended up with

        complexLValue = @[#@ + 1] = newElement

which wouldn't work even *if* Lua had this feature.

  -spc (Sigh)

[1] I have written Lua code in the past (emphasis on "the past") that
        did just this, but for userdata, not a table, but the idea still
        stands.

Reply | Threaded
Open this post in threaded view
|

Re: append to list operator

Philippe Verdy
In reply to this post by Oliver Schmidt
It would be simpler to have the very basic syntax  "t[] = newElement" instead of  "t[#t+1] = newElement" ... No need to introduce any "@" (ambiguous in your example) or "#+1".

We could also have "t:append(newElement)", but this could conflict with an existing append() method existing as a member "t.append" in "t", or found by an __index access method in its metatable. Instead the "t[]=value" syntax could be bound to an __append(t,value) method settable in the metatable of tables (allowing that method to determine which new index key to assign, if it should be different from #t+1 by default).




Le jeu. 15 août 2019 à 10:00, Oliver <[hidden email]> a écrit :
On 13.08.19 06:45, Sean Conner wrote:
>   Well, another pain point is
>       veryLongNmae[complexLValue] = veryLongName[complexLValue] + 1

a similar and common use case is appending an element to an array: it's also
painful to write:

        complexLValue[#complexLValue + 1] = newElement;

One can circumvent this by having a append function:

        append(complexLValue, newElement);

but this makes the assignment not as visible as the first approach does.

A solution for current official lua with explicit assignment:

        local list = complexLValue; list[#list + 1] = newElement;

Can this be rewritten using the imaginary @ operator?

        complexLValue[#@ + 1] = newElement;

Now the @ would be on the left side of the assignment, this looks weird.

-- Oliver

Reply | Threaded
Open this post in threaded view
|

Re: append to list operator

Storkman
In reply to this post by Oliver Schmidt


On August 15, 2019 8:00:02 AM UTC, Oliver <[hidden email]> wrote:
>On 13.08.19 06:45, Sean Conner wrote:
>>   Well, another pain point is
>> veryLongNmae[complexLValue] = veryLongName[complexLValue] + 1
>
>a similar and common use case is appending an element to an array: it's
>also
>painful to write:
>
> complexLValue[#complexLValue + 1] = newElement;

You can avoid typing very long names by not having very long names in your program.

You can avoid repeating complex index calculations by storing the index in a variable or, preferably, not having complex index calculations in your program.
--
Storkman

Reply | Threaded
Open this post in threaded view
|

Re: RFC: "in place" return from imperative function calls

Dennis Fischer
In reply to this post by Griffin Rock
This reminds me a lot of the controversial new feature they want to add
in Ruby where [1,2,3].inject{|a,b| a+b} turns into [1,2,3].inject{@1+@2}

I think it's a terrible idea in Ruby, which is already bloated, but
adding a similar thing to Lua seems like an even worse idea.

It looks and feels like some Perlism, will be hard to remember for
people learning the language and doesn't even save you that much typing
in the end.

As much as I hate Javascript and the browser API, I'm going to use it as
a very positive example for naming certain features; while code like
`document.getElementById` is cumbersome to type, it makes it completely
clear what it does. Considering code is usually read more often than it
is written I think it is many times better than esoteric expressions
like jquery or languages like Perl provide. Languages that cater to lazy
programmers who want to type a bit less always end up being hard to read
in the process. Sacrifice maintainability to save maybe a few seconds of
typing per work day. Not a good trade-off if you ask me.

On 14/08/2019 03:30, Griffin Rock wrote:

>>     veryLongName = trim(x,@,z)
>>     line = @:gsub('%s+',' ')
>>     veryLongName[complexLValue] = @ + 1
>>
>> This still shows the assignment, which in my book is still important.
> Agreed - I like your idea better.
>
>> [I] hate Perl and it's implicit magic ...
> Same, though I don't think this is much more magic than
> the existing method call syntax.

12