【问题标题】:Mysterious Racket error: define: unbound identifier; also, no #%app syntax transformer is bound in: define神秘的球拍错误:定义:未绑定的标识符;此外,没有 #%app 语法转换器绑定在:define
【发布时间】:2014-01-13 18:15:30
【问题描述】:

此程序产生错误:

define: unbound identifier;
 also, no #%app syntax transformer is bound in: define

当粘贴到 REPL 中时(准确地说,最后一行:(displayln (eval-clause clause state))),它可以工作。在定义窗口中运行时,它会失败。我不知道为什么。

#lang racket
(define *state* '((a false) (b true) (c true) (d false)))
(define *clause* '(a (not b) c))

(define (eval-clause clause state)
  (for ([x state])
    (eval `(define ,(first x) ,(second x))))
  (eval (cons 'or (map eval clause))))

(displayln (eval-clause *clause* *state*))

这也是:

(define (eval-clause clause state)
  (eval `(let ,state ,(cons 'or clause))))

生产

let: unbound identifier;
 also, no #%app syntax transformer is bound in: let

这是我尝试翻译以下 Common Lisp 程序:Common Lisp 胜出?

; (C) 2013 KIM Taegyoon
; 3-SAT problem
; https://groups.google.com/forum/#!topic/lisp-korea/sVajS0LEfoA
(defvar *state* '((a nil) (b t) (c t) (d nil)))
(defvar *clause* '(a (not b) c))

(defun eval-clause (clause state)
  (dolist (x state)
    (set (car x) (nth 1 x)))
  (some #'identity (mapcar #'eval clause)))

(print (eval-clause *clause* *state*))

Paren:

(set *state* (quote ((a false) (b false) (c true) (d false))))
(set *clause* (quote (a (! b) c)))
(defn eval-clause (clause state)
  (for i 0 (dec (length state)) 1
    (set x (nth i state))
    (eval (list set (nth 0 x) (nth 1 x))))  
  (eval (cons || clause)))
(eval-clause *clause* *state*)

【问题讨论】:

    标签: lisp racket


    【解决方案1】:

    eval 在 Racket 中很棘手。根据 Racket Guide 15.1.2,您需要按如下方式挂钩到当前命名空间

    (define-namespace-anchor anc)
    (define ns (namespace-anchor->namespace anc))
    

    然后在每次调用eval时添加ns

    (define (eval-clause clause state)
      (for ([x state])
        (eval `(define ,(first x) ,(second x)) ns))
      (eval (cons 'or (map (curryr eval ns) clause)) ns))
    

    请注意,这在 REPL 中不是必需的,如上面引用的文档中所述。

    但是,为您的定义创建一个特定的命名空间可能是一个更好的主意,这样它们就不会与您自己的模块定义混淆:

    (define my-eval
      (let ((ns (make-base-namespace)))
        (lambda (expr) (eval expr ns))))
    
    (define *state* '((a #f) (b #t) (c #t) (d #f)))
    (define *clause* '(a (not b) c))
    
    (define (eval-clause clause state)
      (for ([x state])
        (my-eval `(define ,(first x) ,(second x))))
      (my-eval (cons 'or (map my-eval clause))))
    
    (displayln (eval-clause *clause* *state*))
    

    或者,如果您想继续使用racket/bool 中的truefalse,请按如下方式定义my-eval

    (define my-eval
      (let ((ns (make-base-namespace)))
        (parameterize ((current-namespace ns))
          (namespace-require 'racket/bool))
        (lambda (expr) (eval expr ns))))
    

    【讨论】:

    • 感谢您的友好解释!
    • 如果时间允许,还可以查看我的 Paren 编程语言(Lisp 方言):Paren
    • 因此浪费了至少一小时...谢谢!
    【解决方案2】:

    我会稍微简单地编写 Common Lisp 版本:

    (defun eval-clause (clause state)
      (loop for (var value) in state
            do (set var value))
      (some #'eval clause))
    

    LOOP形式更具描述性(因为我们可以去掉CARNTH)并且EVAL可以直接用在SOME函数中。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    • 2020-01-18
    • 2022-12-18
    • 1970-01-01
    相关资源
    最近更新 更多