重新定义中缀运算符

时间:2012-12-03 15:20:28

标签: functional-programming ocaml

我正在学习Jason Hickey's Introduction to Objective Caml

关于重新定义中缀运算符的问题。


所以在书中,有这样一段:

# let (+) = ( * )
      and (-) = (+)
      and ( * ) = (/)
      and (/) = (-);;
  val + : int > int > int = <fun>
  val - : int > int > int = <fun>
  val * : int > int > int = <fun>
  val / : int > int > int = <fun>
# 5 + 4 / 1;;
-: **int = 15**

首先,这些重新定义是如何工作的?

对我而言,似乎函数在一种无限循环中运行,因为所有操作似乎都被重新定义和连接。

例如,如果我1+2,那么它将是1 * 2,从( * ) = (/)起,它将是1 / 2,然后是(/) = (-),那么它将是1-2,依此类推。 我是对的吗?


其次,5 + 4 / 1的结果是否为15,即使这些功能在重新定义中只执行了一步?

因此,假设重新定义将进一步执行,即1 + 2只会1 * 2而不再有变换,因此5 + 4 / 1应为5 * 4 -1,对吧?然后答案是19我说错了吗?

2 个答案:

答案 0 :(得分:6)

  

对我而言,似乎功能正在以某种无限的方式运行   循环,因为所有操作似乎都被重新定义和连接。

实际上,它只是同时重新定义中缀运算符(使用and关键字)。你看到的是递归定义。在OCaml中,使用 let rec 进行递归定义(正如您可能已经知道的那样)。

对于问题的第二部分,我认为这是运算符优先级的问题。请注意,原始表达式5 + 4 / 1实际上是5 + (4/1),遵循算术运算符的常规优先规则。所以,我认为转换只是保留了这种绑定(有点)。你得到5 * (4 - 1) = 15

答案 1 :(得分:3)

关键观察(恕我直言)是(+)( * )预先存在的定义定义,而不是由稍后出现几行的定义。同样,( * )预先存在的定义(/)定义。正如Asiri所说,这是因为使用let而不是let rec

在OCaml中,优先级和关联性在运算符中是固有的,并且不能通过定义来更改。优先级和关联性由运算符的第一个字符决定。

如果查看Section 6.7 of the OCaml Manual中的运算符优先级和关联性表,您将看到所有条目都是为“以字符X开头的运算符”定义的。