【发布时间】:2012-03-24 17:58:23
【问题描述】:
我正在尝试编写一个宏来检查列表以查看是否有过程调用,但我不太确定如何去做。我首先想到的是使用程序?功能检查,但它不起作用。我试图做的一个例子如下:
(procedure? (car '(+ 1 2)))
现在,该列表中的汽车返回 +,但函数仍返回 false。
有没有办法检查列表中的汽车是否是程序?
【问题讨论】:
我正在尝试编写一个宏来检查列表以查看是否有过程调用,但我不太确定如何去做。我首先想到的是使用程序?功能检查,但它不起作用。我试图做的一个例子如下:
(procedure? (car '(+ 1 2)))
现在,该列表中的汽车返回 +,但函数仍返回 false。
有没有办法检查列表中的汽车是否是程序?
【问题讨论】:
(car '(+ 1 2)) => '+ not +
+是一个程序,而'+只是一个符号!
你应该检查一个未引用的变量:
(procedure? (car (list + 1 2))); => #t
;or
(procedure? (car `(,+ 1 2))); =>#t
如果列表是'(a b c d)的形式,你可以这样检查:
(procedure? (eval (car '(+ 1 2)) (interaction-environment)));=>#t
因为:
(eval (car '(+ 1 2)) (interaction-environment))
;=>(eval '+ (interaction-environment))
;=>+
我认为你在这里不需要宏,一个函数就足够了。 抽象该功能:
(define (application-form? lst)
(procedure? (eval (car lst) (interaction-environment))))
【讨论】:
car 是未绑定的符号,则会引发错误。 (但恐怕这实际上不是一个可移植的可解决问题......)
car 本身就是一个复合表单的情况。嗯......我想哪种解决方案更可取取决于确切的问题陈述。事实上,有一些话要说支持只使用(define application-form? pair?)。 :)
如果列表的car 被允许为未绑定符号,则此问题不可移植。但是,您可以在 Guile 中解决它:
(define (procedure-symbol? x)
(and (symbol? x)
(let ((var (module-variable (interaction-environment) x)))
(and var
(variable-bound? var)
(procedure? (variable-ref var))))))
(define (application-form? lst)
(procedure-symbol? (car lst)))
【讨论】: