当前位置: 首页 > 知识库问答 >
问题:

表达式、顺序的OCaml评估?

傅英喆
2023-03-14

add是OCaml内置的函数。

经验:

# add 5 1;;
- : int = 6

我的问题:add 3(add 5 3)的求值顺序是什么?

# add 3 (add 5 3);;
- : int = 11

是先将(add 5 3)求值为8,然后将add 3(8)求值为11?还是先将add 3求值为函数,然后将(add 5 3)用作函数(add 3)的参数?

谢谢

共有3个答案

方高丽
2023-03-14

OCaml中参数的计算顺序未指定,这意味着它可以从一个编译器更改到另一个编译器。

让我们创建一个分两个阶段评估的函数

let mul a =
  Printf.printf "got a: %i\n%!" a;
  fun b ->
    Printf.printf "got b: %i\n%!" b;
    a * b

使用utop(或ocaml)运行此操作将显示从右到左的评估:

# mul (mul 2 3) (mul 5 7);;
got a: 5
got b: 7
got a: 2
got b: 3
got a: 6
got b: 35
- : int = 210

可以在中引入let-来强制计算顺序,从而产生不同的printf序列:

# let mul6 = mul (mul 2 3) in mul6 (mul 5 7);;
got a: 2
got b: 3
got a: 6
got a: 5
got b: 7
got b: 35
- : int = 210

高迪
2023-03-14

为了完成Jeffrey的回答,这里有一个版本的add,可以让你知道它何时被执行:

# let add a b =
    Printf.printf "Adding %d and %d...\n" a b;
    a + b;;

val add : int -> int -> int = <fun>

让我们看看它的实际行动。

# add (add 1 2) (add 5 8);;

Adding 5 and 8...
Adding 1 and 2...
Adding 3 and 13...

- : int = 16

所以在这里,第二个add首先被计算,但是你不能指望它,因为它没有被指定。

下面是使用本地let强制订单的相同示例:

# let x = add 1 2 in
  add x (add 5 8);;

Adding 1 and 2...
Adding 5 and 8...
Adding 3 and 13...

- : int = 16

现在使用部分应用程序。

# let add_3 = add 3 in
  add_3 (add 5 8);;

Adding 5 and 8...
Adding 3 and 13...

- : int = 16

当然,对于(纯)函数式编程,执行顺序并不重要,因为一切都是不变的。但是OCaml并不是纯功能性的,所以这些小技巧是很好了解的。:)

越安翔
2023-03-14

值得一提的是,OCaml中没有内置名为add的函数。(也就是说,渗透模块中没有这样的符号。)

$ ocaml
        OCaml version 4.06.0

# add;;
Error: Unbound value add

OCaml中函数及其参数的求值顺序未指定。所以没有保证的秩序。

OCaml手册第7.7.1节对此进行了记录。

如果你想让一个计算按照一定的顺序进行,你可以使用let来计算每个子表达式

# let add a b = a + b;;
val add : int -> int -> int = <fun>
# let temp = add 5 3 in
  add 3 temp;;
- : int = 11
# let tempf = add 3 in
  tempf (add 5 3);;
- : int = 11
 类似资料:
  • 问题内容: 假设我有以下表达式 Eclipse警告我,布尔表达式的第二个短语中可能为空。但是,我知道有些人会在第一个条件失败的情况下完全退出布尔表达式。Java是否正确?还是不能保证评估顺序? 问题答案: 但是,我知道有些人会在第一个条件失败的情况下完全退出布尔表达式。Java是否正确? 是的,这就是所谓的短路评估。操作员喜欢和是执行此类操作的操作员。 还是不能保证评估顺序? 不,可以保证评估的顺

  • 本文向大家介绍OCaml 布尔表达式的求值,包括了OCaml 布尔表达式的求值的使用技巧和注意事项,需要的朋友参考一下 示例 我们定义布尔表达式的类型,其原子由字符串标识为 并可以通过oracle : string -> bool给出原子的值来评估这些表达式,如下所示: 了解该功能如何清晰易读。由于正确使用了模式匹配,因此读取此功能的程序员只需很少的时间即可确保其正确实现。

  • 问题内容: 我有以下代码片段: 我知道在C ++中,您被教导不要依赖子表达式的求值顺序,因为它不能保证完全是任何顺序。因此,此代码将是错误的,并且不能保证条件中表达式所产生的布尔值是真实的(例如,可以在第一次等式测试中对y进行递增运算)。由于我是在Java认证书中阅读此代码的,因此我认为Java并非如此。.我的意思是,我是否保证Java的评估顺序始终是从左到右?因此,以上表达式应始终为true。

  • 我有以下代码片段: 我知道在C++中,你被教导不要依赖子表达式的求值顺序,因为它不能保证是任何顺序。因此这段代码是错误的,并且条件中的表达式所产生的布尔值不能保证为真(例如,在第一个相等性测试中计算y之前,可以增加y)。因为我是在Java认证书上读到这段代码的,所以我假设Java不是这样的。我的意思是,我能保证Java的计算顺序总是从左到右吗?所以上面的表达式应该总是产生true。

  • 问题内容: 什么是实现将采用字符串并根据运算符优先级输出结果的python程序的最佳方法(例如:“ 4 + 3 * 5”将输出19)。我在谷歌上寻找解决这个问题的方法,但是它们都太复杂了,我正在寻找一个(相对)简单的方法。 澄清:我需要比eval()稍微先进的东西-我希望能够添加其他运算符(例如,最大运算符-4 $ 2 = 4),或者,我对此在学术上比对专业更感兴趣-我想知道 该怎么 做。 问题答

  • 本文向大家介绍评估后缀表达式,包括了评估后缀表达式的使用技巧和注意事项,需要的朋友参考一下 为了求解数学表达式,我们需要前缀或后缀形式。将中缀转换为后缀后,我们需要后缀评估算法来找到正确的答案。 在这里,我们还必须使用堆栈数据结构来解决后缀表达式。 从后缀表达式中,找到一些操作数后,将它们压入堆栈。找到某个运算符后,将从堆栈中弹出两个项目,并按正确的顺序执行操作。之后,结果也被压入堆栈中以备将来使