【问题标题】:LISP: Illegal argument in functor positionLISP:函子位置的非法参数
【发布时间】:2016-03-02 23:31:28
【问题描述】:

我的代码如下所示:

(defmacro createList (a b c)
  (let ((lst (list a b c)))
    (write lst)))

(createList 1 2 3 )

我明白了:

Illegal argument in functor position: 1 in (1 2 3).

我知道这里有一个类似的问题: Lisp Illegal argument in functor position

但我无法调整我的问题的答案。括号问题出在哪里?我做错了什么?

【问题讨论】:

    标签: list macros lisp common-lisp


    【解决方案1】:

    write 函数的结果是它的参数。所以,(write "Tom") 的结果是"Tom"(它写入输出流的事实是函数的副作用)。

    宏返回要评估的表单,通常表示一个列表。

    您的宏创建列表(1 2 3),然后将其写出。 write 在宏扩展时评估,而不是“运行时”。由于write 将其参数作为返回值返回,而write 是最后一个调用的函数,因此宏函数的结果是write 函数的结果,或者在本例中为(1 2 3)

    (1 2 3) 然后被评估,但如果你尝试在顶层输入(1 2 3),它将看到1 作为表单的第一个参数,并尝试将其作为一个函数来评估——不是,只是数字 1。

    如果你想看看你的宏会扩展什么,你可以试试:(macroexpand '(createlist 1 2 3))

    你可以看到下面的结果:

    [2]> (macroexpand '(createlist 1 2 3))
    (1 2 3)
    (1 2 3) ;
    T
    

    您会看到第一个(1 2 3),这是您的write 的结果。然后您会看到第二个(1 2 3),它是宏扩展的结果(如上所述),然后是T,它是macroexpand 函数的结果。

    所以这就是正在发生的事情。不清楚如何解决它,因为不清楚你想做什么。

    也许这是你想要做的更多:

    (defmacro createlist (a b c)
      `(list ,a ,b ,c))
    
    [5]> (macroexpand `(createlist 1 2 3))
    (LIST 1 2 3) ;
    T
    

    【讨论】:

    • 哇!这很快!它帮助了很多!因为我开始学习 LISP,所以我不知道 write 函数。你最后提供的解决方案正是我需要的。
    【解决方案2】:

    write 返回您传递给它的对象作为它的第一个参数。因此,您将从宏中返回 lst。从宏返回的任何内容都被视为 lisp 代码。

    运行代码时,您应该会看到

    (1 2 3)
    

    在错误之前的标准输出上。这就是你给write 的结果:(list a b c)a 绑定到1 等的结果。

    lisp 代码中列表的第一个元素是被调用的函数。显然,1 是这个列表的第一个元素,它不是一个函数。

    为了调试此类错误,使用macroexpand 通常很有帮助:

    (defmacro createList (a b c)
      (let ((lst (list a b c)))
         (write lst)))
    
    (format t "~%Expanded ~a~%" (macroexpand-1 '(createList 1 2 3)))
    

    (Live)

    【讨论】:

      猜你喜欢
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多