Ocaml 中的括号

发布于 2024-12-09 01:19:14 字数 700 浏览 0 评论 0原文

我正在 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 = ()

我的问题是

  1. ()let p5 () = print_int 5;; 中意味着什么?
  2. # 5- : unit = () 中的 -() 是什么意思?
  3. p4 是一个函数吗?
  4. 为什么#4val p4 : unit = ()开头有一个4
  5. 似乎 () 可以在 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

  1. What does () mean in let p5 () = print_int 5;;?
  2. What do - and () mean in # 5- : unit = ()?
  3. Is p4 a function?
  4. Why is there a 4 in the beginning of # 4val p4 : unit = ()?
  5. It seems that () could be used in Ocaml code to hide side effect, could anyone show me an example?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

瞎闹 2024-12-16 01:19:14

这里有一些答案:

  1. () 是单位类型值。单位类型是一种只有一个值的类型。这通常用于生成不返回任何有意义的内容或不获取任何有意义的内容的函数。请记住,在 OCaml 中,所有函数始终必须返回某些内容并接受一些参数,因此单元类型用于绕过此限制。将此视为类似于 C、C++ 或 Java 中的 void 类型。
  2. 有两条线交错。 5print_int 函数打印,而不是由顶层打印。顶层仅返回 - : unit = () 而不带 5。顶层告诉您它没有创建任何新的绑定 - 并且最后返回的值是 unit 类型并且具有值 ()
  3. 不。它不带任何参数,因此它不是一个函数。
  4. 再次有两条线交错。 4print_int 函数打印。此时,顶层告诉您,它创建了一个新的绑定p4,该变量携带unit类型的值,并且存储的值为()
  5. 不,() 不用于隐藏副作用。它通常用于创建具有副作用的函数,因此不需要采用任何类型的参数。

Here some answers:

  1. () 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 the void type in C, C++ or Java.
  2. There are two lines interleaved. The 5 is printed by the print_int function and not by the toplevel. The toplevel just returns - : unit = () without the 5. The toplevel is telling you that it did not create any new bindings - and that the last returned value is of type unit and has the value ().
  3. No. It does not take any arguments, so it is not a function.
  4. Again there are two lines interleaved. The 4 is printed by the print_int function. At this time, the toplevel is telling you, that it created a new binding p4, that this variable carries a value of type unit and that the stored value is ().
  5. No, () 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.
岁月苍老的讽刺 2024-12-16 01:19:14

LiKao 已经解释了所有关键点,但我认为如果您一次一行输入定义可能会更有意义,这将显示哪些响应来自哪些输入。用户输入的行以# 开头。

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

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

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

这有点令人困惑。 5 由您的函数 p5 编写。剩下的就是 OCaml 高层的回应。它表示表达式的结果属于 unit 类型,并且值为 ()。这是有道理的, print_int 的类型是 int ->;单位。

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

这里也有类似的困惑。星号*print_string写入。其余部分显示结果,该结果也是 unit 类型,值为 ()

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

这里同样的事情。 4是由print_int编写的。其余部分显示顶层定义了一个名为 p4 的符号,其类型为 unit,其值为 ()。同样,这是有道理的,因为 print_int 返回 unit 类型,而 () 是该类型的唯一值。您可以从 p4 的类型看出它不是一个函数。函数的类型中有一个箭头 (->)。 p4 只是一个 unit 类型的值。

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

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

This defines p5 as a function that accepts values of type unit and returns values of type unit. 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).

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

This is a little confusing. The 5 is written by your function p5. The rest is the response from the OCaml top-level. It's saying that the result of your expression is of type unit and has the value (). It makes sense, print_int is of type int -> unit.

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

There's a similar confusion here. The asterisks * are written by print_string. The rest shows the result, which again is of type unit with value ().

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

Same thing here. The 4 is written by print_int. The rest shows that the top level has defined a symbol named p4 whose type is unit and whose value is (). Again, this makes sense because print_int returns unit type and () is the only value of that type. You can tell from the type of p4 that it is not a function. Functions have an arrow (->) in the type. p4 is just a value of type unit.

# p4;;
- : unit = ()

Here you ask the top-level for the type and value of p4, and it tells you (again) that p4 is of type unit and has the value ().

梦幻的心爱 2024-12-16 01:19:14

您的最后一个问题是如何使用 () 来“隐藏副作用”。您可能指的是函数的延迟评估。下面是一个例子:

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

pq 之间有一个至关重要的区别。不同之处在于 p'a ->; 类型的函数。 unitqunit 类型的值。当您定义 p 时,不会打印任何内容。仅当您将函数 p 应用于参数时,即当您计算 p 1p "blah" 时,才会打印字符串“abc” > 或其他什么。 (函数p接受任何类型的参数并忽略它们。)因此,在p的情况下,您在函数内部“隐藏了副作用”。

在“p x”的定义中使用参数“x”是没有意义的,因为根本没有使用“x”。因此,为了简单起见,使用了“unit”类型,因此“p”的定义看起来像“let p () = ...”。 相同

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

这与函数“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:

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

There is a crucial difference between p and q. The difference is that p is a function of type 'a -> unit while q is a value of type unit. When you define p, nothing is printed. The string "abc" will be printed only when you apply the function p to an argument, i.e. when you evaluate p 1 or p "blah" or whatever. (The function p takes arguments of any type and ignores them.) So in the case of p, 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

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

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", and q becomes equal to (), since () is the resulting value obtained by evaluating "print_string".

伴随着你 2024-12-16 01:19:14

我迟到了,但我想指出,在

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 ->整数->单位。所以 f 可以这样写:

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

I am late to the party, but I want to point out that using () in

let p5 () = print_int 5

Has a pattern matching in the argument of p5. It is equivalent of this:

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

Or this:

let p5 = function () -> print_int 5

Or even this:

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

This distinction is important in the following code:

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

f receives only one parameter (the pair (x, y)), while g receives two parameters. f thus has the type (int * int) -> unit and g has the type int -> int -> unit. So f could be written like this:

let f pair = match pair with (x, y) -> print_int (x + y)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文