2011-10-10 25 views
5

estoy evaluando una pieza muy simple de código en Ocaml de nivel superior:paréntesis en Ocaml

let p5() = print_int 5;; 
p5();; 

print_string "*************************";; 

let p4 = print_int 4;; 
p4;; 

y devuelve:

val p5 : unit -> unit = <fun> 
# 5- : unit =() 
# *************************- : unit =() 
# 4val p4 : unit =() 
# - : unit =() 

Mis preguntas son

  1. Lo que hace () media en let p5() = print_int 5;;?
  2. ¿Qué significa - y () en # 5- : unit =()?
  3. ¿Es p4 una función?
  4. ¿Por qué hay un 4 en el comienzo de # 4val p4 : unit =()?
  5. Parece que () podría usarse en código Ocaml para ocultar los efectos secundarios, ¿alguien podría mostrarme un ejemplo?
+1

es posible que desee para acostumbrarse a usar 'print_endline' en lugar de' print_string' porque imprime automáticamente una línea de fondo después de – newacct

Respuesta

11

Aquí algunas respuestas:

  1. () es el valor del tipo de unidad. El tipo de unidad es un tipo con solo un valor. Esto se usa generalmente para producir funciones que o bien no devuelven nada significativo o no toman nada significativo. Recuerde que en OCaml todas las funciones siempre tienen que devolver algo y tomar algunos argumentos, por lo que el tipo de unidad se usa para sortear esta limitación. Piense en esto similar al tipo void en C, C++ o Java.
  2. Hay dos líneas intercaladas. El 5 está impreso por la función print_int y no por el toplevel. El toplevel simplemente devuelve - : unit =() sin el 5. El toplevel le dice que no creó ningún enlace nuevo - y que el último valor devuelto es del tipo unit y tiene el valor ().
  3. No. No toma ningún argumento, por lo que no es una función.
  4. Nuevamente hay dos líneas intercaladas. El 4 se imprime mediante la función print_int. En este momento, toplevel le está diciendo que creó un nuevo enlace p4, que esta variable tiene un valor de tipo unit y que el valor almacenado es ().
  5. No, () no se utiliza para ocultar los efectos secundarios. Por lo general, se usa para crear funciones que tienen efectos secundarios y, por lo tanto, no necesitan ningún tipo de argumento.
6

LiKao ya ha explicado todos los puntos clave, pero pensé que podría tener más sentido si ingresara sus definiciones una línea a la vez, que mostraría qué respuestas provienen de qué entradas. Las líneas ingresadas por la persona comienzan con #.

# let p5() = print_int 5;; 
val p5 : unit -> unit = <fun> 

Esto define p5 como una función que acepta valores de tipo unit y devuelve valores de tipo unit. Solo hay un valor de unidad de texto, que se escribe como (). Entonces estos son exactamente los paréntesis sobre los que preguntas (creo). Tenga en cuenta que el () que aparece en su definición es un patrón para los valores aceptados por la función. Como patrón, () se empareja a sí mismo (como todas las constantes utilizadas como patrones).

# p5();; 
5- : unit =() 

Esto es un poco confuso. El 5 está escrito por su función p5. El resto es la respuesta del nivel superior OCaml. Se dice que el resultado de su expresión es del tipo unit y tiene el valor (). Tiene sentido, print_int es del tipo int -> unit.

# print_string "*************************";; 
*************************- : unit =() 

Aquí hay una confusión similar. Los asteriscos * están escritos por print_string. El resto muestra el resultado, que nuevamente es del tipo unit con el valor ().

# let p4 = print_int 4;; 
4val p4 : unit =() 

Lo mismo aquí. El 4 está escrito por print_int. El resto muestra que el nivel superior ha definido un símbolo llamado p4 cuyo tipo es unit y cuyo valor es (). De nuevo, esto tiene sentido porque print_int devuelve unit tipo y () es el único valor de ese tipo. Puede decir por el tipo de p4 que es no una función. Las funciones tienen una flecha (->) en el tipo. p4 es solo un valor de tipo unit.

# p4;; 
- : unit =() 

Aquí piden al más alto nivel para el tipo y valor de p4, y se le dice (de nuevo) que es de tipo p4unit y tiene el valor ().

2

Su última pregunta es cómo se usa () para "ocultar un efecto secundario". Probablemente se esté refiriendo a la evaluación demorada de una función. Aquí está un ejemplo:

let p x = print_string "abc";; 
let q = print_string "abc";; 

Hay una diferencia crucial entre p y q. La diferencia es que p es una función de tipo 'a -> unit mientras que q es un valor de tipo unit. Cuando define p, no se imprime nada. La cadena "abc" se imprimirá solo cuando aplique la función p a un argumento, es decir, cuando evalúe p 1 o p "blah" o lo que sea. (La función p toma argumentos de cualquier tipo y los ignora). Por lo tanto, en el caso de p, ha "ocultado un efecto secundario" dentro de la función.

No tiene sentido tener un argumento, "x", en la definición de "p x", ya que "x" no se usa en absoluto. Entonces, para simplificar, se usa el tipo "unidad", de modo que la definición de "p" se parece a "let p() = ...". Es lo mismo que

let p = fun() -> print_string "abc";; 

La función "p" se utiliza como "p()". Esto puede ser confuso si primero aprendió lenguajes de programación como C, Java, etc., donde() se usan para argumentos de todas las funciones. Pero en OCAML, () es un símbolo especial que denota un "valor vacío", y este valor tiene un tipo especial llamado "unidad".Lo

Un totalmente diferente sucede como se define q: la cadena "abc" se imprime de inmediato, ya que este es el efecto secundario de la evaluación "print_string", y q se hace igual a (), ya () es el valor resultante obtenido al evaluar "print_string".

0

llego tarde a la fiesta, pero quiero señalar que el uso de () en

let p5() = print_int 5 

Tiene un patrón de coincidencia en el argumento de p5. Es equivalente a esto:

let p5 x = match x with() -> print_int 5 

O esto:

let p5 = function() -> print_int 5 

O incluso esto:

let p5 = fun x -> match x with() -> print_int 5 

Esta distinción es importante en el siguiente código:

let f (x, y) = print_int (x + y) 
let g x y = print_int (x + y) 

f recibe solo un parámetro (el par (x, y)), mientras que g recibe dos parámetros. f tiene el tipo (int * int) -> unit y g tiene el tipo int -> int -> unit. Así f podría escribirse así:

let f pair = match pair with (x, y) -> print_int (x + y)