【问题标题】:Redefine the infix operators重新定义中缀运算符
【发布时间】:2012-12-03 15:20:27
【问题描述】:

我正在学习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我说的对吗?

【问题讨论】:

    标签: functional-programming ocaml


    【解决方案1】:

    对我来说,这些功能似乎是在一种不确定的状态下运行 循环,因为所有操作似乎都重新定义并相互关联。

    并非如此,它只是同时重新定义中缀运算符(使用 and 关键字)。您看到的是不是递归定义。在 OCaml 中,使用 let rec 进行递归定义(您可能已经知道)。

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

    【讨论】:

    • 所以你的意思是如果我使用let rec,那么答案就不一样了?我的意思是它会是我想象的那样?
    • @JacksonTale:是的,但是您不能按原样使用rec 来定义这个定义(我试过了,编译器不喜欢它)。相反,您必须使用let (+) x y = x * y and ...。但是您对结果是正确的,我以这种方式重新定义了运算符,然后它进入了循环。干杯!
    【解决方案2】:

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

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

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

    【讨论】:

    • +1,我认为即使我们通过重新定义来改变+ 的“含义”,我们也无法改变它的关联性,这是由表达式的静态形式决定的(按照规定根据您指出的表格)。干杯!
    • 对,优先级和关联性都是固定的,基于运算符的第一个字符。我会更新我的答案。
    猜你喜欢
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-10
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    相关资源
    最近更新 更多