我想要很好的运算符来进行复杂的算术运算,使我的代码更具可读性。 Ocaml有一个Complex模块,所以我只想添加调用这些函数的运算符。
对我来说,最直观的方法是通过附加'&'来从所有常规操作员创建一个新的复杂操作员到操作员符号。因此+&和*&将是复杂的加法和乘法。我也想〜&是复杂的共轭。
如果我要使用这些运算符,我希望它们与普通算术关联的方式相关联。基于以下会话,它们会按照我想要的方式自动运行,但我想了解原因,以便在引入更多运算符时不会出现可怕的错误。
我目前的猜测是,它们的优先级是通过根据与正常算术优先级一致的排序对运算符符号进行词法排序来完成的。但我无法证实这一点。
第一节:
# open Complex;;
# let (+&) a b = add a b;;
val ( +& ) : Complex.t -> Complex.t -> Complex.t = <fun>
# let ( *&) a b = mul a b;;
val ( *& ) : Complex.t -> Complex.t -> Complex.t = <fun>
# one +& zero *& one +& zero *& one;;
- : Complex.t = {re = 1.; im = 0.}
# zero +& one *& zero +& one *& zero;;
- : Complex.t = {re = 0.; im = 0.}
# i +& i *& i +& i *& i *& i;;
- : Complex.t = {re = -1.; im = 0.}
第二节:
# open Complex;;
# let ( *&) a b = mul a b;;
val ( *& ) : Complex.t -> Complex.t -> Complex.t = <fun>
# let (+&) a b = add a b;;
val ( +& ) : Complex.t -> Complex.t -> Complex.t = <fun>
# one +& zero *& one +& zero *& one;;
- : Complex.t = {re = 1.; im = 0.}
# zero +& one *& zero +& one *& zero;;
- : Complex.t = {re = 0.; im = 0.}
# i +& i *& i +& i *& i *& i;;
- : Complex.t = {re = -1.; im = 0.}
# let (~&) a = conj a;;
val ( ~& ) : Complex.t -> Complex.t = <fun>
# (one +& i) *& ~& (one +& i);;
- : Complex.t = {re = 2.; im = 0.}
答案 0 :(得分:14)
在OCaml手册section 6.7中,向下滚动,就在第6.7.1节之前。优先级表包含+...
之类的内容,其中包含用+
开头的任何用户定义的开头。它始终取决于第一个字符并不正确,因为**...
的优先级高于*...
。
答案 1 :(得分:13)
通常,运算符的关联性和优先级(除非你转到camlp4或其他东西)是基于运算符的第一个字符。
source(寻找“用户定义的运算符的关联性优先级”)。
无法在OCaml中明确定义它(请参阅this上的Comparing Objective Caml and Standard ML以及“用户定义的中缀运算符”)
您可以使用camlp4或camlp5明确定义中缀函数的顺序。似乎pa_do也可以是一种选择。
我试着写一个例子,但我不熟悉camlp4,并且在几分钟内学习起来并不容易。
答案 2 :(得分:3)
OCaml的pa-do语法扩展正好解决了这个问题:
http://pa-do.forge.ocamlcore.org/
您可以使用它来更改运算符优先级,或者更有用的是,在这种情况下,使用显式上下文来更改运算符的含义。