Pythonの範囲関数に相当するOCamlイディオムとは何ですか?

StackOverflow https://stackoverflow.com/questions/243864

  •  04-07-2019
  •  | 
  •  

質問

1〜nの整数のリストを作成したい。 Pythonでrange(1、n + 1)を使用して、Haskellでこれを行うには、take n(iterate(1+)1)を使用します。

このための正しいOCamlイディオムは何ですか?

役に立ちましたか?

解決

私が知っているイディオムはありませんが、ここに中置演算子を使用したかなり自然な定義があります:

# let (--) i j = 
    let rec aux n acc =
      if n < i then acc else aux (n-1) (n :: acc)
    in aux j [] ;;
      val ( -- ) : int -> int -> int list = <fun>
# 1--2;;
- : int list = [1; 2]
# 1--5;;
- : int list = [1; 2; 3; 4; 5]
# 5--10;;
- : int list = [5; 6; 7; 8; 9; 10]

または、 comprehensions構文拡張(構文 [i .. j] は上記の「コミュニティバージョン」」 OCaml のようになります。ただし、言語を初めて使用する場合は、構文拡張機能を使用することはお勧めしません。

他のヒント

Batteries Included を使用すると、次のように記述できます

let nums = List.of_enum (1--10);;

-演算子は、最初の値から2番目の値への列挙を生成します。 -^ 演算子も同様ですが、半開間隔を列挙します( 1-^ 10 は1から9まで列挙します)。

ここに行きます:

let rec range i j = if i > j then [] else i :: (range (i+1) j)

これは末尾再帰ではないことに注意してください。最新のPythonバージョンには遅延範囲もあります。

これはベースOCamlで動作します:

&#65283; List.init 5(fun x-&gt; x + 1);; -:int list = [1; 2; 3; 4; 5]

OCamlには、範囲のパターンマッチング用の特別な構文があります。

let () =
  let my_char = 'a' in
  let is_lower_case = match my_char with
  | 'a'..'z' -> true (* Two dots define a range pattern *)
  | _ -> false
  in
  printf "result: %b" is_lower_case

範囲を作成するには、 Core を使用できます。

>
List.range 0 1000

open Batteries (標準ライブラリのコミュニティバージョン)を使用する場合、 Listで range(1、n + 1)を実行できます。 .range 1 `To n To の前の逆引用符に注意してください)。

より一般的な方法(バッテリーも必要)は、 List.init nf を使用して、(f 0)(f 1)...(f(n-1))を含むリストを返します。

ゲームに少し遅れましたが、ここに私の実装があります:

let rec range ?(start=0) len =
    if start >= len
    then []
    else start :: (range len ~start:(start+1))

その後、Python関数と非常によく似た方法で使用できます。

range 10 
     (* equals: [0; 1; 2; 3; 4; 5; 6; 7; 8; 9] *)

range ~start:(-3) 3 
     (* equals: [-3; -2; -1; 0; 1; 2] *)

当然、最善の答えは単純にCoreを使用することだと思いますが、1つの関数のみが必要で、完全なフレームワークを避けたい場合はこれが良いかもしれません。

ところで、Haskellではむしろ使用したい

enumFromTo 1 n
[1 .. n]

これらは不要です。

take n [1 ..]
take n $ iterate (+1) 1

上からAlex Coventryをフォローしていますが、さらに短くなっています。

let range n = List.init n succ;;    
> val range : int -> int list = <fun>   
range 3;;                           
> - : int list = [1; 2; 3]              

&quot;ステップ&quot;が必要ない場合パラメータ、この関数を実装する簡単な方法の1つは次のとおりです。

let start start = List.init(abs @@ stop-start)(fun i-&gt; i + start)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top