The following works, but surely can't be right: l1 |> List.rev |> List.append [4] |> List.rev I'm sure there's a simpler way to get the append behaviour, but it's eluding me.

If you don't mind some parenthesis to override precedence:

1
2
3
4
([1;2;3;4]
|> List.map (fun x->x+1))
 @ [6;7;8]
|> List.reduce_left (+)
By on 4/28/2009 8:43 AM ()

Or you can use the ( @ ) operator :

1
[1; 2; 3] @ [4; 5; 6]
By on 4/27/2009 6:49 AM ()

Julien:

I couldn't find a way to use @ in a pipeline -- how would I access the "piped input" to pass it as the first argument?

By on 4/28/2009 4:21 AM ()

I think this is what you're looking for, though that may just be because I haven't had enough coffee yet.

[4; 5 ] |> (@) [ 1; 2; 3]

By on 4/28/2009 7:56 AM ()

not-enough-coffee-man bows his head.....

No, that's not what you were looking for. I'm curious, why do you need to use it in a pipeline?

By on 4/28/2009 8:03 AM ()

Same problem, though, (@) prepends instead of appends when in a pipeline.

let l1 = [1;2;3]

l1 |> (@) [4]

val it : int list = [4; 1; 2; 3]

What I'd need is something like:

l1 |> * @ [4]

where * is "the thing thats used as the input to the pipeline"

By on 4/28/2009 8:01 AM ()

What I'd need is something like:

l1 |> * @ [4]

where * is "the thing thats used as the input to the pipeline"

In this case "*" is four presses of the backspace key. :)

As to your original example, you can do e.g.

l1 |> (fun x -> List.append x [4])

but this whole thread highlights that "some curried functions pipeline more naturally than others" or perhaps "pipelining is not always the answer". When both arguments of a two-argument curried function have the same type, and the arguments don't commute, it can be easy to get confused about the ordering when using partial evaluation in a pipeline.

By on 4/28/2009 8:17 AM ()

Hi,
the problem is that your original code is treated like this:

1
2
3
4
 
 [1;2;3] |> List.append [4] 
// ...means the same thing as...
List.append [4] [1;2;3]

To get the behavior you want, you'll need a function a bit like append, but that takes the arguments in the opposite order. The clean way to do this is to define it:

1
2
3
4
5
6
 
module List =
  let prepend a b = List.append b a;;

[1; 2; 3] |> List.prepend [4; 5] 
// the result is [1; 2; 3; 4; 5]

A slightly dirty trick is to define a function that takes a function and two arguments and calls the given function with the arguments in reversed order:

1
2
3
4
5
 
let switch f x y = f y x

[1; 2; 3] |> switch List.append [4; 5] 
// yields [1; 2; 3; 4; 5] too
By on 4/26/2009 2:43 PM ()

Tomas:

Thanks. I think this is the way to go (ie adding a prepend function to List), although I dislike the fact that it sacrifices readability (the effect of the function is to APPEND when called in a pipeline).

By on 4/28/2009 4:24 AM ()

Hi,

As Tomas suggested, I think the correct approach would be to define List.prepend if you really wanted this behavior.

However, in the spirit of dirty solutions(!), it is possible to define functions enabling you to infix the List.append function:

1
2
3
4
5
6
7
8
9
10
11
12
 

let inline (</) x y = y x 
and inline (/>) x y z = x z y 

[1;2;3] </ List.append /> [4;5];;
val it : int list = [1; 2; 3; 4; 5]


[1;2;3] </ List.append /> [4] </List.append/> [5];;
val it : int list = [1; 2; 3; 4; 5]

Note, this solution does not play nicely with true infixed operators:

1
2
3
4
5
6
7
8
9
10
11
 

> 3 </min/> 4 + 6 </max/> 8;;


  3 </min/> 4 + 6 </max/> 8;;
  
----^^^^^^^^

stdin(8,5): error FS0001: Expecting a type supporting the operator '+' but given a function type. You may be missing an argument to a function.

Instead, you would have to enclose each infixed statement in parentheses:

1
2
(3 </min/> 4) + (6 </max/> 8);;
val it : int = 11

Regards,

Michael

By on 4/27/2009 12:38 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper