【问题标题】:Scheme: + is not a procedure?方案:+是不是程序?
【发布时间】:2018-03-07 13:00:44
【问题描述】:

我正在尝试学习方案(更具体地说是 R5RS),并且我想定义一个过程,该过程将具有 3 个元素的列表作为输入,例如:'(5 + 2), 其中中间参数始终是运算符,第一个和第三个始终是操作数。

例子:

(proc-mid '(1 + 2))
--> 3
(proc-mid '(1 list 2))
--> (1 2)
(proc-mid '(20 * 5))
--> 100

到目前为止我的代码是这样的:

(define (proc-mid exp)
    (define proc (cadr exp))
    (proc (car exp) cddr exp))

但是,我收到一条错误消息:

    application: not a procedure;
     expected a procedure that can be applied to arguments
      given: +
      arguments...:

那么我的问题是,为什么 + 不被评估为一个过程?

【问题讨论】:

    标签: scheme r5rs


    【解决方案1】:

    当 Scheme 计算 (+ a b) 时,它会计算操作数 + 并希望有一个过程值,然后是 ab,它们可能都应该计算为数值。然后apply 会将+ 的结果与操作数的结果相结合。

    引用的表达式'(+ a b) 不计算它的参数。因此+ 不会被评估为过程,ab 不会被评估为数字。该值只是列表(+ a b)。如果你用list 来做这个,你会做(list '+ 'a 'b)。如果您执行(list + a b),您将评估3 个变量并得到类似(#<system-procedure:+> 2 3) 的返回值。

    引用的表达式'(+ 2 3) 是特殊的,因为您有数字文字并且它们是自评估的,但+ 仍然是一个符号,而不是看起来相同的评估变量,因为引用不评估它的参数。

    (apply '+ '(2 3)) 将无法工作,因为+ 不是一个过程。

    您或许应该将您的原语映射到实际过程?

    ;; assoc between symbols and their corresponding procedure value
    (define PROCS `((+ . ,+) (* . ,*)))
    
    (define (get-proc symbol)
      (let ((match (assq symbol PROCS)))
        (if match
            (cdr match)
            symbol)))
    

    【讨论】:

      【解决方案2】:

      在您的情况下,+symbol,因为

      '(element1 element2 ... elementn)
      

      将文本(非数字/布尔值等)转换为符号。

      (define l1 '(1 a #f +))
      
      (symbol? (car l1))
      (symbol? (cadr l1))
      (symbol? (caddr l1))
      (symbol? (cadddr l1))
      

      #f

      #t

      #f

      #t

      您可以仔细使用eval 来评估文本,如answer

      (eval '(+ 1 2))
       3  
      

      文档:racket quote

      【讨论】:

        【解决方案3】:

        + 在大多数范围内都绑定到一个过程,但它本身就是一个符号。它几乎总是绑定到的过程是一个过程。 例如,在 (let ((+ "+")) +)+ 是一个字符串。在任何合理的状态下,你都会有类似的东西

        (procedure? '+) => #f (procedure? +) => #t, 这就是说,在大多数编程语言中,您可以将可用变量/函数/等的环境想象为符号到值的字典,只是在方案中,指向值的符号可以作为值访问。因此,在引用列表(+ 1 2) 时,您指的是符号列表,即环境/字典中的键,而不是值。 (symbol? (cadr '(1 + 2)))(procedure? (cadr (list 1 + 2)))

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-28
          • 1970-01-01
          相关资源
          最近更新 更多