Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F#, Pipe-forward first argument

Tags:

f#

Quite similar to this question: F# pipe first parameter

I am currently learning F# and functional programming, and I want to know if there is an easy way to pipe-forward a first argument (instead of last argument).

For example, if I want to pipe forward the last argument, it looks very nice and clean:

[4;5;6]
    |> List.append [1;2;3]

// Result: [1;2;3;4;5;6]

If I want to pipe-forward the first argument, I can use a "fun x ->" function, but I am just curious if there is a cleaner way.

[1;2;3]
    |> fun x -> List.append x [4;5;6]

// Result: [1;2;3;4;5;6] 

Thank you very much.


P.S. My coworker just helped me with this problem. But I would appreciate any help if you have any suggestions for an F# beginner. Thank you.

like image 682
CH Ben Avatar asked Mar 15 '17 03:03

CH Ben


2 Answers

When the order of arguments is inconvenient, you can always transform the function itself to make it take the arguments in a different order:

let flip f x y = f y x

[1; 2; 3]
    |> (flip List.append) [4; 5; 6]

Transforming functions is useful in many contexts. It is a functional programmer's bread and butter.

But in the end, I believe, readability is most important: programs are read incomparably more often than they are written. When I find myself in a similar situation, and I don't want to name the intermediate value or use a lambda expression for some reason, I define myself a function that would be intuitive to understand:

let prependTo a b = List.append b a

[1; 2; 3] 
   |> prependTo [4; 5; 6]
like image 160
Fyodor Soikin Avatar answered Nov 17 '22 13:11

Fyodor Soikin


All the existing answers provide good solution to the problem.

However, I think that if you want to use pipe to specify the first argument of a function, most of the time, it is not a good idea and you should just use an ordinary call without pipes:

List.append [1;2;3] [4;5;6]

The reason is that the "piping pattern" lets you write code that performs series of transformations on some data structure (list, etc.). Libraries designed to support the piping pattern will take the "main input" as the last argument to support pipe.

If you are piping into an argument that is not last, it means that you are breaking this regularity, so you are no longer passing one data structure through a series of transformations. This will make your code confusing because "it looks like a pipe, but it is not really a pipe".

Of course, this is not always the case and there are situations where you need this, but as a rule of thumb, I'd only use pipe when it fits.

like image 12
Tomas Petricek Avatar answered Nov 17 '22 14:11

Tomas Petricek