mnjafar@wsuiar.uucp (06/05/90)
I am a newcomer to lisp, so forgive my ignorance. I ran the test programs shown below on three different machines with Common Lisp. The results of the tests are shown below. Does anyone out there know the answer to why Eval behaves in the way it does. I looked in Guy Steele's book, but did not find an answer, maybe I don't know where to look . What exactly is supposed to happen when I issue an (eval '(setq i j)) inside a block ? The first test --------------------------------------------------- ;Test1.lsp ; (defun strange() (let (j i xpr) (setq i 12) (setq xpr '(setq j i)) (format t " ~% The value of i inside the function is : ~a~%" i) (format t " ~% The value of xpr inside the function is : ~a~%" xpr) (eval xpr) (format t " ~% The value of j inside the function is :~a~%" j) ) ) (strange) --------------------------------------------------- The second test --------------------------------------------------- ;Test2.lsp ; (defun strange() (let (j i xpr) (setq i 12) (setq xpr '(setq j i)) (format t " ~% The value of i inside the function is : ~a~%" i) (format t " ~% The value of xpr inside the function is : ~a~%" xpr) (eval xpr) (format t " ~% The value of j inside the function is :~a~%" j) j ) ) (setq i 13) (format t " ~% The value of i outside the function is : ~a~%" i) (strange) ---------------------------------------------------- The results obtained Machine: VAX 8650 running VMS 5.2 Vax Lisp V 2.2 Test | Error Message or value of j --------------------------------------------- test1 | symbol has no value : I test2 | nil Machine: SUN Sun Common Lisp, development environment 3.0.2 Test | Error Message or value of j --------------------------------------------- test1 | the symbol I has no global value test2 | nil Machine: PC/AT compatible Golden Common Lisp Version 1.01 Test | Error Message or value of j --------------------------------------------- test1 | 12 test2 | 12 Mohammad Jafar mnjafar@wsuiar.wsu.ukans.edu
lou@atanasoff.rutgers.edu (Lou Steinberg) (06/08/90)
In article <200.266aae50@wsuiar.uucp> mnjafar@wsuiar.uucp writes: > I looked in Guy Steele's book, but did not find an answer, > maybe I don't know where to look . What exactly is supposed to > happen when I issue an (eval '(setq i j)) inside a block ? See the definition of eval (p. 490 of 2nd edition of Steele): eval form The form is evaluated in the current lexical environment and a null lexical environment. The term "null lexical environment" means that the eval does NOT take place in the lexical scope where the eval appears. Thus, to simplify your example, (defun strange () (let (i j) (eval '(setq j i)))) is equivalent to (defun strange () (let (i j) (strange1))) (defun strange1 () (setq j i)) Note that the value of j your example code prints is for the binding INSIDE strange, which is unaffected by the setq of the top-level value done by the eval, and thus is still its initial value, NIL. I assume the language was defined this way because, in the general case, the form to be evaled may not be available until run time, but an efficient compiler may want to compile things in such a way that at runtime it is hard to figure out, e.g., that local variable i is currently being stored in register D3. Without this information, of course, the code to be evaled could not be properly interpretted (or compiled). Yes, this information could be kept somewhere, but the question is whether this kind of runtime access to the lexical environment would be worth the overhead needed to provide it. So, by your tests, Golden Common Lisp Version 1.01 is not a correct implementation of lexical scoping. (This may have been corrected in later versions.) The results returned by the other two implementations are correct. -- Lou Steinberg uucp: {pretty much any major site}!rutgers!aramis.rutgers.edu!lou arpa: lou@cs.rutgers.edu
jeff@aiai.ed.ac.uk (Jeff Dalton) (06/08/90)
In article <200.266aae50@wsuiar.uucp> mnjafar@wsuiar.uucp writes: > > I am a newcomer to lisp, so forgive my ignorance. I ran the >test programs shown below on three different machines with >Common Lisp. The results of the tests are shown below. Does >anyone out there know the answer to why Eval behaves in the way >it does. I looked in Guy Steele's book, but did not find an answer, >maybe I don't know where to look. In CLtL, you need to look at 3 Scope and Extent 5.1.2 Variables 7.1.1 Reference: 1st paragraph 7.5 Establishing New Variable Bindings 9.2 Declaration specifiers: the part on SPECIAL 20.1 Run-Time Evaluation of Forms: EVAL Pay attention to all the places where it talks about the distinction between special variables and other kinds. Then note that EVAL evaluates an expression in the current dynamic environment and a null lexical environment. Note too that global variables are the "outermost" special variables. Now suppose we do (setq x 'global-x) Then consider the following examples. They just refer to values rather than use SETQ because it's simpler. Where the local value is obtained, a SETQ would set the local value; and similarly for the global value. (let ((x 'local-x)) x) ==> local-x The LET establishes a _lexical_ variable X and gives it the value LOCAL-X. (let ((x 'local-x)) (eval 'x)) ==> global-x The LET works as before, but since EVAL uses a null lexical environment it does not "see" the local X. (let ((x 'local-x)) (declare (special x)) x) ==> local-x Here the LET establishes a _special_ variable X, because of the declaration. (let ((x 'local-x)) (declare (special x)) (eval 'x)) ==> local-x This is because EVAL uses the _current_ dynamic (ie, special variable) environment. Ok, now let's try this one: (setq x 'x0 y 'y0) (defun test () (let (x y) (declare (special y)) (setq x 'x1 y 'y1) (format t "~&X = ~S; Y = ~S~%" x y) (eval '(setq x 'x2 y 'y2)) (format t "~&X = ~S; Y = ~S~%" x y)) (format t "~&X = ~S; Y = ~S~%" x y)) After this, "(test)" will print: X = x1; Y = y1 X = x1; Y = y2 X = x2; Y = y0 What happens when test is called is: 1. The LET sets up local lexical variable X and a local special variable Y. 2. The SETQ sets the values of those same variables. 3. The EVAL of SETQ sets the global (special) X, because there is no local one, and the local (special) Y. Remember that EVAL uses the current special environment but a null lexical one. So it will see only global or local special variables. >What exactly is supposed to happen when I issue an (eval '(setq i j)) >inside a block ? What it is supposed to do is to set the global value of I to be the global value of J, just as if you typed "(setq i j)" directly to the top-level read-eval-print loop. Actually for "global value" I should really say something like "value of the current binding of the special variable". Note, however, that in your tests you do "(setq j i)" instead. ;Test1.lsp (defun strange() (let (j i xpr) (setq i 12) (setq xpr '(setq j i)) (eval xpr) (format t " ~% The value of j inside the function is :~a~%" j) ) ) Calling (strange) should result in an error saying "I" is unbound or has no global value (unless, of course, you've given it one independently. Your test2 is the same, except that you *do* give "I" a global value. By calling EVAL on (SETQ J I), you set the global value of J to be (in this case) 13. The local value of J (ie, inside the function) will be NIL, because that's what LET gives it initially. The results for Golden Common Lisp 1.01 are incorrect. What is probably happening is that it is interpreting local variables (such as those introduced by LET) as special variables. The SETQ given to EVAL affects such variables. Indeed, note that the value of J is 12 and not 13 even though in test2 you set the global value of I to 13. I suspect a more recent version of GCL would give results in line with the other Common Lisps. -- Jeff
scott@wiley.uucp (Scott Simpson) (06/09/90)
In article <200.266aae50@wsuiar.uucp> mnjafar@wsuiar.uucp writes: > I am a newcomer to lisp, so forgive my ignorance. I ran the >test programs shown below on three different machines with >Common Lisp. The results of the tests are shown below. Does >anyone out there know the answer to why Eval behaves in the way >it does. I looked in Guy Steele's book, but did not find an answer, >maybe I don't know where to look . What exactly is supposed to >happen when I issue an (eval '(setq i j)) inside a block ? >;Test1.lsp >(defun strange() > (let (j i xpr) ;j, i and xpr are nil > (setq i 12) > (setq xpr '(setq j i)) > (format t " ~% The value of i inside the function is : ~a~%" i) > (format t " ~% The value of xpr inside the function is : ~a~%" xpr) > (eval xpr) > (format t " ~% The value of j inside the function is :~a~%" j) > ) >) >(strange) Eval is executed in its own local environment. The stack of execution looks like |---------------------| |eval + environment |___ |---------------------| | |strange + environment| | ----------------------- | Can't find i! V Since i is not in eval's environment and it is not in the global environment you get an error. If you change the line (let (j i xpr) to (let (j i xpr) (declare (special i)) then i is dynamically scoped and it will be found in strange's environment. |---------------------| |eval + environment |___ |---------------------| | finds i dynamically, sets global j |strange + environment|<-- ----------------------- The function strange will now completes correctly and returns The value of i inside the function is : 12 The value of xpr inside the function is : (SETQ J I) The value of j inside the function is :NIL Notice that j is nil. The setq in the eval creates and sets a global variable named j (try evaluating j after running the new strange function with the declare). The j inside the function strange is never set. If you wish to set the j inside the function, declare it dynamically scoped also. (let (j i xpr) (declare (special i) (special j)) The result is now The value of i inside the function is : 12 The value of xpr inside the function is : (SETQ J I) The value of j inside the function is :12 No global j is created. >;Test2.lsp >(defun strange() > (let (j i xpr) > (setq i 12) > (setq xpr '(setq j i)) > (format t " ~% The value of i inside the function is : ~a~%" i) > (format t " ~% The value of xpr inside the function is : ~a~%" xpr) > (eval xpr) > (format t " ~% The value of j inside the function is :~a~%" j) > j > ) >) >(setq i 13) >(format t " ~% The value of i outside the function is : ~a~%" i) >(strange) This yielded The value of i inside the function is : 12 The value of xpr inside the function is : (SETQ J I) The value of j inside the function is :NIL J is still nil. The j set by the eval was a global j. A global i exists now though so you only need to make j special. Try making j special and you get The value of i inside the function is : 12 The value of xpr inside the function is : (SETQ J I) The value of j inside the function is :12 > The results obtained >Machine: VAX 8650 running VMS 5.2 > Vax Lisp V 2.2 >Test | Error Message or value of j >--------------------------------------------- >test1 | symbol has no value : I >test2 | nil > >Machine: SUN > Sun Common Lisp, development environment 3.0.2 >Test | Error Message or value of j >--------------------------------------------- >test1 | the symbol I has no global value >test2 | nil These are correct. >Machine: PC/AT compatible > Golden Common Lisp Version 1.01 > >Test | Error Message or value of j >--------------------------------------------- >test1 | 12 >test2 | 12 This is incorrect. Scott Simpson TRW scott@wiley.coyote.trw.com