Macros 如何调用宏并向其传递参数

Macros 如何调用宏并向其传递参数,macros,clojure,lisp,Macros,Clojure,Lisp,看来我对宏的理解还不完整。 如何将参数传递给宏,并从函数调用它们。 代码下面看似简单的代码不起作用 (defmacro bar [arg] (println (symbol? arg))) (defn foo [arg] (bar arg)) (foo 'baz) => nil 宏应该生成代码。它将源表达式作为参数并创建新的源 你的宏采用什么源 宏生成的源是什么 让我们看看: user=> (defmacro bar [arg] (println (s

看来我对宏的理解还不完整。 如何将参数传递给宏,并从函数调用它们。 代码下面看似简单的代码不起作用

(defmacro bar [arg]
  (println (symbol? arg)))

(defn foo [arg]
  (bar arg))

(foo 'baz) => nil

宏应该生成代码。它将源表达式作为参数并创建新的源

  • 你的宏采用什么源
  • 宏生成的源是什么
  • 让我们看看:

    user=> (defmacro bar [arg]
             (println (symbol? arg)))   
    #'user/bar
    user=> (bar 1)
    false
    nil
    user=> (bar 'a)
    false
    nil
    user=> (bar a)
    true
    nil
    
    这是扩展:

    user=> (macroexpand-1 '(bar a))
    true
    

    它不会生成任何有用的代码。

    定义foo时,将对宏进行求值。如果在repl中定义foo函数,您会注意到Clojure打印true

    user=> (defmacro bar [arg]
             (println (symbol? arg)))
    #'user/bar
    user=> (defn foo [arg]
             (bar arg))
    true ;  <= This is the print from your macro 
         ;     (it prints true, because arg is a symbol)
    #'user/foo
    

    要使宏“工作”,它需要返回代码,通常作为列表表达式。因此,对于您的意图,您需要提供:

    (defmacro bar (arg)
      `(println (symbol? ,arg)))
    
    (这将使用Quasikote作为构建列表的方便符号。)在使用
    bar
    时,通过运行defmacro代码来扩展该用法,以生成该列表。然后对清单进行汇编。例如:

    (progn (bar 10))
    
    扩展为

    (progn (println (symbol? 10))
    
    编译后,运行代码并打印“nil”。您将注意到,
    (a条)
    将产生一个错误“
    a未绑定”
    ”,因为扩展是
    (println(符号a))
    ,其中计算
    a
    ,可能没有值<代码>(条形图'a)返回
    T

    使用此正确的
    bar
    宏,您的函数
    foo
    在编译时将扩展为:

    (defun foo (x)
      (println (symbol? x))
    

    正确计算
    (foo'a)
    (foo'10)

    如果我理解正确,那么foo的定义将扩展为(println(symbol?arg))将为(foo'baz)打印true。我这里缺少什么?@navgeet,不,您编写的宏不会扩展到
    (println(symbol?arg))
    。宏只是一个函数,它必须返回展开形式。如果要获得所描述的内容,应该将宏的主体更改为类似于`(println(symbol?~arg))的内容。
    (defun foo (x)
      (println (symbol? x))