2008-10-28 7 views
19

Я хочу создать список целых чисел от 1 до n. Я могу сделать это в Python, используя диапазон (1, n + 1) и в Haskell, используя: take n (итерация (1+) 1).Что такое идиома OCaml, эквивалентная функции диапазона Python?

Какая идиома OCaml для этого?

+17

Синтаксис Haskell будет следующим: `[1..n]`. – yfeldblum 2008-10-29 16:02:37

ответ

22

Там нет идиомы, что я не знаю, но здесь довольно естественное определение с помощью оператора инфиксную:

# 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 syntax extension (который дает синтаксис [i .. j] для выше), вероятно, будет включенных в будущий выпуск "community version" of OCaml, так что может стать идиоматическим. Я не рекомендую вам начинать играть с расширениями синтаксиса, если вы новичок в языке.

+0

ваша ссылка на публикацию ocaml следует указывать на: http://forge.ocamlcore.org/projects/batteries/ – Thelema 2008-10-28 17:35:32

+0

Оператор `--` реализован в комплекте с батареями, хотя он производит перечисление, а не список. – 2010-08-14 11:44:08

+0

Функция диапазона Python не включает верхнюю границу, как это делает ваш, но достаточно легко исправить, вызвав aux с (j-1) вместо j – 2012-11-18 03:51:26

10

Здесь вы идете:

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

Обратите внимание, что это не хвостовой рекурсией. У современных версий Python даже есть ленивый диапазон.

+3

Не совсем - диапазон Python (1,3) возвращает [1,2], а ваш (диапазон 1 3) возвращает [1; 2; 3]. Изменить> на> =. – 2008-10-29 16:45:43

0

Кстати, в Haskell, вы хотели бы использовать

enumFromTo 1 n 
[1 .. n] 

Это просто ненужными.

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

С Batteries Included, вы можете написать

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

Оператор -- генерирует перечисление от первого значения ко второму. Оператор --^ схож, но перечисляет полуоткрытый интервал (1--^10 будет перечисляться с 1 по 9).

2

Если вы используете open Batteries (который является версией сообщества стандартной библиотеки), вы можете сделать range(1,n+1) по List.range 1 `To n (обратите внимание на кавычку перед тем To).

Более общий способ (также нужны батареи) - использовать List.init n f, который возвращает список, содержащий (f 0) (f 1) ... (f (n-1)).

3

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 
2

Немного поздно к игре здесь, но вот моя реализация:

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] *) 

, естественно, я думаю, что лучший ответ просто использовать ядро, но это могло бы быть лучше, если вам нужно только одну функцию, и вы пытаетесь избежать полной базы.

 Смежные вопросы

  • Нет связанных вопросов^_^