to get suggestions for the current problem (about the use of an input string) it might be more useful to open a new topic with a more specific title
In principle a “simple calculator” seems feasible.
There’s a lot of work to do to make it truly functional, but just to start a seed
df=Dict("log"=>log, "sin"=>sin, "*"=>*,"+"=>+,"-"=>-,"^"=>^, "∘"=>∘)
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)
if all(isnothing,tp)
return ((x,y)->(a->(b->(c->op(a,c))(b)))(x)(y))
else
n=only(filter(!isnothing,tp))
return z->((x,y)->(a->(b->(c->op(a,c))(b)))(x)(y))(n,z)
end
else
return (x...)->"not yet"
end
end
julia> df_flows
6×5 DataFrame
Row │ from to rp tb index
│ String String Int64 Int64 Int64
─────┼─────────────────────────────────────
1 │ p1 d 1 3 1
2 │ p1 d 1 5 2
3 │ p2 d 1 7 3
4 │ p2 d 1 4 4
5 │ p1 d 2 6 5
6 │ p2 d 2 8 6
julia> transform(df_flows,[3,4]=>ByRow(str2func("*(x,y)")))
6×6 DataFrame
Row │ from to rp tb index rp_tb_function
│ String String Int64 Int64 Int64 Int64
─────┼─────────────────────────────────────────────────────
1 │ p1 d 1 3 1 3
2 │ p1 d 1 5 2 5
3 │ p2 d 1 7 3 7
4 │ p2 d 1 4 4 4
5 │ p1 d 2 6 5 12
6 │ p2 d 2 8 6 16
julia> transform(df_flows,[3,4]=>ByRow(str2func("+(x,y)")))
6×6 DataFrame
Row │ from to rp tb index rp_tb_function
│ String String Int64 Int64 Int64 Int64
─────┼─────────────────────────────────────────────────────
1 │ p1 d 1 3 1 4
2 │ p1 d 1 5 2 6
3 │ p2 d 1 7 3 8
4 │ p2 d 1 4 4 5
5 │ p1 d 2 6 5 8
6 │ p2 d 2 8 6 10
julia> transform(df_flows,[4,3]=>ByRow(str2func("^(x,y)")))
6×6 DataFrame
Row │ from to rp tb index tb_rp_function
│ String String Int64 Int64 Int64 Int64
─────┼─────────────────────────────────────────────────────
1 │ p1 d 1 3 1 3
2 │ p1 d 1 5 2 5
3 │ p2 d 1 7 3 7
4 │ p2 d 1 4 4 4
5 │ p1 d 2 6 5 36
6 │ p2 d 2 8 6 64
julia> transform(df_flows,[4,3]=>ByRow(str2func("-(x,y)")))
6×6 DataFrame
Row │ from to rp tb index tb_rp_function
│ String String Int64 Int64 Int64 Int64
─────┼─────────────────────────────────────────────────────
1 │ p1 d 1 3 1 2
2 │ p1 d 1 5 2 4
3 │ p2 d 1 7 3 6
4 │ p2 d 1 4 4 3
5 │ p1 d 2 6 5 4
6 │ p2 d 2 8 6 6
julia> transform(df_flows,[4]=>ByRow(str2func("*(3,y)")))
6×6 DataFrame
Row │ from to rp tb index tb_function
│ String String Int64 Int64 Int64 Int64
─────┼──────────────────────────────────────────────────
1 │ p1 d 1 3 1 9
2 │ p1 d 1 5 2 15
3 │ p2 d 1 7 3 21
4 │ p2 d 1 4 4 12
5 │ p1 d 2 6 5 18
6 │ p2 d 2 8 6 24
julia> transform(df_flows,[4,3]=>ByRow(str2func("+(log(x),∘(sin, *(10,y)))")))
6×6 DataFrame
Row │ from to rp tb index tb_rp_function
│ String String Int64 Int64 Int64 String
─────┼─────────────────────────────────────────────────────
1 │ p1 d 1 3 1 not yet
2 │ p1 d 1 5 2 not yet
3 │ p2 d 1 7 3 not yet
4 │ p2 d 1 4 4 not yet
5 │ p1 d 2 6 5 not yet
6 │ p2 d 2 8 6 not yet
the functions thus defined can be, in appropriate cases (associative operators), applied to more than 2 elements.
And in particular in the case of operators that have methods also defined on vectors, you can do without wrapping everything with ByRow
transform(df_flows,[3,4, 5]=>ByRow((x...)->reduce(str2func("+(x,y)"),x)))
transform(df_flows,[3,4, 5]=>(x...)->foldl(str2func("+(x,y)"),x))