From: Bruno H. <br...@cl...> - 2004-12-20 21:31:50
|
> [138]> (defun verouille (mot-de-passe valeur) > (let ((val valeur) > (mdp mot-de-passe)) > (list > (lambda (cle) (when (eq cle mdp) val)) > (lambda (cle nouvelle) (when (eq cle mdp) (setf val nouvelle)))))) > VEROUILLE > ... > [146]> (defparameter val 3) > VAL By evaluating this defparameter form, you have changed the meaning of the verouille function that you entered earlier. VAL was not declared special before but is declared special afterwards. This explains everything. You probably need a DEFPARAMETER without DECLAIM SPECIAL. This beast is usually called DEFGLOBAL. It defines a global variable but does not affect the behaviour when the symbol is bound. In clisp, DEFGLOBAL is trivial: (defmacro defglobal (symbol initform) `(setq ,symbol ,initform)) In SBCL, DEFGLOBAL is a little less trivial. See http://groups.google.de/groups?q=defglobal&hl=de&lr=&ie=UTF-8&group=comp.lang.lisp.*&selm=xcvu0rhls2z.fsf%40conquest.OCF.Berkeley.EDU&rnum=6 Bruno |
From: Sam S. <sd...@gn...> - 2004-12-20 22:09:54
|
> * Pascal J.Bourguignon <cwo@vasbezngvzntb.pbz> [2004-12-20 22:51:34 +0100]: > > Why the interpreted closure has not the same semantics as the compiled > closure? because the meaning of the interpreted closure is determined at the interpretation time. this means that whenever you call an interpreted function, it is analyzed anew (modulo macroexpansion which has been done at closure creation time), and if a variable happened to be special at one time and lexical at another time, then evaluation will produce different results. > Why the clisp interpreted closure has not the same semantics as the > closures in other implementations? because SBCL always compiles everything (IIUC). > Why should the meaning of a closure change for ulterior declarations? for "interpreted" closures, see above. compiled closures should not be affected. -- Sam Steingold (http://www.podval.org/~sds) running w2k <http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/> <http://www.mideasttruth.com/> <http://www.honestreporting.com> UNIX, car: hard to learn/easy to use; Windows, bike: hard to learn/hard to use. |
From: Pascal J.B. <pj...@in...> - 2004-12-20 23:38:26
|
Sam Steingold writes: > > * Pascal J.Bourguignon <cwo@vasbezngvzntb.pbz> [2004-12-20 22:51:34 +0100]: > > > > Why the interpreted closure has not the same semantics as the compiled > > closure? > > because the meaning of the interpreted closure is determined at the > interpretation time. > this means that whenever you call an interpreted function, it is > analyzed anew (modulo macroexpansion which has been done at closure > creation time), and if a variable happened to be special at one time and > lexical at another time, then evaluation will produce different results. > > > Why the clisp interpreted closure has not the same semantics as the > > closures in other implementations? > > because SBCL always compiles everything (IIUC). ecls has an interpreter as clisp, but it does it right. > > Why should the meaning of a closure change for ulterior declarations? > > for "interpreted" closures, see above. > compiled closures should not be affected. Ok, I overread 3.2.2.3 claim of "minimizing" differences between interpreted and compiled code... So I guess I'll have to write: (defun verouille (mot-de-passe valeur) (let ((#1=#:val valeur) (#2=#:mdp mot-de-passe)) (list (lambda (cle) (when (eq cle #2#) #1#)) (lambda (cle nouvelle) (when (eq cle #2#) (setf #1# nouvelle)))))) to get the effect I need. -- __Pascal Bourguignon__ http://www.informatimago.com/ In a World without Walls and Fences, who needs Windows and Gates? |
From: Bruno H. <br...@cl...> - 2004-12-21 12:17:13
|
Pascal J.Bourguignon wrote: > Why the interpreted closure has not the same semantics as the compiled > closure? Because the compiler makes some optimizations that "fix" the semantics of the functions - ANSI CL 3.2.2.3: "Special proclamations for dynamic variables must be made in the compilation environment. Any binding for which there is no special declaration or proclamation in the compilation environment is treated by the compiler as a lexical binding." and there is no such requirement for the interpreter. > Why the clisp interpreted closure has not the same semantics as the > closures in other implementations? Because the interpreter in other implementations apparently do a little more preprocessing in the interpreter than clisp does. For performance reasons or for ease of debugging - I don't know. > Why should the meaning of a closure change for ulterior declarations? Because the goal of an interpreter is to allow changes to take effect immediately, without recompilation of the whole program. > The problem is not with defparameter. It's that I want a lexical > closure, and I don't get it! Then don't proclaim SPECIAL your variable. A variable that has been proclaimed special cannot be bound lexically. Bruno |
From: Pascal J.B. <pj...@in...> - 2004-12-22 09:18:50
|
Bruno Haible writes: > Pascal J.Bourguignon wrote: > > Why the interpreted closure has not the same semantics as the compiled > > closure? > > Because the compiler makes some optimizations that "fix" the semantics > of the functions - ANSI CL 3.2.2.3: > "Special proclamations for dynamic variables must be made in the > compilation environment. Any binding for which there is no special > declaration or proclamation in the compilation environment is treated > by the compiler as a lexical binding." > and there is no such requirement for the interpreter. That same section declared that these requirements were made to "minimize" the differences between interpreted and compiled code. That's why I was surprised to see a difference. > > The problem is not with defparameter. It's that I want a lexical > > closure, and I don't get it! > > Then don't proclaim SPECIAL your variable. A variable that has been > proclaimed special cannot be bound lexically. I think it's an overlook of the standard. It means that any interpreted closure can be broken just by ulteriorly declaring some special variable colliding with the lexical variables the closure use. Worse, such a declarations makes all lexical variables merge: [pjb@thalassa encours]$ clisp ;; Loading file /home/pascal/.clisprc.lisp ... [1]> (let ((a 1)) (defun f () (incf a))) F [2]> (let ((a "Hello")) (defun g (x) (print a) (setf a x))) G [3]> (f) 2 [4]> (g "World") "Hello" "World" [5]> (f) 3 [6]> (g "Howdy") "World" "Howdy" [7]> (f) 4 [8]> (defvar a '(broken)) A [9]> (f) *** - +: (BROKEN) is not a NUMBER The following restarts are available: USE-VALUE :R1 You may input a value to be used instead. Break 1 [10]> :q [11]> (g "r2d2") (BROKEN) "r2d2" [12]> (f) *** - +: "r2d2" is not a NUMBER The following restarts are available: USE-VALUE :R1 You may input a value to be used instead. Break 1 [13]> :q [14]> I agree that the standard doesn't mandate an interpreted implementation to do otherwise, but I think the behavior of ecls interpreter, which keeps the compiled semantics, is clearly superior here. -- __Pascal Bourguignon__ http://www.informatimago.com/ The mighty hunter Returns with gifts of plump birds, Your foot just squashed one. |
From: Pascal J.B. <pj...@in...> - 2004-12-20 21:53:02
|
Bruno Haible writes: > > [138]> (defun verouille (mot-de-passe valeur) > > (let ((val valeur) > > (mdp mot-de-passe)) > > (list > > (lambda (cle) (when (eq cle mdp) val)) > > (lambda (cle nouvelle) (when (eq cle mdp) (setf val nouvelle)))))) > > VEROUILLE > > ... > > [146]> (defparameter val 3) > > VAL > > By evaluating this defparameter form, you have changed the meaning of the > verouille function that you entered earlier. VAL was not declared special > before but is declared special afterwards. This explains everything. Why the interpreted closure has not the same semantics as the compiled closure? Why the clisp interpreted closure has not the same semantics as the closures in other implementations? Why should the meaning of a closure change for ulterior declarations? > You probably need a DEFPARAMETER without DECLAIM SPECIAL. This beast is > usually called DEFGLOBAL. It defines a global variable but does not > affect the behaviour when the symbol is bound. The problem is not with defparameter. It's that I want a lexical closure, and I don't get it! $ clisp ;; Loading file /home/pascal/.clisprc.lisp ... [1]> (let ((val 1)) (defun get-val () val)) GET-VAL [2]> (get-val) 1 [3]> (defparameter val 2) VAL [4]> (get-val) 2 [5]> (let ((vol 1)) (defun get-vol () vol)) GET-VOL [6]> (compile 'get-vol) GET-VOL ; NIL ; NIL [7]> (defparameter vol 2) VOL [8]> (get-vol) 1 [9]> -- __Pascal Bourguignon__ http://www.informatimago.com/ This is a signature virus. Add me to your signature and help me to live |
From: Thomas F. B. <tfb@OCF.Berkeley.EDU> - 2004-12-20 22:18:07
|
Pascal J.Bourguignon writes: > Bruno Haible writes: > > > [138]> (defun verouille (mot-de-passe valeur) > > > (let ((val valeur) > > > (mdp mot-de-passe)) > > > (list > > > (lambda (cle) (when (eq cle mdp) val)) > > > (lambda (cle nouvelle) (when (eq cle mdp) (setf val nouvelle)))))) > > > VEROUILLE > > > ... > > > [146]> (defparameter val 3) > > > VAL > > > > By evaluating this defparameter form, you have changed the meaning of the > > verouille function that you entered earlier. VAL was not declared special > > before but is declared special afterwards. This explains everything. > > Why the interpreted closure has not the same semantics as the compiled > closure? Because it's *interpreted*: the interpreter is evaluating the Lisp source as data, in the current environment. The compiler fixes the semantics of the function to use the environment it was compiled in. If you proclaim closed-over variables to be special, or redefine macros between invocations of an interpreted function, the behavior of the interpreted function will necessarily change, because it's being interpreted. If you want to avoid this, compile the function. This is the behavior of an obvious, naive interpreter -- it would be possible to try to have the interpreter's semantics more closely match the compiler's here, but this kind of flexibility can be as much of a boon as a bane. And unless I've missed something, there's nothing in the spec that disallows this. > Why the clisp interpreted closure has not the same semantics as the > closures in other implementations? I have a metacircular evaluator for SBCL that I'm going to submit when I get back from vacation -- assuming this gets merged, CLISP's interpreted semantics will match SBCL's. > The problem is not with defparameter. It's that I want a lexical > closure, and I don't get it! Then don't declare the variable to be globally special. Or, compile the function before you do. |