Ocaml 中的括号
我正在 Ocaml toplevel 中评估一段非常简单的代码:
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 = ()
我的问题是
()
在let p5 () = print_int 5;;
中意味着什么?# 5- : unit = ()
中的-
和()
是什么意思?p4
是一个函数吗?- 为什么
#4val p4 : unit = ()
开头有一个4
? - 似乎
()
可以在 Ocaml 代码中使用来隐藏副作用,有人能给我举个例子吗?
I am evaluating a very simple piece of code in Ocaml toplevel:
let p5 () = print_int 5;;
p5 ();;
print_string "*************************";;
let p4 = print_int 4;;
p4;;
And it returns:
val p5 : unit -> unit = <fun>
# 5- : unit = ()
# *************************- : unit = ()
# 4val p4 : unit = ()
# - : unit = ()
My questions are
- What does
()
mean inlet p5 () = print_int 5;;
? - What do
-
and()
mean in# 5- : unit = ()
? - Is
p4
a function? - Why is there a
4
in the beginning of# 4val p4 : unit = ()
? - It seems that
()
could be used in Ocaml code to hide side effect, could anyone show me an example?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这里有一些答案:
()
是单位类型值。单位类型是一种只有一个值的类型。这通常用于生成不返回任何有意义的内容或不获取任何有意义的内容的函数。请记住,在 OCaml 中,所有函数始终必须返回某些内容并接受一些参数,因此单元类型用于绕过此限制。将此视为类似于 C、C++ 或 Java 中的void
类型。5
由print_int
函数打印,而不是由顶层打印。顶层仅返回- : unit = ()
而不带5
。顶层告诉您它没有创建任何新的绑定-
并且最后返回的值是unit
类型并且具有值()
。4
由print_int
函数打印。此时,顶层告诉您,它创建了一个新的绑定p4
,该变量携带unit
类型的值,并且存储的值为()
。()
不用于隐藏副作用。它通常用于创建具有副作用的函数,因此不需要采用任何类型的参数。Here some answers:
()
is the unit type value. The unit type is a type with only one value. This is usually used to produce functions which either return nothing meaningful or take nothing meaningful. Remember, that in OCaml all functions alway have to return something and take some arguments, so the unit type is used to get around this limitation. Think of this similar to thevoid
type in C, C++ or Java.5
is printed by theprint_int
function and not by the toplevel. The toplevel just returns- : unit = ()
without the5
. The toplevel is telling you that it did not create any new bindings-
and that the last returned value is of typeunit
and has the value()
.4
is printed by theprint_int
function. At this time, the toplevel is telling you, that it created a new bindingp4
, that this variable carries a value of typeunit
and that the stored value is()
.()
is not used to hide side effects. It is usually used to create functions, which have side effects, and thus need not take any kind of argument.LiKao 已经解释了所有关键点,但我认为如果您一次一行输入定义可能会更有意义,这将显示哪些响应来自哪些输入。用户输入的行以
#
开头。这将 p5 定义为接受
unit
类型的值并返回unit
类型的值的函数。 Unit 类型只有一个值,写为()
。所以这些正是您要问的括号(我认为)。请注意,定义中出现的()
是函数接受的值的模式。作为模式,()
匹配自身(就像所有用作模式的常量一样)。这有点令人困惑。
5
由您的函数p5
编写。剩下的就是 OCaml 高层的回应。它表示表达式的结果属于unit
类型,并且值为()
。这是有道理的,print_int
的类型是int ->;单位。
这里也有类似的困惑。星号
*
由print_string
写入。其余部分显示结果,该结果也是unit
类型,值为()
。这里同样的事情。
4
是由print_int
编写的。其余部分显示顶层定义了一个名为p4
的符号,其类型为unit
,其值为()
。同样,这是有道理的,因为print_int
返回unit
类型,而()
是该类型的唯一值。您可以从p4
的类型看出它不是一个函数。函数的类型中有一个箭头 (->
)。p4
只是一个unit
类型的值。在这里,您向顶层询问
p4
的类型和值,它(再次)告诉您p4
的类型为unit
并且值为()
。LiKao has explained all the key points already, but I thought it might make more sense if you entered your definitions one line at a time, which would show which responses come from which inputs. Lines entered by the person start with
#
.This defines p5 as a function that accepts values of type
unit
and returns values of typeunit
. There's only one value of type unit, which is written as()
. So these are exactly the parentheses you are asking about (I think). Note that the()
appearing in your definition is a pattern for the values accepted by the function. As a pattern,()
matches itself (like all constants used as patterns).This is a little confusing. The
5
is written by your functionp5
. The rest is the response from the OCaml top-level. It's saying that the result of your expression is of typeunit
and has the value()
. It makes sense,print_int
is of typeint -> unit
.There's a similar confusion here. The asterisks
*
are written byprint_string
. The rest shows the result, which again is of typeunit
with value()
.Same thing here. The
4
is written byprint_int
. The rest shows that the top level has defined a symbol namedp4
whose type isunit
and whose value is()
. Again, this makes sense becauseprint_int
returnsunit
type and()
is the only value of that type. You can tell from the type ofp4
that it is not a function. Functions have an arrow (->
) in the type.p4
is just a value of typeunit
.Here you ask the top-level for the type and value of
p4
, and it tells you (again) thatp4
is of typeunit
and has the value()
.您的最后一个问题是如何使用
()
来“隐藏副作用”。您可能指的是函数的延迟评估。下面是一个例子:p
和q
之间有一个至关重要的区别。不同之处在于p
是'a ->; 类型的函数。 unit
而q
是unit
类型的值。当您定义p
时,不会打印任何内容。仅当您将函数p
应用于参数时,即当您计算p 1
或p "blah"
时,才会打印字符串“abc” > 或其他什么。 (函数p
接受任何类型的参数并忽略它们。)因此,在p
的情况下,您在函数内部“隐藏了副作用”。在“p x”的定义中使用参数“x”是没有意义的,因为根本没有使用“x”。因此,为了简单起见,使用了“unit”类型,因此“p”的定义看起来像“let p () = ...”。 相同
这与函数“p”随后用作“p()” 。如果您第一次学习 C、Java 等编程语言,这可能会令人困惑,其中 () 用于所有函数的参数。但在 OCAML 中,
()
是一个特殊符号,表示“空值”,而这个值有一个特殊的类型,称为“unit”。当您定义
q
时,会发生完全不同的事情:字符串“abc”立即被打印,因为这是评估“print_string”的副作用,并且q
变成等于()
,因为()
是通过评估“print_string”获得的结果值。Your last question is how
()
is used to "hide a side-effect". You are probably referring to the delayed evaluation of a function. Here is an example:There is a crucial difference between
p
andq
. The difference is thatp
is a function of type'a -> unit
whileq
is a value of typeunit
. When you definep
, nothing is printed. The string "abc" will be printed only when you apply the functionp
to an argument, i.e. when you evaluatep 1
orp "blah"
or whatever. (The functionp
takes arguments of any type and ignores them.) So in the case ofp
, you have "hidden a side-effect" inside the function.It is pointless to have an argument, "x", in the definition of "p x", since "x" is not used at all. So for simplicity the type "unit" is used, so that the definition of "p" looks like "let p () = ...". This is the same as
The function "p" is then used as "p ()". This may be confusing if you first learned programming languages like C, Java, etc., where () are used for arguments of all functions. But in OCAML,
()
is a special symbol that denotes an "empty value", and this value has a special type called "unit".A totally different thing happens as you define
q
: the string "abc" is printed right away, since this is the side-effect of evaluating "print_string", andq
becomes equal to()
, since()
is the resulting value obtained by evaluating "print_string".我迟到了,但我想指出,在
p5
的参数中使用()
具有模式匹配。它相当于这样:或这样:
甚至这样:
这种区别在以下代码中很重要:
f
仅接收一个参数(一对(x, y)
) ,而g
接收两个参数。f
因此具有类型(int * int) -> unit
和g
的类型为int ->整数->单位。所以
f
可以这样写:I am late to the party, but I want to point out that using
()
inHas a pattern matching in the argument of
p5
. It is equivalent of this:Or this:
Or even this:
This distinction is important in the following code:
f
receives only one parameter (the pair(x, y)
), whileg
receives two parameters.f
thus has the type(int * int) -> unit
andg
has the typeint -> int -> unit
. Sof
could be written like this: