I'd like to translate this ML code into F#.
fun take ([], i) = []
| take (x::xs, i) = if i > 0 then x::take(xs, i-1)
else [];
I tried this one
let rec take n i =
match n,i with
| [], i -> []
| x::xs, i -> if i > 0 then x::take(xs, i-1)
else [];
l开发者_如何转开发et val = take [1;2;3;4] 3
and this one
let rec take input =
match input with
| ([], i) -> []
| (x::xs, i) -> if i > 0 then x::take(xs, i-1)
else [];
let val = take ([1;2;3;4] 3)
But both of them gives me an error take.fs(7,5): error FS0010: Unexpected keyword 'val' in binding
. What's wrong with the F# code?
Just to add a few comments, I think the nicest way to write the function in F# is to use:
let rec take i n=
match n, i with
| [], i -> []
| _, i when i <= 0 -> []
| x::xs, i -> x::(take (i-1) xs)
I did two changes:
- Use pattern matching to test whether
i <= 0
(which does the same thing asif
, but looks a bit nicer) Reverse the order of arguments so that the most important argument (the input list) is the last one. This makes it possible to use the function nicely with pipelining operator:
[1;2;3;4] |> take 3
Since val
is a reserved keyword in F#, you can't use it as a value. Your first version of take
is wrong because the type of take(xs, i-1)
(tuple form) is different from the type of take n i
(curried form). This works:
let rec take n i =
match n, i with
| [], i -> []
| x::xs, i -> if i > 0 then x::(take xs (i-1)) else []
let value = take [1;2;3;4] 3
The second version has a mistake in the way you invoke the function. It could be fixed as follows:
let rec take input =
match input with
| [], i -> []
| x::xs, i -> if i > 0 then x::take(xs, i-1) else []
let value = take ([1;2;3;4], 3) // Notice ',' as tuple delimiter
Or you can write even closer to your ML function:
let rec take = function
| [], i -> []
| x::xs, i -> if i > 0 then x::take(xs, i-1) else []
let value = take ([1;2;3;4], 3)
精彩评论