# Convert String to function name

**URL:** https://discourse.julialang.org/t/convert-string-to-function-name/1547
**Category:** General Usage
**Created:** [January 17, 2017, 3:36pm UTC](https://discourse.julialang.org/t/convert-string-to-function-name/1547 "2017-01-17T15:36:20Z")
**Posts on this page:** 9
**Page:** 2

<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: [January 19, 2017, 5:27pm UTC](https://discourse.julialang.org/t/convert-string-to-function-name/1547/22 "2017-01-19T17:27:59Z")

</div>

> [@ScottPJones](#):
>
> Taking strings, and using @eval to turn those into function definitions in a loop, was something I learned early on from [DecFP]

Constructing a function name and _defining_ it is quite common (not just in my package). What confused me is the OP’s desire to construct a function name and _look up its binding_; where is that needed?

---

<div class="post-metadata">

### Author: ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)
#### Post date: [January 19, 2017, 8:45pm UTC](https://discourse.julialang.org/t/convert-string-to-function-name/1547/23 "2017-01-19T20:45:44Z")

</div>

Indeed, I have done quite a bit of metaprogramming in Julia, and can’t recall the last time I had to get a function from a symbol. Typically this might suggest that macros are doing work at macro expansion time that should really be done by generated code at runtime instead.

---

<div class="post-metadata">

### Author: ![chuljang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chuljang/32/6608_2.png) [@chuljang](https://discourse.julialang.org/u/chuljang)
#### Post date: [December 13, 2018, 5:04pm UTC](https://discourse.julialang.org/t/convert-string-to-function-name/1547/24 "2018-12-13T17:04:12Z")

</div>

Indeed, this was really useful discussion. Thank you.

---

<div class="post-metadata">

### Author: ![turquoise](https://avatars.discourse-cdn.com/v4/letter/t/71e660/32.png) [@turquoise](https://discourse.julialang.org/u/turquoise)
#### Post date: [July 29, 2019, 4:12pm UTC](https://discourse.julialang.org/t/convert-string-to-function-name/1547/25 "2019-07-29T16:12:59Z")

</div>

There is still a point I don’t understand.

Suppose I have a lists of symbols, `L1 = [:a,:b,:c]` and `L2 = [:d,:e,:f]`, and I want to combine them to obtain a series of functions, `ad()`, `ae()`, etc. The only way I can do this is the following

```julia
for i in L1 j in L2 
@eval $(Symbol(i,j))() = 0 
end 

```

And writing `@eval Symbol($i,$j)() = 0` also doesn’t work. If there is a way to do this without using `@eval` or in a better way please show 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: [July 29, 2019, 4:39pm UTC](https://discourse.julialang.org/t/convert-string-to-function-name/1547/26 "2019-07-29T16:39:29Z")

</div>

> [@turquoise](#):
>
> The only way I can do this is the following

Yes, that’s right. `$(Symbol(i,j))` constructs the combined symbol and then substitutes it into the code to evaluate, which is what you want.

In contrast, `@eval Symbol($i,$j)() = 0` is equivalent to writing `Symbol(a,d)() = 0`, which is not what you wanted.

Defining a bunch of functions from concatenated symbols in this way is actually pretty common in Julia, typically for writing wrapper code around external C and Fortran libraries that have lots of copy-and-paste permutations of a few symbols.

PS. Please read [PSA: how to quote code with backticks](https://discourse.julialang.org/t/psa-how-to-quote-code-with-backticks/7530)

---

<div class="post-metadata">

### Author: ![turquoise](https://avatars.discourse-cdn.com/v4/letter/t/71e660/32.png) [@turquoise](https://discourse.julialang.org/u/turquoise)
#### Post date: [July 29, 2019, 5:06pm UTC](https://discourse.julialang.org/t/convert-string-to-function-name/1547/27 "2019-07-29T17:06:15Z")

</div>

Thank you stevengj for your quick response. Can you explain why `Symbol(a,b)() = 0` doesn’t work ? It seems that I need to use @eval to define a function name from a symbol, I really don’t understand what is going on.

---

<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: [July 29, 2019, 5:32pm UTC](https://discourse.julialang.org/t/convert-string-to-function-name/1547/28 "2019-07-29T17:32:22Z")

</div>

> [@turquoise](#):
>
> Can you explain why `Symbol(a,b)() = 0` doesn’t work ?

The name of a function needs to be determined early on, even before it is compiled, and it would be too unpredictable to evaluate arbitrary code in order to do so (unless the user explicitly calls `@eval`). As far as the Julia parser is concerned, `Symbol(...)` is an arbitrary function call (since in the local namespace you could have defined `Symbol ` to be anything).

---

<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: [July 30, 2019, 2:27am UTC](https://discourse.julialang.org/t/convert-string-to-function-name/1547/29 "2019-07-30T02:27:24Z")

</div>

Also relevant to this discussion: [reflection - Julia: invoke a function by a given string - Stack Overflow](https://stackoverflow.com/a/34023458)

---

<div class="post-metadata">

### Author: ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)
#### Post date: [December 25, 2023, 3:41pm UTC](https://discourse.julialang.org/t/convert-string-to-function-name/1547/30 "2023-12-25T15:41:07Z")

</div>

Here I post a script that tries to interpret expressions provided in the form of strings and constructs the “corresponding” functions.  
The problem comes from [here](https://discourse.julialang.org/t/multi-threading-with-dataframes/101859/33).  
But this post seems more suitable to host the (possible) discussion.

At the moment only some functions are “read” correctly.  
The aim was however to build a small calculator for some predefined functions.  
And in any case there is a case that causes the function that does the “parsing” to fail.  
I have idea how to work around the problem, but I would like to ask for someone’s suggestion to have a “cleaner” solution.

> **la piccola calcolatatrice**
>
> ```julia
> julia> df=Dict("log"=>log, "sin"=>sin, "*"=>*,"+"=>+,"-"=>-,"^"=>^, "∘"=>∘)
> Dict{String, Function} with 7 entries:
> "∘" => ∘
> "-" => -
> "log" => log
> "^" => ^
> "*" => *
> "+" => +
> "sin" => sin
> 
> julia> function splitpar(str)
> splitpos=[]
> cp=0
> for (i,c) in enumerate(str)
> cp= cp+(c=='(')-(c==')')
> c==','&& cp==0 && push!(splitpos,i)
> end
> splitpos
> end
> splitpar (generic function with 1 method)
> 
> julia> function splitinpos(s2s,pos)
> ss=String[]
> pos=[0;pos;length(s2s)+1]
> for i in (2:length(pos))
> push!(ss,s2s[pos[i-1]+1:pos[i]-1])
> end
> ss
> end
> splitinpos (generic function with 1 method)
> 
> julia> function str2func(str)
>        
> lff=findfirst('(', str)
> op=df[str[1:lff-1]]
> if !occursin('(',str[lff+1:end])     
> par=split(str[lff+1:end-1],',')  
> tp=tryparse.(Int,par)
> n=only(filter(!isnothing,tp))    
> return ((a...)->op(n,a...))      
> else
> s2s=str[lff+1:end-1]
> par=splitinpos(s2s,splitpar(s2s))
> return (x...)->op(
> [str2func(p)(x[indexin(intersect(join(vars), p),vars)]
> ...) for p in par]...)       
> end
> end
> str2func (generic function with 1 method)       
> 
> julia> vars=['x','y','z']
> 3-element Vector{Char}:
> 'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)
> 'y': ASCII/Unicode U+0079 (category Ll: Letter, lowercase)
> 'z': ASCII/Unicode U+007A (category Ll: Letter, lowercase)
> 
> julia> str3= "+(*(+(3,x),*(-2,y)),*(2,x),+(*(3,x),*(4,y)))"
> "+(*(+(3,x),*(-2,y)),*(2,x),+(*(3,x),*(4,y)))"
> 
> julia> str2func(str3)(1,-1)
> 9
> 
> julia> str4= "*(+(3,x),*(-2,z),*(1,x,z))"       
> "*(+(3,x),*(-2,z),*(1,x,z))"
> 
> julia> str2func(str4)(1,-1,2) #-32
> -32
> 
> julia> str5= "+(*(+(3,x),*(-2,y),*(1,x,z)),*(+(3,y),*(-2,z),*(1,x,z)))"
> "+(*(+(3,x),*(-2,y),*(1,x,z)),*(+(3,y),*(-2,z),*(1,x,z)))"
> 
> julia> str2func(str5)(1,-1,2) # 0
> 0
> 
> julia> str6= "+(*(+(3,x),*(-2,z),*(1,x)),*(+(3,y),*(-2,x),*(1,x,z)))"
> "+(*(+(3,x),*(-2,z),*(1,x)),*(+(3,y),*(-2,x),*(1,x,z)))"
> 
> julia> str2func(str6)(1,-1,2)
> ERROR: BoundsError: attempt to access Tuple{Int64, Int64} at index [3]
> Stacktrace:
> ---
> 
> # the operation *(-2,z) indexes the 'z' which is in the third position, but the group *(+(3,x),*(-2,z),*(1,x)) it only has two distinct variables. The same expression with *(1,y) instead of *(1,x) does not in fact raise the same problem-
> julia> str7= "+(*(+(3,x),*(-2,z),*(1,y)),*(+(3,y),*(-2,x),*(1,x,z)))"
> "+(*(+(3,x),*(-2,z),*(1,y)),*(+(3,y),*(-2,x),*(1,x,z)))"      
> 
> julia> str2func(str7)(1,-1,2)# 8
> 8
> 
> julia> 
> 
> ```

[Previous page](https://discourse.julialang.org/t/convert-string-to-function-name/1547.md?page=1)
