# Understanding display of equations and computation with Symbolics.jl

**URL:** <https://discourse.julialang.org/t/understanding-display-of-equations-and-computation-with-symbolics-jl/114558>\
**Category:** General Usage\
**Created:** [May 22, 2024, 11:49am UTC](https://discourse.julialang.org/t/understanding-display-of-equations-and-computation-with-symbolics-jl/114558 "2024-05-22T11:49:04Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)\
**Post date:** [May 22, 2024, 11:49am UTC](https://discourse.julialang.org/t/understanding-display-of-equations-and-computation-with-symbolics-jl/114558/1 "2024-05-22T11:49:04Z")

</div>

I got from the [documentation](https://docs.sciml.ai/Symbolics/stable/getting_started/) that you can use Symbolics.jl and Latexify.jl together to display your equations.

However, what can be evaluated gets evaluated right away so in that sense not the same as sympy or Sympy.jl [[1](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547)][[2](https://discourse.julialang.org/t/symbolic-sqrt-2-and-sin-pi/58633)].

For instance,

```julia
using Symbolics
using Latexify

@variables r
v = 4 / 3 * π * r ^ 3
D = Differential(r)
a = expand_derivatives(D(v))
latexify(a)

```

returns

```julia
L"\begin{equation}
12.566 r^{2}
\end{equation}
"

```

A workaround (launching a new instance of Julia):

```julia
using Symbolics
using Latexify

@variables r, π
v = 4 // 3 * π * r ^ 3
D = Differential(r)
a = expand_derivatives(D(v))
latexify(a)

```

assuming that `π` has not already been associated with `Base.pi` through a prior calculation (hence requiring the launch of a new Julia instance; otherwise maybe enclose in a `let...end` block).

This returns

```julia
L"\begin{equation}
4 r^{2} \pi
\end{equation}
"

```

To use this for computation,

```julia
a_expr = (x) -> substitute(a, Dict(π => Symbolics.pi, r => x))
a_expr(2)

```

returns `50.26548245743669`. In this case, care must be taken that the argument to the anonymous function cannot be `r` as it is now considered a symbol in this namespace (which I found out by accident - that `r` would remain a symbol within the scope of the anonymous function was expected behavior).

Alternatively, I can also convert this to a function. If I understand correctly, π will evaluate to `Symbolics.pi` (which is the same as `Base.pi`) even without my substitution.

```julia
a_fn = build_function(a, r, expression=Val{false})
a_fn(2)

```

returns the same value as above.

Am I understanding the use cases correctly - or is there a more direct way to use the same notation for defining symbolic expressions for displaying and calculations?

Is there a better way to contain the scope of symbolic variables? Should they always be used within a `let...end` block?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [June 15, 2024, 11:06am UTC](https://discourse.julialang.org/t/understanding-display-of-equations-and-computation-with-symbolics-jl/114558/2 "2024-06-15T11:06:06Z")

</div>

I am not entirely sure what the questions are here? I haven’t answered because I’m trying to parse what you’re saying and a lot of it doesn’t make sense, so I’m just going to post what I can answer and see if that helps.

> [@hatmatrix](#):
>
> Is there a better way to contain the scope of symbolic variables? Should they always be used within a `let...end` block?

If you need them to stay scoped, then yes do that.

> [@hatmatrix](#):
>
> In this case, care must be taken that the argument to the anonymous function cannot be `r` as it is now considered a symbol in this namespace (which I found out by accident - that `r` would remain a symbol within the scope of the anonymous function was expected behavior).

`@variables x, y` creates lines of code like `x = Symbolics.variable(...)`. I’m not sure how else it could work. It has to create a Julia variable. There’s nothing different about them from a normal Julia variable. It just has dispatches for mathematical operations and display overrides for Latex.

> [@hatmatrix](#):
>
> assuming that `π` has not already been associated with `Base.pi` through a prior calculation (hence requiring the launch of a new Julia instance; otherwise maybe enclose in a `let...end` block)

That’s just Julia’s standard behavior with shadowing base variables. I just wouldn’t shadow variables exported from Base.

---

<div class="post-metadata">

**Author:** ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)\
**Post date:** [June 16, 2024, 9:47pm UTC](https://discourse.julialang.org/t/understanding-display-of-equations-and-computation-with-symbolics-jl/114558/3 "2024-06-16T21:47:35Z")

</div>

Thanks @ChrisRackauckas,

I just wanted to check if my understanding was correct so thanks for confirming - that’s exactly what I was looking for.

I guess the one surprising behavior that remains is that the behavior of the function differs whether `r` or something else (like `x`) is used as the name of the argument of the anonymous function.

```julia
a_expr = let 
    @variables r, π
    v = 4 // 3 * π * r ^ 3
    D = Differential(r)
    a = expand_derivatives(D(v))
    r -> substitute(a, Dict(π => Symbolics.pi, r => r))
end

```

The type for `r` as a symbolic variable appears to carry into the argument of the anonymous function. I thought when the function creates its own scope, that `r` would be allowed to take on any type within that scope but it’s not the case.
