Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
737 views
in Technique[技术] by (71.8m points)

lisp - Mysterious Racket error: define: unbound identifier; also, no #%app syntax transformer is bound in: define

This program produces an error:

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

When pasted into the REPL (to be exact, the last line: (displayln (eval-clause clause state))), it works. When run in definition window, it fails. I don't know why.

#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*))

This too:

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

produces

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

This was my attempt to translate the following Common Lisp program: Common Lisp wins here?

; (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*))

And in 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*)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

eval is tricky in Racket. As per Racket Guide, 15.1.2, you need to hook into the current namespace as follows

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

and then add ns to every call to eval:

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

Note that this is not necessary in the REPL, as explained in the document referenced above.

However, it's probably a better idea to create a specific namespace for your definitions so that they don't get mixed up with your own module's definitions:

(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*))

or, if you want to continue using true and false from racket/bool, define my-eval as follows;

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...