2008-10-28 6 views

Odpowiedz

22

Nie ma idiom, który znam, ale tutaj jest dość naturalny definicja za pomocą operatora Infix:

# 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] 

Alternatywnie comprehensions syntax extension (co daje składni [i .. j] dla wyżej) mogą mieć charakter zawarte w przyszłym wydaniu "community version" of OCaml, więc może stać się idiomatyczne. Nie polecam rozpoczęcia gry z rozszerzeniami składni, jeśli jesteś początkującym językiem.

+0

Twój link do społeczności ocaml powinien wskazywać na: http://forge.ocamlcore.org/projects/batteries/ – Thelema

+0

Operator '--' jest zaimplementowany w dołączonych bateriach, chociaż tworzy raczej wyliczenie niż listę. –

+0

Funkcja zakresu Pythona nie zawiera górnej granicy, tak jak twoja, ale łatwa do naprawienia przez wywołanie Aux z (j-1) zamiast j –

10

Proszę bardzo:

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

Zauważ, że to nie jest ogon rekurencyjnej. Nowoczesne wersje Pythona mają nawet leniwy zasięg.

+3

Niezupełnie - zakres Pythona (1,3) zwraca [1,2], podczas gdy twój (zakres 1 3) wraca [1; 2; 3]. Zmień> na> =. –

0

BTW, w Haskell wolisz używać

enumFromTo 1 n 
[1 .. n] 

Są to po prostu niepotrzebne.

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

Dzięki, nie zdawałem sobie z tego sprawy. – Pramod

11

Z Batteries Included, można napisać

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

Operator -- generuje wyliczenie wartości od pierwszego do drugiego. Operator --^ jest podobny, ale wylicza półotwarty interwał (1--^10 będzie wyliczał od 1 do 9).

+0

Nie jestem pewien, czy mi się podoba - czy możliwe jest zdefiniowanie operatora ..? – aneccodeal

+1

@ kod kodowy OCaml nie zezwala operatorom zaczynającym się od "." (chociaż mogą zawierać "." po pierwszym znaku). Dozwolone znaki dla operatorów są zdefiniowane w dokumentacji leksykalnej OCaml tutaj: http://caml.inria.fr/pub/docs/manual-ocaml/lex.html –

2

Jeśli używasz open Batteries (który jest wersją społeczność biblioteki standardowej), można zrobić range(1,n+1) przez List.range 1 `To n (zawiadomienie backquote przed To).

Bardziej ogólny sposób (również wymaga baterii) jest użycie List.init n f, która zwraca listę zawierającą (f 0) (f 1) ... (f (n-1)).

3

OCaml posiada specjalną składnię dopasowywania wzorca na zakresach:

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 

Aby utworzyć zakres, można użyć Core:

List.range 0 1000 
2

trochę późno do gry tutaj, ale tutaj jest moje wykonanie:

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

Można wtedy użyć go bardzo podobnie do funkcji Pythona:

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

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

naturalnie Myślę, że najlepszym rozwiązaniem jest po prostu użyć Rdzeń, ale to może być lepiej, jeśli potrzebujesz tylko jedną funkcję i starasz się unikać pełnego ramy.