Closed-over variables get wrong values

Willem Broekema metawilm at gmail.com
Fri Sep 24 23:10:25 CEST 2010


In the code below a closure is created, then later called. At call
time, the closed-over variables point to the wrong values.

- - -
(in-package :cl-user)

(defclass lexer (standard-generic-function)
  ()
  (:metaclass pcl:funcallable-standard-class))

(defun make-lexer (closed-over-var)
  (let ((lexer (make-instance 'lexer)))
    (format t "outside 1:~%   closed-over-var = ~S~%   lexer = ~S~%"
closed-over-var lexer)
    (flet ((inner ()
             (format t "closure:~%   closed-over-var = ~S~%   lexer =
~S~%" closed-over-var lexer)))
      (pcl:set-funcallable-instance-function lexer #'inner)
      (format t "outside 2:~%   closed-over-var = ~S~%   inner = ~S~%
 lexer = ~S~%" closed-over-var #'inner lexer)
      lexer)))

(let ((lexer (make-lexer :foo)))
  (funcall lexer))
- - -

CMU Common Lisp 20b-pre2 (20B Unicode), running on framboos
With core: /home/willem/lisp/cmucl-20b-pre2/lib/cmucl/lib/lisp-sse2.core
Dumped on: Mon, 2010-09-06 19:12:52+02:00 on lorien2
See <http://www.cons.org/cmucl/> for support information.
Loaded subsystems:
    Unicode 1.8 with Unicode version 5.1.0
    Python 1.1, target Intel x86/sse2
    CLOS based on Gerd's PCL 2010-03-19 15:19:03
* (progn (compile-file "/tmp/foo.lisp") (load "/tmp/foo"))

; Python version 1.1, VM version Intel x86/sse2 on 2010-09-24 23:03:15.
; Compiling: /tmp/foo.lisp 2010-09-24 23:03:06

; Compiling Load Time Value of (PCL::ENSURE-CTOR '(PCL::CTOR LEXER)
'LEXER ...):
; Converted MAKE-LEXER.
; Compiling DEFUN MAKE-LEXER:
; Byte Compiling Top-Level Form:

; /tmp/foo.sse2f written.
; Compilation finished in 0:00:00.

; Loading #P"/tmp/foo.sse2f".
Warning:
   Changing meta-class of LEXER from KERNEL::STANDARD-CLASS to
KERNEL:RANDOM-PCL-CLASS.
outside 1:
   closed-over-var = :FOO
   lexer = #<LEXER NIL (0) {584ABBE9}>
outside 2:
   closed-over-var = :FOO
   inner = #<Closure Over Function (FLET INNER MAKE-LEXER) {584ADAA9}>
   lexer = #<LEXER NIL (0) {584ABBE9}>
closure:
   closed-over-var = #<Wrapper #<FUNCALLABLE-STANDARD-CLASS LEXER {582BFBDD}>
                       {582CC1FD}>     <-- !!!
   lexer = #<Closure Over Function (FLET INNER MAKE-LEXER) {584ADA99}>
    <-- !!!
T

- - -
However, when the Lisp file is loaded without compiling, things go fine:

* (load "/tmp/foo.lisp")

; Loading #P"/tmp/foo.lisp".
outside 1:
   closed-over-var = :FOO
   lexer = #<LEXER NIL (0) {5867E8B9}>
outside 2:
   closed-over-var = :FOO
   inner = #<Interpreted Function (FLET INNER) {5867F7B9}>
   lexer = #<LEXER NIL (0) {5867E8B9}>
closure:
   closed-over-var = :FOO
   lexer = #<LEXER NIL (0) {5867E8B9}>
T

- Willem



More information about the cmucl-imp mailing list