# Operations on expressions

**URL:** <https://discourse.julialang.org/t/operations-on-expressions/13666>\
**Category:** Internals & Design\
**Created:** [August 18, 2018, 3:24pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666 "2018-08-18T15:24:37Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![tim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim/32/6848_2.png) [@tim](https://discourse.julialang.org/u/tim)\
**Post date:** [August 18, 2018, 3:24pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/1 "2018-08-18T15:24:37Z")

</div>

HI,  
is there a reason why there are no operations such as addition or subtraction defined on symbols and expression. I mean something like `:(x*y) + :z = :(x*y + z)`. I just wrote down a few things like that (see [https://github.com/timkittel/SymbolicMath.jl](https://github.com/timkittel/SymbolicMath.jl) where I used a wrapper to avoid type piracy) because I need it to symbolically evaluate some functions without heavy dependency. Afterwards, I realized it might make sense to simply define that on the expression itself. Is there a reason why this is not a good idea? Or should I maybe simply open a PR?  
Cheers,  
Tim

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [August 18, 2018, 3:56pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/2 "2018-08-18T15:56:50Z")

</div>

> [@tim](#):
>
> Afterwards, I realized it might make sense to simply define that on the expression itself.

No. Having a meaning in a specific context/application never means that it is a good idea in general even though most people tend to think this way.

For this case in particular, operation on expressions simply doesn’t make sense for what symbols and expressions are designed for, which is an accurate representation of a julia expression. The transformation you are suggesting misses a lot of information (e.g. about scope).  
Doing this on symbols will also be really confusing since they are very similar to strings but the operation you suggest will be very different from string ones.  
Finally, doing this only on operators is really arbitrary and doing this for all functions will make it impossible to define any functions that operate on expressions/symbols.

---

<div class="post-metadata">

**Author:** ![tim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim/32/6848_2.png) [@tim](https://discourse.julialang.org/u/tim)\
**Post date:** [August 18, 2018, 4:53pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/3 "2018-08-18T16:53:57Z")

</div>

okai, that makes sense. So it actually makes sense to put in a wrapper and then operate on the level of that wrapper as it was designed for that?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [August 18, 2018, 5:20pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/4 "2018-08-18T17:20:42Z")

</div>

Yes.

---

<div class="post-metadata">

**Author:** ![tim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim/32/6848_2.png) [@tim](https://discourse.julialang.org/u/tim)\
**Post date:** [August 19, 2018, 12:01pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/5 "2018-08-19T12:01:48Z")

</div>

Thank you!

---

<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 19, 2018, 7:15pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/6 "2018-08-19T19:15:40Z")

</div>

You can do operations on expressions using my package

> **[GitHub - chakravala/Reduce.jl: Symbolic parser for Julia language term...](https://github.com/chakravala/Reduce.jl)**
>
> Symbolic parser for Julia language term rewriting using REDUCE algebra - GitHub - chakravala/Reduce.jl: Symbolic parser for Julia language term rewriting using REDUCE algebra

For example

```plaintext
julia> using Reduce
Reduce (Free CSL version, revision 4590), 11-May-18 ...

julia> @force using Reduce.Algebra

julia> :(x*y) + :z
:(x * y + z)

julia> int(ans,:y)
:(((x * y + 2z) * y) / 2)

```

With the `ForceImport` package the overloaded operations are defined separately from the `Base` methods, so that they can remain local in a module scope without changing the behavior of global methods.

> **[GitHub - chakravala/ForceImport.jl: Macro that force imports conflicting...](https://github.com/chakravala/ForceImport.jl)**
>
> Macro that force imports conflicting methods in modules - GitHub - chakravala/ForceImport.jl: Macro that force imports conflicting methods in modules

---

<div class="post-metadata">

**Author:** ![tim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim/32/6848_2.png) [@tim](https://discourse.julialang.org/u/tim)\
**Post date:** [August 19, 2018, 7:44pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/7 "2018-08-19T19:44:05Z")

</div>

Oh interesting, I will check it out. But What was your reason for using plain expressions instead of a wrapper? It kinda goes against the logic explained by @yuyichao (which makes a lot of sense to me).

---

<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 19, 2018, 7:51pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/8 "2018-08-19T19:51:39Z")

</div>

> [@tim](#):
>
> It kinda goes against the logic explained by @yuyichao (which makes a lot of sense to me).

That’s right, we have somewhat of a disagreement about this, but for my purposes it achieves what I wanted and my solution does not interfere or cause any issues.

> [@tim](#):
>
> What was your reason for using plain expressions instead of a wrapper?

My goal is to manipulate the Julia AST, I didn’t want to add extra translation layers for a wrapper. I figured the AST itself provides plenty of information, although with a special wrapper type you could encode extra data. Mainly, I just wanted to take this idea of having operations on `Symbol` to see how far it can be taken while maintaining compatbility and flexibility. However, that’s not the main purpose, I only did it because it is possible, but if you don’t want this feature, then don’t use the command `@force using Reduce.Algebra` and then you don’t have to use those operations.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [August 19, 2018, 7:52pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/9 "2018-08-19T19:52:07Z")

</div>

It limits the scope so it won’t cause much trouble. I wouldn’t recommand import that in a package that does anything else though since it could be hard to understand.

---

<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 19, 2018, 7:54pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/10 "2018-08-19T19:54:14Z")

</div>

> [@yuyichao](#):
>
> I wouldn’t recommand import that in a package that does anything else though since it could be hard to understand.

I also don’t necessarily recommend it since it might be confusing to apply this technique of managing the scope in other packages, although I will gladly explain how to correctly use it if requested.

---

<div class="post-metadata">

**Author:** ![tim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim/32/6848_2.png) [@tim](https://discourse.julialang.org/u/tim)\
**Post date:** [August 26, 2018, 6:12pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/11 "2018-08-26T18:12:18Z")

</div>

With a bit of delay, @chakravala, I would be happy if you could demonstraite the correct use (:

---

<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 26, 2018, 9:59pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/12 "2018-08-26T21:59:45Z")

</div>

The principle which all `@force` users must keep in mind is this: the goal is to extend `Base` methods locally without affecting the global method table by type piracy, and to be able to import them into another package to have the same local effect. In order to avoid the type piracy, one must define a new local complementary n-ary method that will fall back on the base method with `Any` arguments. Then there will be a tiered alternative dispatch layer within the local package scope that redirects to the default `Base` dispatch generically. This has many advantages, including a 2x-improvement in precompile time (since the precompilation is now tiered), which actually makes a big difference if this technique is applied to a large number of operations (on the order of 50-100 in `Reduce`).

```nohighlight
module ExtendedPackage
+(x...) = Base.:+(x...)
+(x::Symbol,y::Number...) = Expr(:call,:+,x,y...)
end

```

Then you can use it locally with the `@force` macro, which automatically forces imports of all exported methods one by one;

```nohighlight
module NewScope
using ForceImport
@force using ExtendedPackage
end

```

You will now have the property

```nohighlight
julia> Base.:+ == NewScope.:+
false

```

where the `+` in the `NewScope` is now the extended plus that falls back on `Base`, which is also different from the `+` in `Main`. All it takes is the application of this principle, which has been pioneered with the development of the `Reduce.Algebra` module (defined in [src/args.jl](https://github.com/chakravala/Reduce.jl/blob/master/src/args.jl) and [src/unary.jl](https://github.com/chakravala/Reduce.jl/blob/master/src/unary.jl)).

> <https://github.com/chakravala/Reduce.jl/blob/382b5ff84bb66067f2f087156c6bd930c297318a/src/Reduce.jl#L105-L123>

The main difficulty lies in properly designing the redirection from the tiered method dispatch so that the infix operations work naturally with a variety of syntax.

---

<div class="post-metadata">

**Author:** ![tim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim/32/6848_2.png) [@tim](https://discourse.julialang.org/u/tim)\
**Post date:** [September 11, 2018, 3:15pm UTC](https://discourse.julialang.org/t/operations-on-expressions/13666/13 "2018-09-11T15:15:37Z")

</div>

First of all, thanks a lot for the extensive explanation. Following your example, I am trying to implement a similar idea for `getindex` but it’s somehow not working (which is why I am responding so lat). I will will try to work up an minimal (not) working example and maybe you could help me a bit with the force import.

Again, thanks for the explanations!
