Как Ocaml решает приоритет для пользовательских операторов?
Я хочу, чтобы хорошие операторы для сложной арифметики сделали мой код более удобочитаемым. Ocaml имеет комплексный модуль, поэтому я просто хочу добавить операторов, которые называют эти функции.
Самый интуитивный способ для меня - создать новый сложный оператор из всех обычных операторов, добавив '&' к символу оператора. Таким образом, + & и * & будет сложным сложение и умножение. Мне также хотелось бы ~ & быть сложным сопряжением.
Если я собираюсь использовать эти операторы, я хочу, чтобы они связывались так же, как и обычные арифметические отношения. Основываясь на следующих сеансах, они автоматически ведут себя так, как я хочу, но я хотел бы понять, почему, так что я не получаю ужасных ошибок при введении большего числа операторов.
Мое последнее предположение заключается в том, что их приоритет выполняется путем лексической сортировки символов оператора в соответствии с порядком, который согласуется с обычным арифметическим приоритетом. Но я не могу это подтвердить.
Первый сеанс:
# 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.}
Ответы
Ответ 1
В общем случае ассоциативность и приоритет оператора (если вы не выходите на camlp4 или что-то еще) основывается на первом символе оператора.
источник (ищите "приоритет ассоциативности для пользовательского оператора" ).
Невозможно определить его явно в OCaml (см. this, а также "Пользовательские операторы infix" на Сравнение Objective Caml и стандартного ML)
Вы можете использовать camlp4 или camlp5 для явного определения порядка функции infix. Кажется, что pa_do также может быть вариантом.
Я попытался написать пример, но я не знаком с camlp4, и это нелегко узнать за несколько минут.
Ответ 2
В руководстве OCaml, раздел 6.7, прокрутите вниз, прямо перед разделом 6.7.1. В таблице приоритета есть некоторые вещи, такие как +...
, который включает любые пользовательские значения, начинающиеся с +
. Неверно, что он всегда зависит от первого символа, поскольку **...
имеет более высокий приоритет, чем *...
.
Ответ 3
Расширение синтаксиса pa-do для OCaml адресует именно эту проблему:
http://pa-do.forge.ocamlcore.org/
Вы можете использовать его для изменения приоритета оператора или, что более полезно в этом случае, использовать явный контекст для изменения значения операторов.