尝试调用未绑定的fn,而我已定义它

Erw*_*ers 2 scheme clojure sicp evaluator metacircular

我正在尝试将SICP的元循环评估程序转换为Clojure.在setup-environment调用extend-environment不编译因为我收到错误"尝试调用未绑定的fn".这是代码的一部分:

(... loads of methods for creating and managing environment list)

(def primitive-procedures
  (list (list 'car first)
        (list 'cdr rest)
        (list 'cons conj) ;; TODO: reverse
        (list 'null? nil?)
        (list 'list list)
        (list '+ +)
        (list '- -)
        (list '* *)
        (list '/ /)
        ;;      more primitives
        ))

(def primitive-procedure-names 
  #(map [first
         primitive-procedures]))

(def primitive-procedure-objects 
  (fn [] (map (fn [p] (list 'primitive (second p)))
               primitive-procedures)))

(def the-empty-environment '())

(defn extend-environment [vars vals base-env]
  (if (= (count vars) (count vals))
    (conj base-env (make-frame vars vals))
    (if (< (count vars) (count vals))
      (throw (Throwable. "Too many arguments supplied") vars vals)
      (throw (Throwable. "Too few arguments supplied") vars vals))))

;; Added # in front here so it could be called (???)
(defn setup-environment []
  #(let [initial-env
         (extend-environment (primitive-procedure-names)
                             (primitive-procedure-objects)
                             the-empty-environment)] ;; <= that does not work
     (define-variable! 'true true initial-env)
     (define-variable! 'false false initial-env)
     initial-env)))

;; Method for interacting with the evaluator:

(defn driver-loop []
  (prompt-for-input input-prompt)
  (let [input (read)]
    (let [output (m-eval input the-global-environment)]
      (announce-output output-prompt)
      (user-print output)))
  (driver-loop))

(...)

(def the-global-environment (setup-environment))
(driver-loop)
Run Code Online (Sandbox Code Playgroud)

当我评估该extend-environment方法时,我收到以下错误:

  1. 由java.lang.IllegalStateException引起
    尝试调用未绑定的fn:
    #'scheme-evaluator/extend-environment
    Var.java:43 clojure.lang.Var $ Unbound/throwArity
    AFn.java:40 clojure.lang.AFn/invoke
    scheme- evaluator.clj:277 scheme-evaluator/eval7808

我想我没有提供正确类型的参数,或者我没有创建正确的函数类型.我尝试了各种各样的匿名方法,并在括号中传递或没有,但我没有得到它编译.

有谁知道这个错误的原因是什么,我该如何解决?

Art*_*ldt 5

的定义

(def primitive-procedure-names 
  #(map [first
        primitive-procedures]))
Run Code Online (Sandbox Code Playgroud)

可能不会做你想要的.由于写入此定义了一个函数,它没有参数并返回换能器(这是一个函数),将,如果施加到一个序列替代值0和1的功能firstprimitive-procedures分别.我将首先演示函数,然后使用数字值来演示更清晰的内容(希望如此):

user> (into [] (map [first 'example]) [0 1])
[#function[clojure.core/first--4339] example]
user> (into [] (map [1 2]) [0 1])
[1 2]
Run Code Online (Sandbox Code Playgroud)

也许你想要

(def primitive-procedure-names 
 (map first primitive-procedures))
Run Code Online (Sandbox Code Playgroud)

我可以建议使用defn表单定义函数和def形式来定义值,除非你有一个非常强烈的理由不这样做.

setup-environment是一个函数,它返回一个函数,如果你调用该函数,它将返回一个返回初始环境的函数,该函数不会被对define-variable的调用修改.在Clojure中,集合类型是不可变的,因此如果要对集合进行多处更改,则需要将添加第一个的结果链接到添加第二个的输入中,然后返回添加第二个的结果:

(add-second (add-first initial-value))
Run Code Online (Sandbox Code Playgroud)

也可以这样写:

(-> initial-value
    add-first
    add-second)
Run Code Online (Sandbox Code Playgroud)

这只是上面例子的简写.