2011-10-10 45 views
5

我在ocaml的顶层评价一个非常简单的代码:括号OCaml中

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

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

let p4 = print_int 4;; 
p4;; 

,并返回:

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

我的问题是

  1. 什么()平均在let p5() = print_int 5;;
  2. -()是什么意思?# 5- : unit =()
  3. p4的一个函数吗?
  4. 为什么在# 4val p4 : unit =()的开头有4
  5. 看来()可以在Ocaml代码中用来隐藏副作用,任何人都可以给我一个例子吗?
+1

'print_endline',而不是'print_string'因为它会自动打印后的底线 – newacct

回答

11

这里一些答案:

  1. ()是单元类型值。单位类型是只有一个值的类型。这通常用于产生无意义或无意义的函数。请记住,在OCaml中,所有函数都必须返回一些内容并采取一些参数,因此单位类型用于解决此限制。可以考虑类似于C,C++或Java中的void类型。
  2. 有两行交错。 5print_int函数打印,而不是由顶层打印。顶层只是返回- : unit =()没有5。顶层告诉你,它没有创建任何新的绑定-,最后返回的值是unit类型,其值为()
  3. 不会。它没有任何参数,所以它不是一个函数。
  4. 再次有两行交错。 4print_int函数打印。此时,顶层告诉你,它创建了一个新的绑定p4,该变量的值为unit,存储的值为()
  5. 不,()不用于隐藏副作用。它通常用于创建具有副作用的函数,因此不需要采取任何形式的论证。
6

LiKao已经解释了所有的关键点,但是我认为如果您一次一行地输入您的定义,这将显示哪些回答来自哪些输入,这可能会更有意义。该人输入的行从#开始。

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

这P5定义为接受unit类型的值,并返回unit类型的值的函数。类型单位只有一个值,写为()。所以这些就是你问的括号(我认为)。请注意,出现在您的定义中的()是该函数接受的值的模式。作为一种模式,()匹配自身(就像所有用作模式的常量)。

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

这有点令人困惑。 5由您的函数p5编写。其余的是OCaml顶级响应。这是说你的表情的结果是unit类型,其值为()。它是有道理的,print_intint -> unit类型。

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

这里也有类似的混淆。星号*print_string编写。其余显示结果,该结果同样是unit,其值为()

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

这里是一样的东西。 4print_int编写。其余显示顶级已定义了一个名为p4的符号,其类型为unit,其值为()。再一次,这是有道理的,因为print_int返回unit类型和()是该类型的唯一值。你可以从p4的类型中知道它是而不是的一个函数。函数在类型中有一个箭头(->)。 p4只是unit类型的值。

# p4;; 
- : unit =() 

在这里,你问顶级的类型和p4价值,而且它(再次)告诉你p4unit类型的并具有价值()

2

您最后的问题是如何使用()“隐藏副作用”。您可能指的是功能的延迟评估。这里有一个例子:

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

pq之间的关键区别。区别在于p是类型'a -> unit的函数,而q是类型unit的值。当您定义p时,不会打印任何内容。字符串“abc”仅在您将函数p应用于参数时才会打印,即,当您评估p 1p "blah"或其他任何内容时。 (函数p需要任何类型的参数并忽略它们。)因此,在p的情况下,您在函数内部“隐藏了一个副作用”。

在“p x”的定义中有一个参数“x”是没有意义的,因为根本不使用“x”。所以为了简单起见,使用“unit”类型,以便“p”的定义看起来像“let p()= ...”。这与

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

函数“p”然后被用作“p()”。如果您第一次学习像C,Java等编程语言,其中()用于所有函数的参数,这可能会引起混淆。但在OCAML中,()是一个表示“空值”的特殊符号,该值有一个称为“单位”的特殊类型。

一个完全不同的事情发生在定义q:字符串“abc”被印刷向右走,因为这是评估“print_string”的副作用,和q变得等于(),由于()是所得到的值通过评估“print_string”获得。

0

我迟到了,但我想在

let p5() = print_int 5 

指出,使用()具有在p5参数匹配的模式。这是该等效:

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

或者这样:

let p5 = function() -> print_int 5 

甚至这样的:

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

这种区别是在下面的代码很重要:

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

f只接收一个参数(对(x, y)),而g接收两个参数。 f因此具有类型(int * int) -> unitg具有类型int -> int -> unit。所以f可以这样写:

let f pair = match pair with (x, y) -> print_int (x + y) 
你可能要习惯使用