Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Julia codegeneration with global function

Tags:

julia

julia 0.5.1

I want to create a function inside a quote that can be used after the specified macro has been used. Here is an example of what I mean

macro wat()
  quote
    type Foo end
    global bar() = begin end
    global function bar2()
    end
    type Baaz end
  end
end

@wat
Foo()
Baaz()
bar()
bar2()

Now when I run this the last line crashes, because bar2 is undefined. I do not understand why because in my understanding bar() and bar2() should be equal and bar is just syntactic sugar for bar2. But they are apparently not equal and I do not understand why the one works and other does not.

Secondly is there a way to define bar and bar2 inside that quote without the global-keyword and still being available after the macro has been executed?

My motivation for wanting the bar2 notation is that I can specify a return-type with this syntax.

global bar3()::Void = begin end

Is not allowed syntax.


1 Answers

In the returned expressions of Julia macros, names of local variables are replaced with unique symbols:

julia> macro foo()
        quote
            x = 1
            global y = 2
        end
    end
@foo (macro with 1 method)

julia> macroexpand(:(@foo))
quote  # REPL[1], line 4:
    #1#x = 1
    global y = 2
end

This feature is called macro hygiene and avoids accidental clashes with variables at the call site.

To escape from this behavior, one has to use esc:

julia> macro bar()
                quote
                    x = 1
                end |> esc
            end
@bar (macro with 1 method)

julia> macroexpand(:(@bar))
quote  # REPL[1], line 3:
    x = 1
end

Often, one doesn't want to escape the whole returned expression but only specific parts of it:

julia> macro myshow(expr)
        quote
            x = $(esc(expr))
            println($(string(expr)), " = ", x)
            x
        end
    end
@myshow (macro with 1 method)

julia> x = pi/2
1.5707963267948966

julia> macroexpand(:(@myshow sin(x)))
quote  # REPL[1], line 3:
    #1#x = sin(x) # REPL[1], line 4:
    (Main.println)("sin(x)", " = ", #1#x) # REPL[1], line 5:
    #1#x
end

julia> @myshow sin(x)
sin(x) = 1.0
1.0

julia> x
1.5707963267948966

For details, I recommend to read the corresponding section in the manual.

like image 93
tim Avatar answered Nov 28 '25 02:11

tim



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!