3

この ML コードを F# に変換したいと思います。

fun take ([], i) = []
  | take (x::xs, i) = if i > 0 then x::take(xs, i-1) 
                                else [];

私はこれを試しました

let rec take n i =
  match n,i with 
    | [], i -> []
    | x::xs, i -> if i > 0 then x::take(xs, i-1)
                           else [];

let val = take [1;2;3;4] 3

そしてこれ

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)

しかし、どちらもエラーが発生しますtake.fs(7,5): error FS0010: Unexpected keyword 'val' in binding。F# コードの何が問題になっていますか?

4

2 に答える 2

9

いくつかコメントを追加すると、F# で関数を記述する最も良い方法は、次を使用することだと思います。

let rec take i n=  
  match n, i with
  | [], i -> []
  | _, i when i <= 0 -> []
  | x::xs, i -> x::(take (i-1) xs)

私は2つの変更を行いました:

  • パターン マッチングを使用してテストしますi <= 0(これは と同じことをif行いますが、見た目が少し良くなります)。
  • 最も重要な引数 (入力リスト) が最後の引数になるように、引数の順序を逆にします。これにより、パイプライン演算子で関数をうまく使用できます。

    [1;2;3;4] |> take 3
    
于 2011-06-05T22:06:22.520 に答える
7

は F# の予約済みキーワードであるためval、値として使用することはできません。(タプル形式) の型が(カリー化された形式)の型と異なるため、の最初のバージョンtakeは間違っています。これは機能します:take(xs, i-1)take n i

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

2 番目のバージョンでは、関数を呼び出す方法に誤りがあります。次のように修正できます。

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

または、ML 関数にさらに近づけて書くこともできます。

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)
于 2011-06-05T21:46:31.867 に答える