【问题标题】:How to check if a symbol is a procedure or not如何检查符号是否是过程
【发布时间】:2012-03-24 17:58:23
【问题描述】:

我正在尝试编写一个宏来检查列表以查看是否有过程调用,但我不太确定如何去做。我首先想到的是使用程序?功能检查,但它不起作用。我试图做的一个例子如下:

(procedure? (car '(+ 1 2)))

现在,该列表中的汽车返回 +,但函数仍返回 false

有没有办法检查列表中的汽车是否是程序?

【问题讨论】:

    标签: scheme guile


    【解决方案1】:
    (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 是未绑定的符号,则会引发错误。 (但恐怕这实际上不是一个可移植的可解决问题......)
    • 我明白了,但是,考虑到这种情况:(application-form? '((lambda (x) x) 1)) ,肯定汽车部分(lambda (x) x)是一个程序,但它返回#f
    • 和所有类型谓词,包括“procedure?” “一对?” “列表?”在其参数未绑定的情况下引发错误。所以我认为我们的过程应该具有相同的行为。
    • 你说得对,我没有想到表单的car 本身就是一个复合表单的情况。嗯......我想哪种解决方案更可取取决于确切的问题陈述。事实上,有一些话要说支持只使用(define application-form? pair?)。 :)
    【解决方案2】:

    如果列表的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)))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-11
      • 1970-01-01
      相关资源
      最近更新 更多