Pregunta

Quiero crear una lista de enteros de 1 a n. Puedo hacer esto en Python usando el rango (1, n + 1), y en Haskell usando: tomar n (iterar (1+) 1).

¿Cuál es el idioma OCaml correcto para esto?

¿Fue útil?

Solución

No conozco ningún idioma, pero aquí hay una definición bastante natural con un operador de infijo:

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

Alternativamente, la extensión de sintaxis de comprensiones (que da el código de sintaxis < > [i .. j] para lo anterior) es probable que se incluya en una versión futura de " versión de la comunidad " de OCaml , por lo que puede volverse idiomático. Sin embargo, no recomiendo que comiences a jugar con las extensiones de sintaxis si eres nuevo en el idioma.

Otros consejos

Con Baterías incluidas , puede escribir

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

El operador - genera una enumeración desde el primer valor hasta el segundo. El operador - ^ es similar, pero enumera un intervalo medio abierto ( 1 - ^ 10 se enumerará del 1 al 9).

Aquí tienes:

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

Tenga en cuenta que esto no es recursivo de cola. Las versiones modernas de Python incluso tienen un rango perezoso.

Esto funciona en base OCaml:

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

OCaml tiene una sintaxis especial para la coincidencia de patrones en rangos:

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

Para crear un rango, puede usar Core :

List.range 0 1000

Si usa open Batteries (que es una versión comunitaria de la biblioteca estándar), puede hacer un rango de (1, n + 1) por List .range 1 `a n (observe el backquote antes de To ).

Una forma más general (también necesita baterías) es usar List.init nf que devuelve una lista que contiene (f 0) (f 1) ... (f (n-1)) .

Un poco tarde para el juego, pero aquí está mi implementación:

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

Luego puedes usarlo muy parecido a la función 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] *)

naturalmente, creo que la mejor respuesta es simplemente usar Core, pero esto podría ser mejor si solo necesitas una función y estás tratando de evitar el marco completo.

Por cierto, en Haskell preferirías usar

enumFromTo 1 n
[1 .. n]

Estos son simplemente innecesarios.

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

Siguiendo a Alex Coventry desde arriba, pero aún más corto.

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

Si no necesita un " paso " parámetro, una manera fácil de implementar esta función sería:

deja que start start stop = List.init (abs @@ stop - start) (fun i - > i + start)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top