2017-05-15 20 views
5

Tôi đã có thể nghĩ điều này sẽ làm việc:Làm cách nào để xác định macro julia xác định macro?

macro meta_meta(x,y) 
    :(macro $x(arg) :($($y) + $arg) end) 
end 

Các hành vi mong đợi được mà gọi @meta_meta(f,2) nên tương đương với macro f(arg) :(2 + $arg) end

Nói cách khác:

julia> @meta_meta(f,2) 
julia> @f(3) 
5 

Thay vào đó tôi nhận được:

ERROR: syntax: invalid macro definition 

Tôi đang mất một chút tiền để tiến hành. Tôi thấy rằng cây biểu thức cho macro này khác với cái tôi nhận được nếu tôi tạo thủ công @f và kiểm tra cây biểu thức của nó và tôi đã thử một vài lần lặp của @meta_meta, nhưng tôi không thể tìm ra cách thay đổi định nghĩa của mình thành làm cho nó hoạt động.

+1

Sử dụng điều này như một ví dụ: https://discourse.julialang.org/t/def-macro-generator-broken-on-master/1096/3? U = chrisrackauckas. Bạn có thể cần phải thoát khỏi cái gì đó. –

+0

Cảm ơn con trỏ! Điều đó sẽ làm các trick. Tôi sẽ thử điều đó khi tôi có cơ hội để tìm ra. – HaberdashPI

Trả lời

6

Vệ sinh môi trường vĩ mô hơi khó xử khi xử lý báo giá bên trong báo giá. Thường thì tôi thấy cách duy nhất là từ chối hoàn toàn vệ sinh macro, và sử dụng gensym một cách tự do để mô phỏng nó.

Tuy nhiên trong ví dụ giảm của bạn, đó là đơn giản để chỉ cần bật các báo bên trong thành một Expr:

julia> macro meta_meta(x, y) 
      :(macro $(esc(x))(arg) Expr(:call, :+, $(esc(y)), esc(arg)) end) 
     end 
@meta_meta (macro with 1 method) 

julia> @meta_meta f 2 
@f (macro with 1 method) 

julia> @f 3 
5 

Nếu mọi thứ trở nên phức tạp hơn, cách tiếp cận tôi đã đề cập ở trên bao gồm việc tắt vệ sinh vĩ mô với esc. Điều này có nghĩa rằng chúng ta phải làm vệ sinh ourself, vì thế mà gensym:

julia> macro meta_meta(x, y) 
      arg = gensym() 
      esc(:(macro $x($arg) :($$y + $$arg) end)) 
     end 
@meta_meta (macro with 1 method) 

julia> @meta_meta f 2 
@f (macro with 1 method) 

julia> @f 3 
5 
+0

Cảm ơn! Lời nhận xét của Chris khiến tôi khá thân thiết, nhưng chưa đến đó. Tôi tiếp tục gặp phải [vấn đề này] (https://github.com/JuliaLang/julia/issues/16096). Nó làm tôi ngạc nhiên rằng giải pháp thứ hai của bạn không chạy vào vấn đề này. Tôi đoán nếu bạn thoát khỏi * toàn bộ * biểu hiện lỗi về đối số thoát không áp dụng. – HaberdashPI

+0

@HaberdashPI ah vâng, trong giải pháp đầu tiên của tôi, tôi đã quên mất trốn thoát khỏi arg. Tuy nhiên nó cũng không chạy vào vấn đề đó; chúng tôi không thực sự thoát khỏi bất kỳ tên đối số chức năng nào ở đây. Tôi đã cập nhật câu trả lời của mình. –

Các vấn đề liên quan