# On adjoints and custom postfix and infix operators

**URL:** <https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863>\
**Category:** Internals & Design\
**Created:** [August 3, 2018, 7:24am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863 "2018-08-03T07:24:25Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 4, 2018, 7:24am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/41 "2018-08-04T07:24:58Z")

</div>

> [@chakravala](#):
>
> I’d rather stay within the Julia environment than to switch to another language only because operator precedence cannot be set.

I am not sure I understand why custom precendence is so important for you.

Very few programmers remember the precedence tables in full, most people just rely on a few rules and use `()`s for explicit grouping. Precendence mistakes are frequently a source of bugs, some style guides discourage relying on precedence altogether, eg [the Google JS style guide](https://google.github.io/styleguide/jsguide.html#formatting-grouping-parentheses) says:

> Optional grouping parentheses are omitted only when the author and reviewer agree that there is no reasonable chance that the code will be misinterpreted without them, nor would they have made the code easier to read. It is _not_ reasonable to assume that every reader has the entire operator precedence table memorized.

I am sure customizing precendence could be useful occasionally, but at the same time it could make these bugs an order of magnitude worse.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [August 4, 2018, 7:56am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/42 "2018-08-04T07:56:14Z")

</div>

> [@stevengj](#):
>
> Just take `*` (or one of the above) and add one or more of any of the allowed operator suffixes in Julia 0.7, e.g. `*̂₁ᵃ′` is an operator with the same precedence as `*` .

Shouldn’t variable names beginning with those characters have been deprecated before they became allowed as operator suffixes. For example in Julia 0.6 the following is legal syntax:

```julia
ᵃx = 3
1+ᵃx # returns 4

```

but in Julia 0.7 it gives `UndefVarError` because it parses as `1 +ᵃ x`.

Edit: I opened an issue on github. [Ambiguous syntax with operator suffixes · Issue #28441 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/28441)

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [August 4, 2018, 8:49am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/43 "2018-08-04T08:49:03Z")

</div>

> [@Tamas\_Papp](#):
>
> I am not sure I understand why custom precendence is so important for you.

It’s important to me because I sometimes work with binary operations that use the same symbols that are already declared, but at a different precdence. Not being able to change the precedence makes the operator declaration practically useless in most cases. It isnt completely necessary, but it would be nice to actually be able to use infix operators proper, without worrying about wrong precedences.

Normally, I dont have many issues with Julia, but since this is one of my issues, it stands out, it feels like a language wart to me.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [August 4, 2018, 11:48am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/44 "2018-08-04T11:48:51Z")

</div>

> [@chakravala](#):
>
> It’s important to me because I sometimes work with binary operations that use the same symbols that are already declared, but at a different precdence.

Can you give an example?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 4, 2018, 12:22pm UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/45 "2018-08-04T12:22:29Z")

</div>

> [@chakravala](#):
>
> work with binary operations that use the same symbols that are already declared, but at a different precdence

I may misunderstand your intention, but if you want an operator to have different precedence based on its arguments, I don’t think you can do that; because that is already resolved in the AST, eg

```julia
julia> dump(Meta.parse("a+b*c"))
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol +
    2: Symbol a
    3: Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol *
        2: Symbol b
        3: Symbol c

```

---

<div class="post-metadata">

**Author:** ![Roger-luo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roger-luo/32/3399_2.png) [@Roger-luo](https://discourse.julialang.org/u/Roger-luo)\
**Post date:** [August 4, 2018, 12:38pm UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/46 "2018-08-04T12:38:04Z")

</div>

Just want to ask where can I find the definition of **precedence** of those UTF-8 operators? (except by reading the source code flisp) I think it might looks more explicit if this part can be define in Julia.

And maybe we will need a function for looking up the current **precedence** between two operators (or inside an expression). It will be more convenient when you are trying to use some unfamiliar operator.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 4, 2018, 12:41pm UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/47 "2018-08-04T12:41:17Z")

</div>

> [@Roger-luo](#):
>
> we will need a function for looking up the current **precedence** between two operators

You can use `Base.operator_precedence` for reflection.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [August 4, 2018, 2:12pm UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/48 "2018-08-04T14:12:56Z")

</div>

See [https://docs.julialang.org/en/latest/manual/mathematical-operations/#Operator-Precedence-and-Associativity-1](https://docs.julialang.org/en/latest/manual/mathematical-operations/#Operator-Precedence-and-Associativity-1)

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [August 4, 2018, 3:53pm UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/49 "2018-08-04T15:53:37Z")

</div>

> [@Tamas\_Papp](#):
>
> I don’t think you can do that; because that is already resolved in the AST

That is correct, this is what I specifically mentioned when I brought this problem up, and this is also why I characterize it as an issue.

However, it is not impossible to think of a solution. Here is an example of how this could work

```Julia
Base.unhinge_precedence(current_module())
Base.set_precedence(char, prec)

```

Perhaps, you could make it even simpler into a single function call

```Julia
Base.set_precedence(current_module(), char, prec)

```

Essentially, you want the precedence to be context specific for whatever module you are currently in, to contain the changes. Then the parser can keep its current default precedence list, and if a specific module needs a different precedence, then you can simply create an `Array` of precedence lists that maps to specific modules that had changes made. Then all you do is copy the default precedence list into the new one, except that the new one is mutable instead of immutable. Then you simply let the user change the precedence.

Thus, the parser then simply needs to have some basic logic to check if the precedence has been altered in a specific module, and if it has, branch off to select from the mutable `Array` instead of the immutable default.

```Julia
if module_precedence_modified
    # pick from mutable array
else
    # pick from immutable default
end

```

Fairly simple I think, and it doesn’t cause any breaking changes or compatibility issues.

If this is really so terrible for normal users and for the mainstream status of the language, please do elaborate and provide specific counter points, so that I can be convinced that this is a terrible idea. Right now, I am not convinced this is a bad idea, and I don’t think this would bother anyone, and if you don’t need it, then you would probably never notice that this features was added. If you need it, then win-win.

---

<div class="post-metadata">

**Author:** ![jandehaan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jandehaan/32/6805_2.png) [@jandehaan](https://discourse.julialang.org/u/jandehaan)\
**Post date:** [August 5, 2018, 2:18am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/50 "2018-08-05T02:18:55Z")

</div>

> [@chakravala](#):
>
> t would be nice to actually be able to use infix operators proper, without worrying about wrong precedences

This kind of syntax flexibility may seem useful in certain cases, but I would hate to be the person tasked with debugging code in which operator precedence is different from what everybody expects.  
Good luck finding the bug if for example `a+b*c^d` is being parsed as `((a+b)*c)^d` instead of  
the customary `a+(b*(c^d))`.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 5, 2018, 6:30am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/51 "2018-08-05T06:30:03Z")

</div>

> [@chakravala](#):
>
> Fairly simple I think

I don’t think so, I guess that allowing “local” parser states and designing a composable API would involve a fundamental redesign of the parser. And, as @jandehaan pointed out, it would be a code readability nightmare.

That said, I am sure it can be done (again, there are Lisps with very flexible parsers you can rewrite to parse anything), but I suspect there is a reason why this did not catch on.

Frankly, beyond “it would be nice”, I don’t understand the appeal. You can always use `()`s for grouping subexpressions — instead of a nuisance, think of them as a feature: they help the person who reads this code 3+ months later.

Precendence tables are a bit like national anthems: there is a part that more or less everyone knows, but there are obscure parts like the second verse which only the author and a few other people know about. Relying on these to save a few `()`s is usually not considered good practice.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [August 5, 2018, 7:03am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/52 "2018-08-05T07:03:30Z")

</div>

> [@Tamas\_Papp](#):
>
> Precendence tables are a bit like national anthems: there is a part that more or less everyone knows, but there are obscure parts like the second verse which only the author and a few other people know about.

Exactly! 🙂

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [August 5, 2018, 10:50am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/53 "2018-08-05T10:50:02Z")

</div>

> [@Tamas\_Papp](#):
>
> I guess that allowing “local” parser states and designing a composable API would involve a fundamental redesign of the parser.

This is a change that has to happen eventually regardless, in my opinion. There are other ways in which the Julia language is context-ambiguous, so moving in this direction is a good step towards resolving that.

> [@Tamas\_Papp](#):
>
> Precendence tables are a bit like national anthems: there is a part that more or less everyone knows, but there are obscure parts like the second verse which only the author and a few other people know about. Relying on these to save a few `()` s is usually not considered good practice.

Yet anyone writing a math paper seems to have no trouble parsing these precedences, mathematicians dont get confused because they studied all the definitions precisely. Unfortunately, the Julia language can’t make itself smarter because people reject this idea.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 5, 2018, 11:01am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/54 "2018-08-05T11:01:24Z")

</div>

> [@chakravala](#):
>
> anyone writing a math paper seems to have no trouble parsing these precedences

Certainly, as precedence (order of operations) in algebra is usually considerably simpler, because there are essentially 3 levels (`+-`, `*/`, `^`), with right-associativity for nested exponentiation. Julia as 13 precedence classes (if I am counting correctly), you are proposing to add to these and make them context-sensitive.

> [@chakravala](#):
>
> Unfortunately, the Julia language can’t make itself smarter

I don’t think this would make the language any “smarter”, just some syntax potentially more confusing.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 6, 2018, 7:21am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/55 "2018-08-06T07:21:26Z")

</div>

This is all very abstract to me (well, obviously). Can you give any concrete examples of what the code should look like, and what it does look like now? What does the math itself look like?

To me it seems reasonable that if, say, your multiplication operator doesn’t behave like an ordinary `*` and has different precedence, then it also should have a different spelling — not just in code, but even in writing. Given an example, it might be clearer why this is useful.

Are you even using `*` or are you talking about more exotic unicode symbols that happen to not have the right precedence for your use? In the latter case, would it make more sense to argue for changing the precedence of those specific operators?

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [August 6, 2018, 9:08am UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/56 "2018-08-06T09:08:21Z")

</div>

> [@chakravala](#):
>
> Yet anyone writing a math paper seems to have no trouble parsing these precedences, mathematicians dont get confused because they studied all the definitions precisely.

I’ve never encountered a math paper that violates the norm that `^` has higher precedence than `*` which has higher precedence than `+`. Moreover, if I did come across a paper that did this and missed the “notation” section where they explained their bizarre choice of precedence, I’d interpret everything in the paper incorrectly and be deeply confused when trying to follow it. It would never even occur to me that they might have changed this and my only reaction upon discovering their choice would be confusion and anger that the authors had wasted my time with such a ridiculous choice.

---

<div class="post-metadata">

**Author:** ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)\
**Post date:** [August 6, 2018, 1:59pm UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/57 "2018-08-06T13:59:22Z")

</div>

> [@Tamas\_Papp](#):
>
> Precendence tables are a bit like national anthems: there is a part that more or less everyone knows, but there are obscure parts like the second verse which only the author and a few other people know about.

This is just brilliant!

---

<div class="post-metadata">

**Author:** ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)\
**Post date:** [August 6, 2018, 2:06pm UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/58 "2018-08-06T14:06:06Z")

</div>

> [@chakravala](#):
>
> Base.set\_precedence(current\_module(), char, prec)

This would not be a good way to implement this feature. The problem is that it requires the ability to evaluate julia code in order to parse julia code.

> [@chakravala](#):
>
> There are other ways in which the Julia language is context-ambiguous, so moving in this direction is a good step towards resolving that.

Being able to change operator precedence seems like the opposite of reducing ambiguity and context-dependence.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [August 6, 2018, 2:25pm UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/59 "2018-08-06T14:25:09Z")

</div>

> [@DNF](#):
>
> Are you even using `*` or are you talking about more exotic unicode symbols that happen to not have the right precedence for your use?

Yes, this is my case. I am using atypical symbols, but their precedence is hard coded incorrectly. They are not your standard algebra symbols, so they certainly dont interfere. And my use case is very limited to research purposes, there are likely very few users who will ever look at it, let alone contribute. With the current way it works, I’m gonna have to give users a warning that they need to use parenthesis, because Julia will parse the syntax incorrectly without them. This is technically a bug, since I cant tell Julia which operations have precedence. None of these operations involve regular algebra symbols.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [August 6, 2018, 2:26pm UTC](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863/60 "2018-08-06T14:26:28Z")

</div>

> [@jeff.bezanson](#):
>
> This would not be a good way to implement this feature. The problem is that it requires the ability to evaluate julia code in order to parse julia code.

So scheme cant handle this? Also, isnt there a Julia parser written in Julia?

[Previous page](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863.md?page=2)

[Next page](https://discourse.julialang.org/t/on-adjoints-and-custom-postfix-and-infix-operators/12863.md?page=4)
