【问题标题】:Avoid an extra begin block when quoting in a macro在宏中引用时避免额外的开始块
【发布时间】:2019-05-29 14:59:01
【问题描述】:

我正在编写这样的 Julia 宏:

macro cfunc(name, rettype)
  quotedname = Expr(:quote, name)
  return quote 
    (()->ccall(($quotedname, "libc.so.6"), $rettype, ()))
  end
end

我可以用它来创建一个函数:

@cfunc(time, Int32)()  # Returns current time

但是,如果我排除引用宏:

macro q(name)
  sym = Expr(:quote,name)
  return quote
    $(sym)
  end
end

macroexpand 产生一个额外的开始和结束:

:((begin
      #= REPL[142]:4 =#
      ()->begin
              #= REPL[142]:4 =#
              ccall((begin # <-- This is the extra begin
                          #= REPL[102]:4 =#
                          :clock
                      end, "libc.so.6"), Main.Int32, ())
          end       # ^^^ This is the extra end
  end)())

导致 ccall 失败的原因:

@cfunc(time, Int32)()
ERROR: error compiling #26: unsupported or misplaced expression "block" in function #26
Stacktrace:
 [1] top-level scope at REPL[151]:4

这样引用时如何避免开始/结束?

【问题讨论】:

    标签: julia metaprogramming ffi


    【解决方案1】:

    q 宏中的quote 块在完全扩展的版本中引入了额外的beginend。它通常不应该影响结果,但ccall is special

    这行得通:

    macro q(name)
      sym = Expr(:quote,name)
      return sym
    end
    

    就像这个不引入begin/end的报价表一样:

    macro q(name)
      sym = Expr(:quote,name)
      return :($sym)
    end
    

    【讨论】:

      猜你喜欢
      • 2012-12-18
      • 2020-02-10
      • 2020-02-16
      • 1970-01-01
      • 2020-09-09
      • 2016-12-24
      • 2013-07-09
      • 2011-11-28
      • 2012-01-26
      相关资源
      最近更新 更多