You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@groovy.apache.org by "Daniel.Sun" <su...@apache.org> on 2018/02/25 13:38:54 UTC

[GEP] Concatenative Method Calls

Hi all,

     I propose to introduce Concatenative Method Calls to Groovy. It can
make code more readable, for example:

Currently we write method calls like:
y = foo(x)
z = bar(y)
w = baz(z)
OR
w = baz(bar(foo(x)))

Concatenative Method Calls(inspired by [1]):
w = x => foo => bar => baz

      Any thoughts?

Cheers,
Daniel.Sun
[1] https://en.m.wikipedia.org/wiki/Concatenative_programming_language



--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html

Re: [GEP] Concatenative Method Calls

Posted by mg <mg...@arscreat.com>.
Hi Daniel,
I agree with Andrew, the example to me looks less readable. Do you have another example that shows what application you had in mind ?
Cheers,mg
-------- Ursprüngliche Nachricht --------Von: Andrew Bayer <an...@gmail.com> Datum: 25.02.18  15:02  (GMT+01:00) An: dev@groovy.apache.org Betreff: Re: [GEP] Concatenative Method Calls 
I actually find that less readable, and feel like it would get even worse with multiple parameters. I’m not sure I see what the value here would be.
A.
On Sun, Feb 25, 2018 at 8:39 AM Daniel.Sun <su...@apache.org> wrote:
Hi all,



     I propose to introduce Concatenative Method Calls to Groovy. It can

make code more readable, for example:



Currently we write method calls like:

y = foo(x)

z = bar(y)

w = baz(z)

OR

w = baz(bar(foo(x)))



Concatenative Method Calls(inspired by [1]):

w = x => foo => bar => baz



      Any thoughts?



Cheers,

Daniel.Sun

[1] https://en.m.wikipedia.org/wiki/Concatenative_programming_language







--

Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html



Re: [GEP] Concatenative Method Calls

Posted by Andrew Bayer <an...@gmail.com>.
I actually find that less readable, and feel like it would get even worse
with multiple parameters. I’m not sure I see what the value here would be.

A.

On Sun, Feb 25, 2018 at 8:39 AM Daniel.Sun <su...@apache.org> wrote:

> Hi all,
>
>      I propose to introduce Concatenative Method Calls to Groovy. It can
> make code more readable, for example:
>
> Currently we write method calls like:
> y = foo(x)
> z = bar(y)
> w = baz(z)
> OR
> w = baz(bar(foo(x)))
>
> Concatenative Method Calls(inspired by [1]):
> w = x => foo => bar => baz
>
>       Any thoughts?
>
> Cheers,
> Daniel.Sun
> [1] https://en.m.wikipedia.org/wiki/Concatenative_programming_language
>
>
>
> --
> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
>

Re: [GEP] Concatenative Method Calls

Posted by MG <mg...@arscreat.com>.
As somebody who routinely works with Groovy ( ;-) ) I agree with all of 
that.
Using e.g. |> instead of => seems to me a much better choice, for a 
multitude of reasons.

While I personally do not have big need for such an operator, and am 
generally a fan of using fluent method chaining (when I did e.g. program 
in C# I always found that much clearer in 99% of cases than the LINQ 
syntax - but opinions differ widely on this), for using Groovy as an 
alternative to Unix shell scripts having a pipe operator could be useful...


On 25.02.2018 16:02, Jesper Steen Møller wrote:
> Interesting proposal and discussion!
>
> As somebody who routinely work in both Java, Groovy, TypeScript/ES6 
> and C#, I find this /syntactically/ too close too arrow 
> functions/lambdas, in other words, they may confuse a lot of readers.
>
> As for the /semantic/ content: I realize that Groovy goes a long way 
> to support multiple paradigms, but I feel this is trying to cater to 
> the needs of concatenative / point-free style programming, in a 
> language and environment which doesn't really have the functional 
> compositionality to take advantage of it -- because Groovy is at its 
> heart object-oriented.
>
> Your proposal is essentially the forward pipe operator |> for function 
> composition, as seen in a number of functional languages, like F# and 
> Elm (as "&" in Haskell). In those languages, it makes a lot of sense, 
> since the function is the primarily compositional building block. In 
> Groovy, it's the object, and many of the core features of Groovy (like 
> overloading, extension methods, AST transformations, closures) are 
> added to support those. In practice, I've seen very little Groovy code 
> which ends up being formulated as baz(bar(foo(x))) -- but I've seen a 
> lot of  x.foo().bar().baz() instead. It's a better match, and Groovy 
> already has a great operator "." to make programs easy to read and type
>
> -Jesper
>
>> On 25 Feb 2018, at 14.38, Daniel.Sun <sunlan@apache.org 
>> <ma...@apache.org>> wrote:
>>
>> Hi all,
>>
>>     I propose to introduce Concatenative Method Calls to Groovy. It can
>> make code more readable, for example:
>>
>> Currently we write method calls like:
>> y = foo(x)
>> z = bar(y)
>> w = baz(z)
>> OR
>> w = baz(bar(foo(x)))
>>
>> Concatenative Method Calls(inspired by [1]):
>> w = x => foo => bar => baz
>>
>>      Any thoughts?
>>
>> Cheers,
>> Daniel.Sun
>> [1] https://en.m.wikipedia.org/wiki/Concatenative_programming_language
>>
>>
>>
>> --
>> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
>


Re: [GEP] Concatenative Method Calls

Posted by "Daniel.Sun" <su...@apache.org>.
Hi Guillaume,

     I have to admit closure is very versatile...

     In practice, chained closures are a bit verbose :-(

(obj1.&m1 >> obj2.&m2 >> obj3.&m3)(someParam)

     In addition, chained closures seems not to support multiple parameters.
While I propose the following syntax to support multiple parameters.

(x, y) => m1 => (m2, param) => m3

P.S.  I like Jesper proposed |> to replace =>

Cheers,
Daniel.Sun





--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html

Re: [GEP] Concatenative Method Calls

Posted by Guillaume Laforge <gl...@gmail.com>.
Quick note in the discussion: we have already a form of composition with
closures, using the right shift operator:

http://mrhaki.blogspot.fr/2011/04/groovy-goodness-chain-closures-together.html?m=1

Le dim. 25 févr. 2018 à 16:02, Jesper Steen Møller <je...@selskabet.org> a
écrit :

> Interesting proposal and discussion!
>
> As somebody who routinely work in both Java, Groovy, TypeScript/ES6 and
> C#, I find this *syntactically* too close too arrow functions/lambdas, in
> other words, they may confuse a lot of readers.
>
> As for the *semantic* content: I realize that Groovy goes a long way to
> support multiple paradigms, but I feel this is trying to cater to the needs
> of concatenative / point-free style programming, in a language and
> environment which doesn't really have the functional compositionality to
> take advantage of it -- because Groovy is at its heart object-oriented.
>
> Your proposal is essentially the forward pipe operator |> for function
> composition, as seen in a number of functional languages, like F# and Elm
> (as "&" in Haskell). In those languages, it makes a lot of sense, since the
> function is the primarily compositional building block. In Groovy, it's the
> object, and many of the core features of Groovy (like overloading,
> extension methods, AST transformations, closures) are added to support
> those. In practice, I've seen very little Groovy code which ends up being
> formulated as baz(bar(foo(x))) -- but I've seen a lot of
>  x.foo().bar().baz() instead. It's a better match, and Groovy already has a
> great operator "." to make programs easy to read and type
>
> -Jesper
>
> On 25 Feb 2018, at 14.38, Daniel.Sun <su...@apache.org> wrote:
>
> Hi all,
>
>     I propose to introduce Concatenative Method Calls to Groovy. It can
> make code more readable, for example:
>
> Currently we write method calls like:
> y = foo(x)
> z = bar(y)
> w = baz(z)
> OR
> w = baz(bar(foo(x)))
>
> Concatenative Method Calls(inspired by [1]):
> w = x => foo => bar => baz
>
>      Any thoughts?
>
> Cheers,
> Daniel.Sun
> [1] https://en.m.wikipedia.org/wiki/Concatenative_programming_language
>
>
>
> --
> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
>
>
>

Re: [GEP] Concatenative Method Calls

Posted by Jesper Steen Møller <je...@selskabet.org>.
Interesting proposal and discussion!

As somebody who routinely work in both Java, Groovy, TypeScript/ES6 and C#, I find this syntactically too close too arrow functions/lambdas, in other words, they may confuse a lot of readers.

As for the semantic content: I realize that Groovy goes a long way to support multiple paradigms, but I feel this is trying to cater to the needs of concatenative / point-free style programming, in a language and environment which doesn't really have the functional compositionality to take advantage of it -- because Groovy is at its heart object-oriented.

Your proposal is essentially the forward pipe operator |> for function composition, as seen in a number of functional languages, like F# and Elm (as "&" in Haskell). In those languages, it makes a lot of sense, since the function is the primarily compositional building block. In Groovy, it's the object, and many of the core features of Groovy (like overloading, extension methods, AST transformations, closures) are added to support those. In practice, I've seen very little Groovy code which ends up being formulated as baz(bar(foo(x))) -- but I've seen a lot of  x.foo().bar().baz() instead. It's a better match, and Groovy already has a great operator "." to make programs easy to read and type

-Jesper

> On 25 Feb 2018, at 14.38, Daniel.Sun <su...@apache.org> wrote:
> 
> Hi all,
> 
>     I propose to introduce Concatenative Method Calls to Groovy. It can
> make code more readable, for example:
> 
> Currently we write method calls like:
> y = foo(x)
> z = bar(y)
> w = baz(z)
> OR
> w = baz(bar(foo(x)))
> 
> Concatenative Method Calls(inspired by [1]):
> w = x => foo => bar => baz
> 
>      Any thoughts?
> 
> Cheers,
> Daniel.Sun
> [1] https://en.m.wikipedia.org/wiki/Concatenative_programming_language
> 
> 
> 
> --
> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html


Re: [GEP] Concatenative Method Calls

Posted by Jochen Theodorou <bl...@gmx.org>.
On 26.02.2018 00:53, Daniel Sun wrote:
> Hi Jochen,
> 
>       To be honest, I have no complex examples in my mind. Maybe it will be
> good for DSL(We can think `|>` as a big arrow drawn by | and >):
> 
> ```
> clothes  |>  clean  |>  dry  |>  notify
> ```

In my experience the less grammar elements a DSL has the better, unless 
it is a mathematical DSL. |> does not server that purpose, nor do .& or 
=> or ->

>       I ran the code you provided, error occurred as you expected,  but we
> wish it could run well. We have to refine the implementation...
> 
> groovy> class X {
> groovy>   private bar(){1}
> groovy>   def b = this.&bar
> groovy> }
> groovy> println new X().b()
> groovy> class Y extends X {}
> groovy> println new Y().b()

the implementation will have to provide the caller class as part of the 
method choosing, thus as part of the method reference... unless we 
totally rewrite that and make something entirely different... maybe I 
would experiment with using a callsite as backing for the handle.

bye Jochen

Re: [GEP] Concatenative Method Calls

Posted by Daniel Sun <re...@hotmail.com>.
Hi Jochen,

     To be honest, I have no complex examples in my mind. Maybe it will be
good for DSL(We can think `|>` as a big arrow drawn by | and >):

```
clothes  |>  clean  |>  dry  |>  notify
```

     I ran the code you provided, error occurred as you expected,  but we
wish it could run well. We have to refine the implementation...

groovy> class X {  
groovy>   private bar(){1}  
groovy>   def b = this.&bar  
groovy> }  
groovy> println new X().b()  
groovy> class Y extends X {}  
groovy> println new Y().b()  
 
1
Exception thrown

groovy.lang.MissingMethodException: No signature of method: Y.bar() is
applicable for argument types: () values: []
Possible solutions: tap(groovy.lang.Closure), wait(), any(), wait(long),
any(groovy.lang.Closure), is(java.lang.Object)


Cheers,
Daniel.Sun



--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html

Re: [GEP] Concatenative Method Calls

Posted by "Daniel.Sun" <su...@apache.org>.
Hi Jochen,

     I submitted a JIRA ticket to show the evolving process :-)

https://issues.apache.org/jira/browse/GROOVY-8997


Cheers,
Daniel.Sun



-----
Apache Groovy committer 
Blog: http://blog.sunlan.me 
Twitter: @daniel_sun 

--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html

Re: [GEP] Concatenative Method Calls

Posted by Jochen Theodorou <bl...@gmx.org>.
On 25.02.2018 14:38, Daniel.Sun wrote:
> Hi all,
> 
>       I propose to introduce Concatenative Method Calls to Groovy. It can
> make code more readable, for example:
> 
> Currently we write method calls like:
> y = foo(x)
> z = bar(y)
> w = baz(z)
> OR
> w = baz(bar(foo(x)))
> 
> Concatenative Method Calls(inspired by [1]):
> w = x => foo => bar => baz
> 
>        Any thoughts?
> 
> Cheers,
> Daniel.Sun
> [1] https://en.m.wikipedia.org/wiki/Concatenative_programming_language

I think if we want to become a concatenative programming language, we 
should first try to allow tacit programming... I would not start with 
composition here. You start with how to actually reference a function in 
the first place. If you go with method references you can do some things:

this.&baz << this.&bar << this.&foo (x)

Or with a lambda style:

this::baz << this::bar << this::foo (x)

And you can even leave the (x) to get the composition. And you can do 
even something like

def barfoo = this::bar << this::foo
this::baz << barfoo (x)

In your variant I find it questionable if you can do without the "this". 
Otherwise you will have an overlap between local variables and methods.

So what I would like to see is 1-n more complex examples, that do not 
concentrate on one line only. It should contain a "reference" to method, 
that is no on "this"; it should show how the shadowing by a local 
variable is supposed to be handled (if any); and it show how arguments 
are handled, especially for different arities... After that we can talk 
about if that is really better readable.

I actually do think our method references need rework in how they are 
formed, because they are actually functionally incomplete, as can be 
easily seen in this example:

> class X {
>   private bar(){1}
>   def b = this.&bar
> }
> println new X().b()
> class Y extends X {}
> println new Y().b()

That's why I said I would prefer cleaning those elements up and make 
them actually working correctly before we go to composition in the next 
step and then talk maybe about a concatenative programming language and 
how much that clashes with command expressions ;)

bye Jochen


Re: [GEP] Concatenative Method Calls

Posted by David Dawson <da...@simplicityitself.com>.
Hello.

I conceptually like this a lot, its a very dataflow style approach to the
problem

Conceptually, its similar to

[1,2,3].map { it * 2 }.each { println it }

Or in a unix shell

cat file | grep x | echo

Or perhaps something more reactive streams ish.

In any case, its re-arranging the function call order to visually be in the
order that it actually happens, rather than inside out, as is "normal"

You could imagine the above chained method calls (which is given to us by
extension methods on groovy collections) as something more generic using
this form.  Imagine that we have a new collection type, not implementing
the java collections api (like one of the dodgy SAX libraries or
something). You can't do the method chaining transformation above.  What
you want to do is to arrange a pipeline of function calls.

Instead of having to do something contrived like

printIt(timesTwo([1,2,3]))

You could do something more like

[1,2,3] => timesTwo => printIt

So, with "generic" methods, unattached to any types via extension methods,
you gain much of the same benefit as method chained transforms on
Collections, but *everywhere*.

So, I'm certainly a fan of *something* like this, even if the fat arrow
syntax might not be the best/ one I'd choose necessarily.

Personally, I'd like a " | ", if it can be made to fit in somehow, as thats
a very familiar syntax for the concept from the shell world

David.






On 25 February 2018 at 14:17, mg <mg...@arscreat.com> wrote:

> Intuitively the => arrow-operators point in the wrong direction, since I
> feel foo gets applied to x, etc...
>
> How would additional arguments to an intermediate function be handled in
> this syntax ?
>
> -------- Ursprüngliche Nachricht --------
> Von: "Daniel.Sun" <su...@apache.org>
> Datum: 25.02.18 14:38 (GMT+01:00)
> An: dev@groovy.incubator.apache.org
> Betreff: [GEP] Concatenative Method Calls
>
> Hi all,
>
>      I propose to introduce Concatenative Method Calls to Groovy. It can
> make code more readable, for example:
>
> Currently we write method calls like:
> y = foo(x)
> z = bar(y)
> w = baz(z)
> OR
> w = baz(bar(foo(x)))
>
> Concatenative Method Calls(inspired by [1]):
> w = x => foo => bar => baz
>
>       Any thoughts?
>
> Cheers,
> Daniel.Sun
> [1] https://en.m.wikipedia.org/wiki/Concatenative_programming_language
>
>
>
> --
> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
>

Re: [GEP] Concatenative Method Calls

Posted by mg <mg...@arscreat.com>.
Intuitively the => arrow-operators point in the wrong direction, since I feel foo gets applied to x, etc...
How would additional arguments to an intermediate function be handled in this syntax ?
-------- Ursprüngliche Nachricht --------Von: "Daniel.Sun" <su...@apache.org> Datum: 25.02.18  14:38  (GMT+01:00) An: dev@groovy.incubator.apache.org Betreff: [GEP] Concatenative Method Calls 
Hi all,

     I propose to introduce Concatenative Method Calls to Groovy. It can
make code more readable, for example:

Currently we write method calls like:
y = foo(x)
z = bar(y)
w = baz(z)
OR
w = baz(bar(foo(x)))

Concatenative Method Calls(inspired by [1]):
w = x => foo => bar => baz

      Any thoughts?

Cheers,
Daniel.Sun
[1] https://en.m.wikipedia.org/wiki/Concatenative_programming_language



--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html