2008-10-28 7 views

Répondre

22

Il n'y a pas idiome que je connaisse, mais voici une assez définition naturelle à l'aide d'un opérateur infixe:

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

Alternativement, le comprehensions syntax extension (ce qui donne pour ce qui précède la syntaxe [i .. j]) est susceptible d'être inclus dans une future version de la "community version" of OCaml, de sorte que mai devenir idiomatique. Cependant, je ne vous recommande pas de commencer à jouer avec des extensions de syntaxe si vous êtes nouveau dans la langue.

+0

votre lien vers la communauté ocaml doit pointer vers: http://forge.ocamlcore.org/projects/batteries/ – Thelema

+0

L'opérateur '- 'est implémenté dans Batteries Included, bien qu'il produise une énumération plutôt qu'une liste. –

+0

La fonction range de Python n'inclut pas la limite supérieure, comme la vôtre, mais assez facile à corriger en appelant aux aux avec (j-1) au lieu de j –

10

Ici, vous allez:

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

Notez que ce n'est pas récursive. Les versions modernes de Python ont même une gamme paresseuse.

+3

Pas tout à fait - La plage Python (1,3) renvoie [1,2] alors que votre (plage 1 3) renvoie [1; 2; 3]. Changer> à> =. –

0

BTW, en Haskell vous préférez utiliser

enumFromTo 1 n 
[1 .. n] 

Ce sont tout simplement inutiles.

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

Merci, je ne m'en suis pas rendu compte. – Pramod

11

Avec Batteries Included, vous pouvez écrire

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

L'opérateur -- génère une énumération de la première valeur à la seconde. L'opérateur --^ est similaire, mais énumère un intervalle semi-ouvert (1--^10 énumérera de 1 à 9).

+0

Pas sûr que j'aime - pour cela, est-il possible de définir un opérateur ..? – aneccodeal

+1

@aneccodeal Non. OCaml n'autorise pas les opérateurs commençant par '.' (bien qu'ils puissent contenir '.' après le premier caractère). Les caractères autorisés pour les opérateurs sont définis dans la documentation lexicale d'OCaml ici: http://caml.inria.fr/pub/docs/manual-ocaml/lex.html –

2

Si vous utilisez open Batteries (qui est une version communautaire de la bibliothèque standard), vous pouvez le faire range(1,n+1) par List.range 1 `To n (notez le backquote avant To).

Une manière plus générale (nécessite également des batteries) est d'utiliser List.init n f qui retourne une liste contenant (f 0) (f 1) ... (f (n-1)).

3

OCaml a une syntaxe spéciale pour la correspondance de motif sur les gammes:

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 

Pour créer une gamme, vous pouvez utiliser Core:

List.range 0 1000 
2

Un peu tard pour le jeu ici, mais voici ma mise en œuvre: Vous pouvez ensuite l'utiliser comme la fonction 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] *) 

naturellement, je pense que la meilleure réponse est d'utiliser simplement de base, mais cela pourrait être mieux si vous avez seulement besoin d'une fonction et que vous essayez d'éviter le cadre complet.

Questions connexes