[nem-bug] [Nemerle 0000870]: Function composition operator & Pipeline operator

feedback at nemerle.org feedback at nemerle.org
Wed Feb 7 19:20:36 CET 2007


The following issue has been RESOLVED.
======================================================================
<http://nemerle.org/bugs/view.php?id=870> 
======================================================================
Reported By:                iae
Assigned To:                nazgul
======================================================================
Project:                    Nemerle
Issue ID:                   870
Category:                   Language Feature
Reproducibility:            N/A
Severity:                   feature
Priority:                   normal
Status:                     resolved
Resolution:                 fixed
Fixed in Version:           
======================================================================
Date Submitted:             02-05-2007 06:16 CET
Last Modified:              02-07-2007 19:20 CET
======================================================================
Summary:                    Function composition operator & Pipeline operator
Description: 
A lot of functional languages has a function composition operator. For
example in Haskell such operator is '.':

(.) :: (b -> c) -> (a -> b) -> (a -> c)
so "f.g" is equivalent to "\x -> f (g x)"

F# has the similar operator '>>':

val >>: ('a -> 'b) -> ('b -> 'c) -> ('a -> 'c)
so "g>>f" is equivalent to "fun x -> f (g x)"

It'll be a nice to have such operator in Nemerle. As for me, I prefer
Haskell style, but we can't use '.'. So, there is two way: 
1. use '>>' and F# style, i.e. "g>>f" will be "f of g", nor [Haskell
style] "g of f".
2. use own operator sign and Haskell style.


Other feature I want suggest is a pipeline operator.
Haskell:
($) :: (a -> b) -> a -> b
f $ g x = f (g x)

F#:
val |>: 'a -> ('a -> 'b) -> 'b
g x |> f = f (g x)

If we planing to add both oparetors (not only function composition),
possible we should use F# style for both of them.

What do you think about these two oparators? 
F# style oparators implemented in attached patch. Should I commit them?
======================================================================

----------------------------------------------------------------------
 iae - 02-05-07 06:21 
----------------------------------------------------------------------
Pipeline usage:

WriteLine(Sqrt(1235432) |> Floor);

Unfortunately, this way will not work propertly:

// typing fails on ambiguity between overloads
Sqrt(1235432) |> Floor |> WriteLine;

----------------------------------------------------------------------
 VladD2 - 02-05-07 12:25 
----------------------------------------------------------------------
In my option, Extension methods more intuitive than pipline:
1235432.Sqrt().Floor().WriteLine()

----------------------------------------------------------------------
 iae - 02-05-07 12:36 
----------------------------------------------------------------------
But there are a lot of methods not marked with extension attribute. Also,
as I know, local functions can't be an extensions.

----------------------------------------------------------------------
 VladD2 - 02-05-07 13:11 
----------------------------------------------------------------------
Maybe, it's better to allow to m&http://nemerle.org/bugs/view.php?id=1072;ke
ordinar methods as Extension
methods?
For example, it's can be done by blobale castom attributes:
[assembly: MakeMethodsAsExtention(Match.Sqrt, Console.WriteLine)]

----------------------------------------------------------------------
 iae - 02-05-07 13:20 
----------------------------------------------------------------------
Hmmm... It is a quite good idea. But, I'm not sure is it easy to implement.

----------------------------------------------------------------------
 nazgul - 02-05-07 17:37 
----------------------------------------------------------------------
I think that composition should be an instance method of function:

WriteLine(tup.Compose (t2str)());

WriteLine(tup.Compose (t2str).Compose(strlen)());

WriteLine(t2str.Compose (strlen)(1,2));

def isqrt = Sqrt.Compose (Ceiling); // instead of x => Ceiling(Sqrt(x))
WriteLine(isqrt(1235432));


As for the pipeline... I don't really see how this is useful... The only
thing it does is to move function name from beginning to the end:

x |> f   ===  f (x)    

For me, the second one is much cleaner. And if you really like to write
down the  operations applied in left-to-right order, then maybe use macro
to get:

pipe (343, Sqrt, Ceil, Sqrt, Sqr, Abs)
--->
Abs (Sqr, Sqrt, Ceil, Sqrt, 343)))))

----------------------------------------------------------------------
 iae - 02-06-07 08:31 
----------------------------------------------------------------------
> I think that composition should be an instance method of function:
> def isqrt = Sqrt.Compose (Ceiling); // instead of x => Ceiling(Sqrt(x))

I tried to find the shortest way. And I will never use Compose method
instead of 'x => ...' form. Using the operator '>>' will make the code
shorter and clearer. Also, function composition is usually used in
functional programming, so using an imperative style to make function
composition isn't a good idea.

> As for the pipeline... I don't really see how this is useful...

I don't really see how this can be much of use in Nemerle either... But,
if you look at any F# or Haskell codes, you will see many places where
such operator is used. As I see, F# and Haskell programmers use them to
avoid flooding of code with parentheses.
Also, we can use pipeline when we can't use extension methods. Let's look
at the piece of code bellow:

  def types : list[Type] = 
    AppDomain.CurrentDomain.GetAssemblies()
    .ToList()
    .FoldLeft([], (x,y) => x.GetTypes().ToList() + y);

This code is quite easy to understand. And now imagine that ToList and
FoldLeft are local functions. So, our code will be very ugly:

  def types : list[Type] = 
    FoldLeft(ToList(AppDomain.CurrentDomain.GetAssemblies()), 
                    [], 
                    (x,y) => ToList(x.GetTypes()) + y);

Isn't it? But, we can use pipeline to avoid such ugliness:

  def types : list[Type] = 
    AppDomain.CurrentDomain.GetAssemblies() 
    |> ToList 
    |> FoldLeft(_, [], (x,y) => (x.GetTypes() |> ToList) + y);

This code is almost like our first version with extension methods.



----------------------------------------------------------------------
 nazgul - 02-07-07 19:20 
----------------------------------------------------------------------
Ok, I added a modified version of those operators. There is still bug 882,
which prevents from using them out of the box, but with 'using
Nemerle.Builtins.Function' it works reasonably well.

Issue History
Date Modified  Username       Field                    Change              
======================================================================
02-05-07 06:16 iae            New Issue                                    
02-05-07 06:16 iae            File Added: funccomp.patch                    
02-05-07 06:21 iae            Note Added: 0001677                          
02-05-07 12:25 VladD2         Note Added: 0001678                          
02-05-07 12:36 iae            Note Added: 0001679                          
02-05-07 13:11 VladD2         Note Added: 0001680                          
02-05-07 13:20 iae            Note Added: 0001681                          
02-05-07 17:37 nazgul         Note Added: 0001688                          
02-06-07 08:28 iae            Note Added: 0001702                          
02-06-07 08:31 iae            Note Edited: 0001702                         
02-06-07 08:31 iae            Note Edited: 0001702                         
02-07-07 19:20 nazgul         Status                   new => resolved     
02-07-07 19:20 nazgul         Resolution               open => fixed       
02-07-07 19:20 nazgul         Assigned To               => nazgul          
02-07-07 19:20 nazgul         Note Added: 0001707                          
======================================================================




More information about the bugs mailing list