Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Ocaml decide precedence for user-defined operators?

Tags:

ocaml

I want nice operators for complex arithmetic to make my code more readable. Ocaml has a Complex module, so I just want to add operators that call those functions.

The most intuitive way for me is to make a new complex operator from all of the usual operators by appending '&' to the operator symbol. Thus +& and *& will be complex addition and multiplication. I would also like ~& to be complex conjugation.

If I'm going to use these operators, I want them to associate the same way that normal arithmetic associates. Based on the following sessions, they are automatically behaving the way I want, but I would like to understand why, so that I don't get horrible bugs when I introduce more operators.

My current guess is that their precedence is done by lexically sorting the operator symbols according to an ordering that is consistent with normal arithmetic precedence. But I cannot confirm this.

Session one:

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

Session two:

# 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.}
like image 593
forefinger Avatar asked Jun 05 '10 20:06

forefinger


2 Answers

It's right in the OCaml manual, section 6.7, scroll down, right before section 6.7.1. The precedence table has some things like +..., which includes any user-defined starting with +. It is not true that it always depends on the first character, as **... has higher precedence than *....

like image 52
newacct Avatar answered Dec 02 '22 12:12

newacct


In general, the associativity and precedence of an operator (unless you go out to camlp4 or something) is based on the operator's first character.

source (look for for "Associativity precedence for the user-defined operator").

There is no way to define it explicitly in OCaml (see this and also "User-defined infix operators" on Comparing Objective Caml and Standard ML)

You can use camlp4 or camlp5 to explicitly define the order of infix function. It seems like pa_do can also be an option.

I tried to write an example but I am not familiar with camlp4 and it is not easy to learn in a few minutes.

like image 45
dbarbosa Avatar answered Dec 02 '22 12:12

dbarbosa