A macro for automatic output generation

Hi you all,
suppose I have a function my_func(args...; kwargs...). For example,

function my_func(a, b)
    a + b
end

I would like to manipulate the function with a macro to make a function whose output contains macroed(?) values. For example,

function my_func(a, b)
    @log a
    @log c = b^2
    a + b
end

with a function Generator makes a new function such that my_func2 = Generator(my_func) where

function my_func2(a, b)
    Dict(:a => a, :c => b^2)
end

Is it possible? If so, how can I achieve this?

Would something like this work

julia> using Logging

julia> function wrap(f)
          (a,b) -> begin
             @info a
             @info "c=$(b^2)"
             f(a,b)
          end
       end
wrap (generic function with 1 method)

julia> f(a,b) = a+b
f (generic function with 1 method)

julia> wf = wrap(f)
#1 (generic function with 1 method)

julia> wf(2,3)
[ Info: 2
[ Info: c=9
5

Sorry but it’s not what I wanted.
I would like “not to” rewrite some logging lines (e.g., a or c = b^2) for logging.
I hope that just putting a macro @log in front of a variable that I want to log in my_func.

I can’t see the logic behind the c=b^2 line.
Do you want to automatically log the input parameters?

Yes.

Only for the use of my_func, it’s enough. However, I’d like to add a macro @log such as

and passing a function or macro to make a new function

which is “annotated” variables in my_func.

So you want to add a @log macro to a function which should log its input parameters based on the output of my_func2?

Umm… My explanation was probably poor. Sorry.

What I want is,

  1. write a function (in the above example, my_func) which contains @log macro to indicate which variable will be saved.
  2. passing a function (namely, Generator) so that Generator(my_func) produces a function like
function my_func2(a, b)  # the same arguments with `my_func`
    """
    the below lines would be the same as `my_func`; not manually written, but probably written by `Generator` and assisted by `@log`.
    """
    a = a
    c = b^2
    # output is a dictionary containing variables annotated by `@log`
    Dict(:a => a, :c => c)
end

That is, @log indicates which variable will be saved, and Generator will automatically transform my_func to my_func2 (recognising @log).

Actually, I’m not sure the above idea works properly. It’s just an idea :slight_smile:

Ah okay :slight_smile:
So you probably need another macro in front of the function as you have to modify parts surrounding the marked lines.

1.) So you would need an object holding your return values(returndict = Dict())
2.) every log line then converts to something like

# @log c=b^2
c = b^2
returndict[Symbol("c")] = b^2

3.) at the end insert a return returndict

Sadly I don’t have experience with nested macros

1 Like

Exactly what I’m looking forward :slight_smile:

Do you have any idea to achieve this functionality without nested macros?

No, at the moment I think this is only possible by using macros, but I could be wrong.