Code Comments
Programming Forum and web based access to our favorite programming groups.rocco.rossi@gmail.com writes: > The only thing is that I didn't expect to find out that EVAL does not > "see" the lexically scoped environment in which it is operating. WHY > IS THAT? I'm really very curious. I tried some stuff, for instance, in > the Python language with its eval function, and the lexical scoping > was valid, so I can't figure out the reason for doing it differently > in Lisp. The reason is because Common Lisp is an industrial strong programming language. It is designed with efficiency in mind (that's why some CL compilers beat some C compilers). Compilation time of the lexical environment occurs before evaluation time of the EVAL call, and CL allows very optimized compilation of lexical environments. The name of the variable, and even the variable themselves maybe optimized out, may and will disappear from the generated code. When EVAL is called, there is no more a lexical environment to be used, only processor instructions doing references to the heap or the stack. Not a symbol in sight. (disassemble (compile nil (lambda (a b c) (let ((d (- (* b b) (* 4 a c)))) (when (plusp d) (eval '(+ 1 1))))))) Disassembly of function NIL (CONST 0) = 4 (CONST 1) = (+ 1 1) 3 required arguments 0 optional arguments No rest parameter No keyword parameters 16 byte-code instructions: 0 (LOAD&PUSH 2) 1 (LOAD&PUSH 3) 2 (CALLSR&PUSH 2 55) ; * 5 (CONST&PUSH 0) ; 4 6 (LOAD&PUSH 5) 7 (LOAD&PUSH 4) 8 (CALLSR&PUSH 3 55) ; * 11 (CALLSR&PUSH 1 54) ; - 14 (LOAD&PUSH 0) 15 (CALLS2 147) ; PLUSP 17 (JMPIFNOT1 L24) 19 (CONST&PUSH 1) ; (+ 1 1) 20 (CALLS1 91) ; EVAL 22 (SKIP&RET 5) 24 L24 24 (SKIP&RET 5) NIL C/USER[157]> See? No D! Note how the value (- (* b b) (* 4 a c)) is not even stored anywhere. -- __Pascal Bourguignon__ http://www.informatimago.com/ This is a signature virus. Add me to your signature and help me to live.
Post Follow-up to this messagePascal Bourguignon wrote: > The name of the variable, and even the variable themselves maybe > optimized out, may and will disappear from the generated code. When > EVAL is called, there is no more a lexical environment to be used, > only processor instructions doing references to the heap or the > stack. Not a symbol in sight. Not to encourage use of eval, but just to note that while the name may indeed be optimised away, you can of course choose to _explicitly_ splice values from lexical variables into the lisp expression to be eval'd if you really want to. Sometimes I feel the whole "no lexical environment" thing is getting to be a bit overstated - it's of course entirely true, but at the same time, if you really want to inject a value into the expression to be evalled you can, you just have to do it explicitly, and it doesn't matter if that value happens to come from a lexical variable. (disassemble (compile nil (lambda (a b c) (let ((d (- (* b b) (* 4 a c)))) (when (plusp d) (eval (list '+ d 1))))))) Of course, this does not diminish the fact that usually, when if you're using eval, chances are you probably shouldn't be...
Post Follow-up to this messageOn Apr 2, 4:51 am, David Golden <david.gol...@oceanfree.net> wrote: > Pascal Bourguignon wrote: > > Not to encourage use of eval, but just to note that while the name may > indeed be optimised away, you can of course choose > to _explicitly_ splice values from lexical variables into the lisp > expression to be eval'd if you really want to. > > Sometimes I feel the whole "no lexical environment" thing is getting to > be a bit overstated - it's of course entirely true, but at the same > time, if you really want to inject a value into the expression to be > evalled you can, you just have to do it explicitly, and it doesn't > matter if that value happens to come from a lexical variable. > > (disassemble (compile nil (lambda (a b c) > (let ((d (- (* b b) (* 4 a c)))) > (when (plusp d) > (eval (list '+ d 1))))))) > > Of course, this does not diminish the fact that usually, when if > you're using eval, chances are you probably shouldn't be... Thanks guys for clearing this up for me. David, to tell you the truth, I had no intention of using EVAL actually, and I think that it's a much better option to use macros practically all of the time, but, still I was really curious to know why the difference between, say, Python's choice of conserving lexical scoping for the eval function, and Lisp's decision not to. Now, I understand perfectly. And thank you for showing me that it is possible to "inject" values from the lexical scope in eval anyway, using LIST (clever :) ).
Post Follow-up to this messageDavid Golden <david.golden@oceanfree.net> wrote: > (disassemble (compile nil (lambda (a b c) > (let ((d (- (* b b) (* 4 a c)))) > (when (plusp d) > (eval (list '+ d 1))))))) This only works if the value of d is self-evaluating. If your goal is to handle the value of d within the eval, then you should probably write it as (eval `(+ ',d 1)) Compare: (defun foo (thing) (eval (list 'list ''before thing ''after))) (foo '(error "this error is signalled.")) (defun bar (thing) (eval `(list 'before ',thing 'after))) (bar '(error "this form is just included in the output.")) -- [mdw]
Post Follow-up to this messagerocco.rossi@gmail.com wrote: > Now, I understand perfectly. And thank you > for showing me that it is possible to "inject" values from the lexical > scope in eval anyway, using LIST (clever :) ). Well, just pay close attention to Mark Wooding's reply re backquote and self-evaluation too. If d had somehow been the list (- 7 4) say, it would have been spliced in and evaluated as part of the expression, and you might (wrong) or might not (right) have naively expected an error since (- 7 4) is not a number, it's a list, though the result of its standard evaluation is of course a number. In the obscure cases where I've ever felt like doing this, I think the splice-evaluate is just what I wanted anyway, but Mark is right too. Just remember you're building up a whole expression and then evaluating it, and it all makes sense, honest. i.e. (let ((d '(- 7 4))) (eval (list '+ d 1))) => 4 because (let ((d '(- 7 4))) (list '+ d 1)) => (+ (- 7 4) 1) ** vs (let ((d '(- 7 4))) (eval `(+ ',d 1))) => TYPE ERROR because (let ((d '(- 7 4))) `(+ ',d 1)) => (+ '(- 7 4) 1) ** but (let ((d 3)) (eval `(+ ',d 1))) => 4 because CL-USER> (let ((d 3)) `(+ ',d 1)) => (+ '3 1) (and '3 => 3)
Post Follow-up to this messagerocco.rossi@gmail.com writes: > I've come across the following in the hyperspec regarding the function > INTERN: > > "It is implementation-dependent whether the string that becomes the > new symbol's name is the given string or a copy of it. Once a string > has been given as the string argument to intern in this situation > where a new symbol is created, the consequences are undefined if a > subsequent attempt is made to alter that string." > > Does this mean that, to play it safe, the best way to assign a value > to a symbol converted from a string would be using COPY-SEQ as > follows? Well, I think to play it safe, it would be best if you don't mutate your strings, unless you have explicitly created them with MAKE-STRING to use as buffers. Mutating literal strings is non-conforming code anyway. > (defparameter *name* "my-variable") > (setf (symbol-value (intern (copy-seq (string-upcase *name*)))) "Any > old value!") Here, the value of *name* is a literal string, so you shouldn't ever try doing (setf (char *name* 1) #\e) on it. You would really only need to worry about using COPY-SEQ if you had some buffer that you expected to be mutated that you were passing to INTERN. -- Thomas A. Russ, USC/Information Sciences Institute
Post Follow-up to this message> > Constructor Summary > From: Frank Buss <f...@frank-buss.de> > http://java.sun.com/j2se/1.4.2/docs...on.html#JButton(j avax.swing.Icon) > public JButton(Icon icon) > Creates a button with an icon. Correct, but irrelevant. The topic of discussion was whether textual labels were symbols or strings, not whether other kinds of labels can also be used. Clearly the OP was referring to the print-name of the symbol, trying to concatenate those print-names, not some other ICON property of a symbol and trying to concatenate picture-icons together to make a larger icon. (And as it turned out, what he *really* wanted was a symbol as a variable whose value cell held a link to the widgit, which had nothing to do with a label or icon displayed on the widget itself.) Today we have US-ASCII characters in strings and print-names of symbols and syntax of source code. Tomorrow we'll have UniCode characters for the same use. A Chinese adaption of Common Lisp might use single Chinese characters for most of the common Lisp functions. Maybe someday when our youngsters are dumbed down that they can't read English or any other ordinary language, hence can't even begin to understand program syntax, we'll need to devise a totally icon-based graphical programming language with not a single character of ordinary text like natural language anywhere. It'd be almost like we took the picture icons that fill the top rows above the edit area of a MS-Word window and used them as the primitives of our langauge. Or maybe China will revert their written language to the old form that had actual pictures of stuff (like Egyption heirogliphics), and all the youngers worldwide will recognize them as familiar icons and all programming languages will switch to ancient-Chinese icons?
Post Follow-up to this message> From: rocco.ro...@gmail.com > I'm sorry, my fault. I didn't mean label, I meant identifier. I > was looking for a way to actually bind values to symbols being > generated automatically, like button1, button2, etc... but I meant > variables, not the text labels that go on the buttons. Thanks for the correction so we can start solving the *actual* problem you have instead of the mis-speak problem. So you need to explain when such labels will first be built and how long they will last and how many different parts of your system will need to share knowledge of these symbols? For example, is it necessary only to build these symbols at runtime, and also at runtime to keep a list or hash table of these symbols as well as pointers to inviduals which are passed around as parameters and return values and deposited in semi-permanent places within the runtime environment? Is there any reason whatsoever that the user, at runtime, would need to manually type in something representing one of these symbols and thereby select something to happen to it? Or would all selection of these symbols be via a menu, where direct links to the symbols would be in the menu-object so no translation from type-in to internal-object would need ever occur? I suggest *very* strongly that you make a list of all use-cases that in any way directly use these symbols, so that we can decide what characteristics they require. If any use-case requires manual type-in, not menu selection, then there must be a global list or hashtable that would support lookup. Also if there's any function that affects *all* these symbols, then again you need some kind of global collection of them. Will it be possible to build an unlimited number of new labels at runtime, and then generate code that makes reference to these labels, which can then be EVALed? All these kinds of use-case questions need to be answered before we can make any further effort toward helping you. If we try to guess what your use-cases are, we'll be wasting our time and yours. Depending on use cases, the best design might be a special package that has all these symbols, or just a simple hashtable of uninterned symbols, or just an a-list of uninterned symbols, or no global collection of them all whatsoever, or not symbols at all but rather CLOS objects or just DEFSTRUCTs in some class you define yourself.
Post Follow-up to this message> From: Alan Crowe <a...@cawtech.freeserve.co.uk> > Symbols are for when you want to trade to get fast identity > checks at the exense of a lack of internal structure. INTERN > uses a hash table to recognise strings that it has interned before. > Strings are for the opposite trade: easy to append and check > for substrings, but identity requires a character by > character comparison. Let me say that in different words that IMO might be more clear: Symbols are for where you will need lots of comparison at runtime, so you want to invest some effort to canonicalize the textual names so that all duplicates of the same string of characters will be identical machine location, so that comparison then becomes trivial. Symbols also have a lot of storage overhead to store the value cell and the function cell and the properties cell as well as the link from the main cell to the print-name cell. If you write (setq x 5) (setq y (+ x 3)) it's essential that the first x match the second x, so that the second expression can see the value you assigned in the first expression, so you use a symbol. If you tried to do it by strings, the code would read something like this: (setq $ht$ (make-hash-table :test #'equal)) (setf (get $ht$ "x") 5) (setf (get $ht$ "y") (+ (get $ht$ "x") 3)) See how messy it is to register each new value of "x" in the hash table then recover it later via another hashtable lookup? And every time you enter a function and want to establish a lexical context, you'd have to build a whole new hash table!! And how would you pass parameters to a function without using symbols as parameters?? Maybe you'd prefer Unix's argv convention, using a hashtable for parameters to each function? (defun arithemetical-mean (myht) (return (/ (+ (get myht "1") (get myht "2")) 2))) (let ((arght (make-hash-table :test #'equal))) (setf (get arght "1") (get $ht$ "x1")) (setf (get arght "2") (get $ht$ "x2")) (setf (get $ht$ "y") (arithemetical-mean arght))) Strings are for where you don't really care to find matches most of the time, all you care is how the strings print out, so you aren't willing to go to all the overhead of canonicalizing each string.
Post Follow-up to this messagePowered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.