defmodule M1 do
def func1 do
__ENV__.function
end
end
If I call it from some other function, it’ll be called in the context of “func1”, that is, it’ll return “:func1” as the name of a function. But I want it to have a context of a function it’s called from and return its name, that is, function “func1” should be kind of a macros or inline function, it should unwrap its body when it’s being called. How can I implement this?
[…] “func1” should be kind of a macros or inline function
If you want the __ENV__ of the caller, you need to stick to the context of the caller. The version I have shown here, simply injects the code __ENV__.function back to the callsite. There is also the __CALLER__-macro available, which is also an Macro.Env-struct. Using that, the macro could look like this:
defmodule M1 do
defmacro func1 do
funname = __CALLER__.function
quote do: unquote(funname)
end
end
This will not inject the __ENV__.function into the caller code but the function name itself.
The most easiest way to do guaranteed inlining is via macros. Inlining itself is not controllable and will never happen across module-boundaries since it would hurt hot swapping of modules.
Technically things are expanded before inlining could ever take place, so __ENV__.function would never ever work for a calling function from within a function, always need a macro.