[Proposal] Extend no-parenthesis notation to variables

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

[Proposal] Extend no-parenthesis notation to variables

Mattia Maldini
Hello everyone,
I started using Lua for fun and was amazed by the huge flexibility such a simple language allows.
I am writing here to possibly push a suggestion. For function calls with a single argument Lua allows to omit the parenthesis if the argument is a string. Would it be possible to extend this notation to variables as well?

I'm proposing this because I have a soft spot for functional programming notation (Haskell, Elm,...). I know Lua only allows the first (string) argument to be passed this way, but it is easy to natively implement partial functions that extend this notation to the full list:


```
local function arraycat(t1, t2)
    for i = 1, #t2 do t1[#t1 + 1] = t2[i] end
    return t1
end

local function intermediatefun(params, nargs, fun)
    local parameters = params
    return function(...)
        local arg = {...}
        parameters = arraycat(parameters, arg)
        if #parameters >= nargs then
            return fun(unpack(parameters))
        else
            return intermediatefun(parameters, nargs, fun)
        end
    end
end

-- makes a function that accepts partial arguments (i.e. passing a first argument returns
-- another function with the fixed first argument)
function letfun(nargs, fun)
    return function(...)
        local arg = {...}
        if #arg >= nargs then
            return fun(unpack(arg))
        else
            return intermediatefun(arg, nargs, fun)
        end

    end
end

concat = letfun(3, function(x, y, z)
    return x .. y .. z
end)

print(concat "hello" " Lua" " world")  
```

With this code I can almost achieve what I'm looking for, and I can invoke a function with a space-separated list of strings. I really wish I could do the same with regular variables.
Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

Sergey Kovalev
I think you could achieve the same behaviour easier:

function concat(s)
    return setmetatable({s},{
        __call=function(t,s) table.insert(t,s) return t end,
        __tostring=function(t) return table.concat(t," ") end
    })
end

print( concat "a" "b" "c" )

вс, 20 окт. 2019 г. в 18:16, Mattia Maldini <[hidden email]>:

>
> Hello everyone,
> I started using Lua for fun and was amazed by the huge flexibility such a simple language allows.
> I am writing here to possibly push a suggestion. For function calls with a single argument Lua allows to omit the parenthesis if the argument is a string. Would it be possible to extend this notation to variables as well?
>
> I'm proposing this because I have a soft spot for functional programming notation (Haskell, Elm,...). I know Lua only allows the first (string) argument to be passed this way, but it is easy to natively implement partial functions that extend this notation to the full list:
>
>
> ```
> local function arraycat(t1, t2)
>     for i = 1, #t2 do t1[#t1 + 1] = t2[i] end
>     return t1
> end
>
> local function intermediatefun(params, nargs, fun)
>     local parameters = params
>     return function(...)
>         local arg = {...}
>         parameters = arraycat(parameters, arg)
>         if #parameters >= nargs then
>             return fun(unpack(parameters))
>         else
>             return intermediatefun(parameters, nargs, fun)
>         end
>     end
> end
>
> -- makes a function that accepts partial arguments (i.e. passing a first argument returns
> -- another function with the fixed first argument)
> function letfun(nargs, fun)
>     return function(...)
>         local arg = {...}
>         if #arg >= nargs then
>             return fun(unpack(arg))
>         else
>             return intermediatefun(arg, nargs, fun)
>         end
>
>     end
> end
>
> concat = letfun(3, function(x, y, z)
>     return x .. y .. z
> end)
>
> print(concat "hello" " Lua" " world")
> ```
>
> With this code I can almost achieve what I'm looking for, and I can invoke a function with a space-separated list of strings. I really wish I could do the same with regular variables.

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

Mattia Maldini
> I think you could achieve the same behaviour easier:
Yes, but only in the specific case of string concatenation; my idea is to have all generic functions with partial argument invocation and space-separated variable parameters.

I used a concat implementation as an example only because Lua allows me to do it with string arguments. I could not use the same syntax if the strings were in variable form.

Il giorno dom 20 ott 2019 alle ore 17:53 Sergey Kovalev <[hidden email]> ha scritto:
I think you could achieve the same behaviour easier:

function concat(s)
    return setmetatable({s},{
        __call=function(t,s) table.insert(t,s) return t end,
        __tostring=function(t) return table.concat(t," ") end
    })
end

print( concat "a" "b" "c" )

вс, 20 окт. 2019 г. в 18:16, Mattia Maldini <[hidden email]>:
>
> Hello everyone,
> I started using Lua for fun and was amazed by the huge flexibility such a simple language allows.
> I am writing here to possibly push a suggestion. For function calls with a single argument Lua allows to omit the parenthesis if the argument is a string. Would it be possible to extend this notation to variables as well?
>
> I'm proposing this because I have a soft spot for functional programming notation (Haskell, Elm,...). I know Lua only allows the first (string) argument to be passed this way, but it is easy to natively implement partial functions that extend this notation to the full list:
>
>
> ```
> local function arraycat(t1, t2)
>     for i = 1, #t2 do t1[#t1 + 1] = t2[i] end
>     return t1
> end
>
> local function intermediatefun(params, nargs, fun)
>     local parameters = params
>     return function(...)
>         local arg = {...}
>         parameters = arraycat(parameters, arg)
>         if #parameters >= nargs then
>             return fun(unpack(parameters))
>         else
>             return intermediatefun(parameters, nargs, fun)
>         end
>     end
> end
>
> -- makes a function that accepts partial arguments (i.e. passing a first argument returns
> -- another function with the fixed first argument)
> function letfun(nargs, fun)
>     return function(...)
>         local arg = {...}
>         if #arg >= nargs then
>             return fun(unpack(arg))
>         else
>             return intermediatefun(arg, nargs, fun)
>         end
>
>     end
> end
>
> concat = letfun(3, function(x, y, z)
>     return x .. y .. z
> end)
>
> print(concat "hello" " Lua" " world")
> ```
>
> With this code I can almost achieve what I'm looking for, and I can invoke a function with a space-separated list of strings. I really wish I could do the same with regular variables.

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

Jonathan Goble
On Sun, Oct 20, 2019 at 12:03 PM Mattia Maldini
<[hidden email]> wrote:
>
> > I think you could achieve the same behaviour easier:
> Yes, but only in the specific case of string concatenation; my idea is to have all generic functions with partial argument invocation and space-separated variable parameters.

The problem is that functions are first-class values, and any object
can be callable if its metatable has a __call metamethod.

So what does this do?

x = var1 var2 var3 var4

Does that become var1(var2, var3, var4), var1(var2(var3, var4)),
var1(var2, var3(var4)), var1(var2(var3), var4), or
var1(var2(var3(var4)))? Remember that passing a function as an
argument to another function is perfectly valid and in many cases
desirable, and anything can be callable.

There's too much ambiguity here for what you want.

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

Philippe Verdy
In reply to this post by Mattia Maldini
if you mean parameters using expressions surrounded by parentheses, then how would you parse :
  print(concat (a) (b) (c))
This is basically the same problem, not limited to string constants.

Le dim. 20 oct. 2019 à 18:03, Mattia Maldini <[hidden email]> a écrit :
> I think you could achieve the same behaviour easier:
Yes, but only in the specific case of string concatenation; my idea is to have all generic functions with partial argument invocation and space-separated variable parameters.

I used a concat implementation as an example only because Lua allows me to do it with string arguments. I could not use the same syntax if the strings were in variable form.

Il giorno dom 20 ott 2019 alle ore 17:53 Sergey Kovalev <[hidden email]> ha scritto:
I think you could achieve the same behaviour easier:

function concat(s)
    return setmetatable({s},{
        __call=function(t,s) table.insert(t,s) return t end,
        __tostring=function(t) return table.concat(t," ") end
    })
end

print( concat "a" "b" "c" )

вс, 20 окт. 2019 г. в 18:16, Mattia Maldini <[hidden email]>:
>
> Hello everyone,
> I started using Lua for fun and was amazed by the huge flexibility such a simple language allows.
> I am writing here to possibly push a suggestion. For function calls with a single argument Lua allows to omit the parenthesis if the argument is a string. Would it be possible to extend this notation to variables as well?
>
> I'm proposing this because I have a soft spot for functional programming notation (Haskell, Elm,...). I know Lua only allows the first (string) argument to be passed this way, but it is easy to natively implement partial functions that extend this notation to the full list:
>
>
> ```
> local function arraycat(t1, t2)
>     for i = 1, #t2 do t1[#t1 + 1] = t2[i] end
>     return t1
> end
>
> local function intermediatefun(params, nargs, fun)
>     local parameters = params
>     return function(...)
>         local arg = {...}
>         parameters = arraycat(parameters, arg)
>         if #parameters >= nargs then
>             return fun(unpack(parameters))
>         else
>             return intermediatefun(parameters, nargs, fun)
>         end
>     end
> end
>
> -- makes a function that accepts partial arguments (i.e. passing a first argument returns
> -- another function with the fixed first argument)
> function letfun(nargs, fun)
>     return function(...)
>         local arg = {...}
>         if #arg >= nargs then
>             return fun(unpack(arg))
>         else
>             return intermediatefun(arg, nargs, fun)
>         end
>
>     end
> end
>
> concat = letfun(3, function(x, y, z)
>     return x .. y .. z
> end)
>
> print(concat "hello" " Lua" " world")
> ```
>
> With this code I can almost achieve what I'm looking for, and I can invoke a function with a space-separated list of strings. I really wish I could do the same with regular variables.

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

Mattia Maldini
In reply to this post by Jonathan Goble
And that's exactly what I feared (but could not quite pinpoint).
> There's too much ambiguity here for what you want.
You're absolutely right, there is no way to achieve the syntax I was looking for without fundamentally changing how Lua works.
I was hoping for a simple solution since I got so close with strings, but oh well. Thanks for the clarification.

Il giorno dom 20 ott 2019 alle ore 18:20 Jonathan Goble <[hidden email]> ha scritto:
On Sun, Oct 20, 2019 at 12:03 PM Mattia Maldini
<[hidden email]> wrote:
>
> > I think you could achieve the same behaviour easier:
> Yes, but only in the specific case of string concatenation; my idea is to have all generic functions with partial argument invocation and space-separated variable parameters.

The problem is that functions are first-class values, and any object
can be callable if its metatable has a __call metamethod.

So what does this do?

x = var1 var2 var3 var4

Does that become var1(var2, var3, var4), var1(var2(var3, var4)),
var1(var2, var3(var4)), var1(var2(var3), var4), or
var1(var2(var3(var4)))? Remember that passing a function as an
argument to another function is perfectly valid and in many cases
desirable, and anything can be callable.

There's too much ambiguity here for what you want.

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

Philippe Verdy
In reply to this post by Jonathan Goble
I think that :
x = var1 var2 var3 var4 
should parse as:
x = ((var1(var2))(var3))(var4)
i.e. use the curryfied semantics. If you want to designate var1 as the last function to call with its parameter computed from the others, you'd need to use explicit parentheses to separate it from the rest:
x = var1(var2 var3 var4)
i.e. the "__call" semantics should apply only to the first item to follows, allowing only left-to-right evaluation, It's up to the fist item "called" to decide what to return to process another item after it. If what it returns is not "callable", then the other variables would not be used and a type error would be thrown.

The alternative would be to parse it as: x= var1(var2(var3(var4)))
But I think it is much less flexible.


Le dim. 20 oct. 2019 à 18:20, Jonathan Goble <[hidden email]> a écrit :
On Sun, Oct 20, 2019 at 12:03 PM Mattia Maldini
<[hidden email]> wrote:
>
> > I think you could achieve the same behaviour easier:
> Yes, but only in the specific case of string concatenation; my idea is to have all generic functions with partial argument invocation and space-separated variable parameters.

The problem is that functions are first-class values, and any object
can be callable if its metatable has a __call metamethod.

So what does this do?

x = var1 var2 var3 var4

Does that become var1(var2, var3, var4), var1(var2(var3, var4)),
var1(var2, var3(var4)), var1(var2(var3), var4), or
var1(var2(var3(var4)))? Remember that passing a function as an
argument to another function is perfectly valid and in many cases
desirable, and anything can be callable.

There's too much ambiguity here for what you want.

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

Andrew Gierth
In reply to this post by Mattia Maldini
>>>>> "Mattia" == Mattia Maldini <[hidden email]> writes:

 Mattia> Hello everyone,

 Mattia> I am writing here to possibly push a suggestion. For function
 Mattia> calls with a single argument Lua allows to omit the parenthesis
 Mattia> if the argument is a string. Would it be possible to extend
 Mattia> this notation to variables as well?

The biggest problem with this idea is parsing ambiguity with regard to
the start of the next statement. A statement can't start with a string
literal or a table constructor, but it can start with a variable.

--
Andrew.

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

szbnwer@gmail.com
hi there! :)

my suggestion:

dont make a general curry function or anything like that, it would
make all of ur codes only heavier with a thin layer that applies to a
lot of things and that will be called very often... not much, and
sometimes it is necessary, but think speedwise always to not let
urself step onto that path if it can be avoided, cuz they will grow
deep roots into ur projects...

so instead make factories (only) when they are needed, and u can give
it 2 "levels" (the 2 calls) for the most of the purposes, where the
1st level will generate out the specialized target function, cuz the
new one will be used (2nd level) more often and u can save this
generated one, so u just saved a lotsa operations for all the rest of
the uses via memoizing this new prototype function; but with the 1st
level, u can still have any kinda flexibility to write some arguments
instead of new codes! :) (then u will most likely need a naming
convention to generate out some of the variants u wanted :D i know
that... multiple parameters of the 1st level will most likely make it
necessary...) actually i can imagine something with more than 2 levels
but generally this can be fine...

btw even this will be needed too rarely to make too fancy general
stuffs for it, but anyhow never be afraid of making such nasty ideas
real, one day u will be happy even if it will be just the base for
something better... :D except if u really want to make any paradigm
shift for any idea, when u will need probably these kinda language
hacks...

i would also like to suggest to always use the most primitive variant
of the things, so like functions instead of methods, iterators instead
of coroutines, tables instead of trying to hack the varargs or crying
after tuples, arrays, dictionaries, proxy tables and whatever like (no
offense for any1 around! :D ) and one day u will really need these
things that i just told u to avoid, but wait for that day when it will
really come, and the final results will be much more pure and simple,
while u will have a lotsa time to make the best mental model for
everything before u would wire alltogether everything for delayed pain
:D

actually this is just a suggestion, but i know that i really doesnt
belong under the flagship of any specific paradigm, so a lotsa various
paradigms gave me funds for mine and maybe this wont be beneficial if
it is forced, but still, these rules of thumb serve me really nicely,
and i think mostly fixed programming paradigms can also be more or
less paired with these without making mess and any inconvenience by
breaking paradigm rules...

(sorry if i wasnt the clearest in my words, i has 3 days of
partyharding behind my shoulders that i still feel in my bones...)

bests, and have fun! :D

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

Philippe Verdy
Note that I don't like also the existing curryfied syntax of Lua (based only on ambiguous space separators). A "chaining" syntax using an explicit operator is possible and would be preferable without any syntaxic ambiguity.
The alternate would be to have custom syntax parsers in Lua, using an alternate syntax with some prefix. The alternate parser could be shipped or should be pluggable, e.g. with specific string prefixes, which would still be declarable and implementable in pure Lua with a commission interface for custom "loaders". Such thing could be handy for adding custom loaders for Perl-style regexps (internally compiled into Lua patterns by the loader), or parsers for common data formats (e.g. JSON, XML, RDF and binary variants, compressors...) like they also exist in PostScript.

Le mar. 22 oct. 2019 à 12:59, [hidden email] <[hidden email]> a écrit :
hi there! :)

my suggestion:

dont make a general curry function or anything like that, it would
make all of ur codes only heavier with a thin layer that applies to a
lot of things and that will be called very often... not much, and
sometimes it is necessary, but think speedwise always to not let
urself step onto that path if it can be avoided, cuz they will grow
deep roots into ur projects...

so instead make factories (only) when they are needed, and u can give
it 2 "levels" (the 2 calls) for the most of the purposes, where the
1st level will generate out the specialized target function, cuz the
new one will be used (2nd level) more often and u can save this
generated one, so u just saved a lotsa operations for all the rest of
the uses via memoizing this new prototype function; but with the 1st
level, u can still have any kinda flexibility to write some arguments
instead of new codes! :) (then u will most likely need a naming
convention to generate out some of the variants u wanted :D i know
that... multiple parameters of the 1st level will most likely make it
necessary...) actually i can imagine something with more than 2 levels
but generally this can be fine...

btw even this will be needed too rarely to make too fancy general
stuffs for it, but anyhow never be afraid of making such nasty ideas
real, one day u will be happy even if it will be just the base for
something better... :D except if u really want to make any paradigm
shift for any idea, when u will need probably these kinda language
hacks...

i would also like to suggest to always use the most primitive variant
of the things, so like functions instead of methods, iterators instead
of coroutines, tables instead of trying to hack the varargs or crying
after tuples, arrays, dictionaries, proxy tables and whatever like (no
offense for any1 around! :D ) and one day u will really need these
things that i just told u to avoid, but wait for that day when it will
really come, and the final results will be much more pure and simple,
while u will have a lotsa time to make the best mental model for
everything before u would wire alltogether everything for delayed pain
:D

actually this is just a suggestion, but i know that i really doesnt
belong under the flagship of any specific paradigm, so a lotsa various
paradigms gave me funds for mine and maybe this wont be beneficial if
it is forced, but still, these rules of thumb serve me really nicely,
and i think mostly fixed programming paradigms can also be more or
less paired with these without making mess and any inconvenience by
breaking paradigm rules...

(sorry if i wasnt the clearest in my words, i has 3 days of
partyharding behind my shoulders that i still feel in my bones...)

bests, and have fun! :D

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

Soni "They/Them" L.


On 2019-10-22 3:50 p.m., Philippe Verdy wrote:

> Note that I don't like also the existing curryfied syntax of Lua
> (based only on ambiguous space separators). A "chaining" syntax using
> an explicit operator is possible and would be preferable without any
> syntaxic ambiguity.
> The alternate would be to have custom syntax parsers in Lua, using an
> alternate syntax with some prefix. The alternate parser could be
> shipped or should be pluggable, e.g. with specific string prefixes,
> which would still be declarable and implementable in pure Lua with a
> commission interface for custom "loaders". Such thing could be handy
> for adding custom loaders for Perl-style regexps (internally compiled
> into Lua patterns by the loader), or parsers for common data formats
> (e.g. JSON, XML, RDF and binary variants, compressors...) like they
> also exist in PostScript.

In EXP context, but not EXPLIST context, I see no particular reason why
we couldn't do it with variables:

local foo = a b () -- equivalent to "local foo = a; b()"
local foo = (a b ()) -- equivalent to "local foo = a(b)()"

This makes it lisp-like but basically is just a (trivial IMO) bit of
sugar. Basically just tell expr/subexpr/simpleexp/suffixedexp whether
they are in a explist (see lparser.c), and accept names in suffixedexp
if so. Note that you'd still need () in a funcargs - foo(a b ()) would
be illegal syntax and you'd have to use foo((a b ())) instead. anyway,
just an idea.

>
> Le mar. 22 oct. 2019 à 12:59, [hidden email]
> <mailto:[hidden email]> <[hidden email]
> <mailto:[hidden email]>> a écrit :
>
>     hi there! :)
>
>     my suggestion:
>
>     dont make a general curry function or anything like that, it would
>     make all of ur codes only heavier with a thin layer that applies to a
>     lot of things and that will be called very often... not much, and
>     sometimes it is necessary, but think speedwise always to not let
>     urself step onto that path if it can be avoided, cuz they will grow
>     deep roots into ur projects...
>
>     so instead make factories (only) when they are needed, and u can give
>     it 2 "levels" (the 2 calls) for the most of the purposes, where the
>     1st level will generate out the specialized target function, cuz the
>     new one will be used (2nd level) more often and u can save this
>     generated one, so u just saved a lotsa operations for all the rest of
>     the uses via memoizing this new prototype function; but with the 1st
>     level, u can still have any kinda flexibility to write some arguments
>     instead of new codes! :) (then u will most likely need a naming
>     convention to generate out some of the variants u wanted :D i know
>     that... multiple parameters of the 1st level will most likely make it
>     necessary...) actually i can imagine something with more than 2 levels
>     but generally this can be fine...
>
>     btw even this will be needed too rarely to make too fancy general
>     stuffs for it, but anyhow never be afraid of making such nasty ideas
>     real, one day u will be happy even if it will be just the base for
>     something better... :D except if u really want to make any paradigm
>     shift for any idea, when u will need probably these kinda language
>     hacks...
>
>     i would also like to suggest to always use the most primitive variant
>     of the things, so like functions instead of methods, iterators instead
>     of coroutines, tables instead of trying to hack the varargs or crying
>     after tuples, arrays, dictionaries, proxy tables and whatever like (no
>     offense for any1 around! :D ) and one day u will really need these
>     things that i just told u to avoid, but wait for that day when it will
>     really come, and the final results will be much more pure and simple,
>     while u will have a lotsa time to make the best mental model for
>     everything before u would wire alltogether everything for delayed pain
>     :D
>
>     actually this is just a suggestion, but i know that i really doesnt
>     belong under the flagship of any specific paradigm, so a lotsa various
>     paradigms gave me funds for mine and maybe this wont be beneficial if
>     it is forced, but still, these rules of thumb serve me really nicely,
>     and i think mostly fixed programming paradigms can also be more or
>     less paired with these without making mess and any inconvenience by
>     breaking paradigm rules...
>
>     (sorry if i wasnt the clearest in my words, i has 3 days of
>     partyharding behind my shoulders that i still feel in my bones...)
>
>     bests, and have fun! :D
>


Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

Michal Kottman
On Sat, Oct 26, 2019, 7:37 PM Soni "They/Them" L. <[hidden email]> wrote:
In EXP context, but not EXPLIST context, I see no particular reason why
we couldn't do it with variables:

local foo = a b () -- equivalent to "local foo = a; b()"
local foo = (a b ()) -- equivalent to "local foo = a(b)()"

Can you explain how the second one works? Why is it not "a(b())"?
Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] Extend no-parenthesis notation to variables

Soni "They/Them" L.


On 2019-10-27 7:00 a.m., Michal Kottman wrote:

> On Sat, Oct 26, 2019, 7:37 PM Soni "They/Them" L. <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     In EXP context, but not EXPLIST context, I see no particular
>     reason why
>     we couldn't do it with variables:
>
>     local foo = a b () -- equivalent to "local foo = a; b()"
>     local foo = (a b ()) -- equivalent to "local foo = a(b)()"
>
>
> Can you explain how the second one works? Why is it not "a(b())"?
>

a "b" () --> a("b")()
(a b ()) --> a(b)()

it would remain consistent with existing language rules.