F#, Pipe-forward first argument

寵の児 提交于 2020-02-29 12:20:31

问题


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.


回答1:


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]



回答2:


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.




回答3:


Just use a lambda:

[1;2;3] |> fun l -> l @ [4;5;6]

or point-free:

[1;2;3] |> (@) <| [4;5;6] // or
([1;2;3], [4;5;6]) ||> (@)

or as a normal function:

let foo l = l @ [4;5;6]
let bar = foo [1;2;3]



回答4:


After asking my coworker, he suggested:

[1;2;3]
    |> List.append
    <| [4;5;6]
// Result: [1;2;3;4;5;6]

If you have any other suggestions to an F# beginner like me, I would greatly appreciate your help. Thank you.



来源:https://stackoverflow.com/questions/42800373/f-pipe-forward-first-argument

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!