I want to define functions f1 and f2 (to be inputted inside a struct S) from another function f, defined at global scope, using another auxiliary function fun:
mutable struct S
f1::Function
f2::Function
end
function fun(f)
f1 = f
f2 = x -> 2 * f1(x)
# or function f2(x); 2 * f1(x); end
S(f1, f2)
end
f(x) = x
s = fun(f)
Now, this works:
typeof(s.f1)
> typeof(f)
However,
typeof(s.f2)
> var"#f2#1"{typeof(f)}
which I guess will lead to performance and time losses along the line. Is there a better way to do it?
Yes, of course, I always forget to mention that I already do that when I write MWEs. A better representation of my problem would then be:
mutable struct S{f1_T, f2_T}
f1::f1_T
f2::f2_T
end
function fun(f)
f1 = f
f2 = x -> 2 * f1(x)
# or function f2(x); 2 * f1(x); end
S(f1, f2)
end
f(x) = x
s = fun(f)
typeof(s.f1)
> typeof(f)
typeof(s.f2)
> var"#f2#1"{typeof(f)}
Maybe there is a misconception here. var"#f2#1"{typeof(f)} isn’t any worse than typeof(f), it’s just that’s an anonymous function so there are no better ways of representing it in the REPL.
Also, did you know you can define one-line functions like
Actually, yes, but I had an issue (on julia v1.0) that prevented me to use that form, hence my example. However, I’m not able to reproduce that issue now (neither in v1.6 nor in v1.0) so I guess that’s sorted.
A follow-up question is: is this a good design pattern (in terms of performances) to do this kind of things? To be absolutely clear, this is the test case I have in mind:
module M
mutable struct S{f1_T, f2_T}
f1::f1_T
f2::f2_T
end
function fun(f)
f1 = f
f2(x) = 2 * f1(x)
S(f1, f2)
end
export S, fun
end
using .M
f(x) = x
s = fun(f)
typeof(s.f1)
typeof(s.f2)
I tried instead to define f1 and f2 as stubs outside fun and then overload them with new methods using fun, but that’s of course just worse.
I think that making the struct mutable does not make sense, because each function has its own type. You won’t be able to replace the function by another one (I think, can’t check now).
Concerning the performance, it is hard to tell, it depends on what you will be doing with such structure.
The idea is to take a function f and use fun to compute its derivatives (say, first and second ones, with ForwardDiff and/or FiniteDifferences), saving the results into f1 and f2.
For that the data structure is not important. The point is if you are planing to have functions that have this structure as a parameter, and if the structure changes frequently (thus begin type unstable) in your code.
If you using the structure just to store two functions (coming from wherever they come from) and then the expensive computation is done inside these functions (f1 and f2), how you stored them will not affect performance.