e343ca@tamuts.tamu.edu (Colin Allen) (02/21/91)
Can anyone tell me why foo1 below appears to execute the read-line before the print, but foo2 executes the print before the read? (defun foo1 () (print 'hello) (read-line)) (defun foo2 () (print 'hello) (read)) Thanks. Colin Allen e343ca@tamuts.tamu.edu Department of Philosophy Texas A&M University (409) 845-3606 College Station, TX 77843-4237
e343ca@tamuts.tamu.edu (Colin Allen) (02/21/91)
In article <12413@helios.TAMU.EDU> e343ca@tamuts.tamu.edu I asked: >Can anyone tell me why foo1 below appears to execute the read-line >before the print, but foo2 executes the print before the read? > >(defun foo1 () (print 'hello) (read-line)) >(defun foo2 () (print 'hello) (read)) I should add that I have checked this code now in Kyoto and Franz Allegro Common Lisp and the weird behavior occurs only in kcl. So possibly this is a bug in kcl. Anyone run into this before? Colin Allen e343ca@tamuts.tamu.edu Department of Philosophy Texas A&M University (409) 845-3606 College Station, TX 77843-4237
eliot@phoenix.Princeton.EDU (Eliot Handelman) (02/21/91)
In article <12413@helios.TAMU.EDU> e343ca@tamuts.tamu.edu (Colin Allen) writes: ;Can anyone tell me why foo1 below appears to execute the read-line ;before the print, but foo2 executes the print before the read? ; ;(defun foo1 () (print 'hello) (read-line)) ;(defun foo2 () (print 'hello) (read)) In my KCL READ-LINE reads the hanging #\Newline when you hit return. If I were to execute foo1 I'd get something like this: > (foo1) HELLO"" I don't have a chance to type in anything at all. If I do this: > (progn (foo1) (foo1))) HELLO HELLOand now I can type "and now I can type" Note, incidentally, another KCl bug -- PRINT doesn't leave a space after printing, as it should. Anyhow, READ-LINE doesn't work right in KCL, and the thought occurs to me -- is it possible that READ-LINE is reading the PRINT statement?
barmar@think.com (Barry Margolin) (02/21/91)
In article <12413@helios.TAMU.EDU> e343ca@tamuts.tamu.edu (Colin Allen) writes: >Can anyone tell me why foo1 below appears to execute the read-line >before the print, but foo2 executes the print before the read? > >(defun foo1 () (print 'hello) (read-line)) >(defun foo2 () (print 'hello) (read)) My guess is that KCL's READ performs a FORCE-OUTPUT call before starting to read input, but READ-LINE doesn't. I don't think CLtL specifies anything about this interaction, so I suggest you put your own call to FORCE-OUTPUT before any input functions when necessary. -- Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
lkramer@brahms.udel.edu (Laurence Kramer) (02/21/91)
Permit me to flame a while... Last week I wrote a message that said briefly that people doing AI R&D in C rather than Lisp needed their heads examined. Well, this common lisp "feature" mentioned further reinforces another opinion I have: People developing in common lisp need their heads examined. If I write (foo a) (foo2 b), I would certainly expect foo to be evalled before foo2. As a software developer I shouldn't have to worry that the combination of foo and foo2 somehow is different than most other functions I know about. This is certainly in direct opposition to the spirit of Lisp programming! The problem with common lisp is not so much that it is too big, or that it was written by a committee, etc. The problem with common lisp is that it was written more with an eye to the compiler than to the interpreter. Do people programming in common lisp really need their heads examined? No, they should be pitied because their options are few. In an ideal world we would all be programming in muLisp. It is beautiful, small, efficient, extensible, and really embodies the spirit of what Lisp should be. Two big problems: it is imprisoned within DOS's 640k barrier and isn't portable. (An idea: everyone write letters to Al Rich and convince him to write a portable muLisp. We already tried this, but perhaps if more people tried...) So, what did we (Quantum Software) end up doing? We bit the bullet and wrote our own portable lisp in C (based very closely on muLisp). XLisp is ok, but obviously not up to an industrial strength standards. (Sorry, sportsfans, we're really not interested in selling this Lisp, because we don't have the resources to support it outside of our organization.) Larry
barmar@think.com (Barry Margolin) (02/22/91)
In article <18935@brahms.udel.edu> lkramer@brahms.udel.edu (Laurence Kramer) writes: >Permit me to flame a while... Last week I wrote a message that said >briefly that people doing AI R&D in C rather than Lisp needed their >heads examined. Well, this common lisp "feature" mentioned further >reinforces another opinion I have: People developing in common lisp >need their heads examined. If I write (foo a) (foo2 b), I would certainly >expect foo to be evalled before foo2. As a software developer I shouldn't >have to worry that the combination of foo and foo2 somehow is different >than most other functions I know about. This is certainly in direct >opposition to the spirit of Lisp programming! I've never heard of a case where they would be evaluated out of order, unless they are subforms of a macro call that explicitly rearranges its subforms, e.g. (defmacro do-backwards (&body body) `(progn .,(reverse body))) This can happen in any language with a sufficiently powerful macro processor. The problem that the original poster was running into has nothing to do with things being evaluated out of order. He was simply encountering problems due to the implementation's and OS's I/O buffering, which afflicts many languages, and which can have the appearance of executing things out of order. I've seen similar questions in comp.lang.c; for example, the following Unix C excerpt will likely execute out of order: printf("This should be first. "); write(1, "This should be second. ", 23); By the way, some other Lisp dialects actually *do* have the feature that forms may be evaluated out of order. Scheme deliberately does not specify the order of evaluation of arguments in a function call; if you are concerned about order, you must use BLOCK (the Scheme equivalent to PROGN). Common Lisp specifies that function arguments will be evaluated left to right. -- Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
jeff@aiai.ed.ac.uk (Jeff Dalton) (02/22/91)
In article <18935@brahms.udel.edu> lkramer@brahms.udel.edu (Laurence Kramer) writes: >Permit me to flame a while... Last week I wrote a message that said >briefly that people doing AI R&D in C rather than Lisp needed their >heads examined. Well, this common lisp "feature" mentioned further >reinforces another opinion I have: People developing in common lisp >need their heads examined. If I write (foo a) (foo2 b), I would certainly >expect foo to be evalled before foo2. As a software developer I shouldn't >have to worry that the combination of foo and foo2 somehow is different >than most other functions I know about. This is certainly in direct >opposition to the spirit of Lisp programming! As several others have noted, the problem concerns I/O, not evaluation order. I consider it a _bug_ in KCL and usually load in some code that fixes it. You shouldn't be so quick to seize on examples of how losing Common Lisp is, because they might turn out not to be anything of the kind. >The problem with common lisp is not so much that it is too big, or that it >was written by a committee, etc. The problem with common lisp is that >it was written more with an eye to the compiler than to the interpreter. This reminds me of something someone in BSI said, that the problem with Common Lisp was that it had taken too much from procedural languages. I suspect rather strongly that when you saw what looked like an evaluation order problem you thought "Ah ha! See what happens when you try to make life easy for the compiler!" But the truth is that Common Lisp specifies _more_ of the evaluation order than most other languages (eg, C). Let's face it. Some people don't like Common Lisp and never will. They have all kinds of reasons for thinking CL is bad. But it often turns out that what's behind it is that they have a different idea of what Lisp should be like and think they are in the true Lisp tradition while Common Lisp is a deviation. If you're used to small, interpreted Lisps, you may not like a Lisp that enforces compiler-like semantics (eg, lexical scoping). But _other_ Lisp programmers were used to compiling their programs and wrote "for the compiler", so they're glad Common Lisp enforces the same scope rules in the interpreter. For example, many MacLisp (and Franz Lisp) programmers considered the compiler's semantics to be the real semantics and the use of different scoping rules in the interpreter to be a bug. I think it helps to remember that there's more than one good way to do Lisp. If people disagree about which way is best, it doesn't mean that one side or the other needs their heads examined. -- jd
jeff@aiai.ed.ac.uk (Jeff Dalton) (02/22/91)
In article <12414@helios.TAMU.EDU> e343ca@tamuts.tamu.edu (Colin Allen) writes: >In article <12413@helios.TAMU.EDU> e343ca@tamuts.tamu.edu I asked: >>Can anyone tell me why foo1 below appears to execute the read-line >>before the print, but foo2 executes the print before the read? >> >>(defun foo1 () (print 'hello) (read-line)) >>(defun foo2 () (print 'hello) (read)) > >I should add that I have checked this code now in Kyoto and Franz >Allegro Common Lisp and the weird behavior occurs only in kcl. So >possibly this is a bug in kcl. Anyone run into this before? The behavior I get in KCL is that foo2 does what yuo expect but foo1 does something like this: >(foo1) HELLO "" > That is, read-line returns an empty string and I don't have to type anything. There is no evidence that the read-line happens before the print, and indeed it doesn't. What happens is that the newline after "(foo1)" is still there when read-line is called, and since read-line takes the characters up to the next newline and returns them as a string, you get "". This is, in my opinion, a bug in KCL. But it could be argued that such behavior is allowed by CLtL. One way to deal with the problem is to call clear-input. Another, less reputable, solution would be to redefine read: (defun fix-read () (unless (fboundp 'real-read) (setf (symbol-function 'real-read) (symbol-function 'read) (symbol-function 'read) (symbol-function 'patched-read)))) (defun patched-read (&optional (stream *standard-input*) (eof-error-p t) (eof-value nil) (recursive-p nil)) (let ((object (real-read stream eof-error-p eof-value recursive-p))) (unless recursive-p ;??? (loop (let ((c (read-char-no-hang stream nil nil nil))) (cond ((null c) (return)) ((not (whitespace-p c)) (unread-char c stream) (return)))))) object)) (defun whitespace-p (c) (member c '(#\space #\newline #\tab #\return) :test #'char=)) (defun listen-test () (loop (format t "test> ") (do ((args (list (read)) (cons (read) args))) ((not (listen)) (prin1 (nreverse args)))) (terpri))) -- jeff
dkahn@SCHUBERT.PRODIGY.CS.CMU.EDU (Daniel Kahn) (02/23/91)
|> > |> >(defun foo1 () (print 'hello) (read-line)) |> >(defun foo2 () (print 'hello) (read)) You might try something like this: (defun foo1 () (print 'hello) (finish-output) (read-line)) It is conceivable that in foo1 the print sends its output to operating system and then the read-line beats it to the control of the terminal (is this a "race condition"?). The read-line might then "block" the print from working until it is done. In foo2 the more complicated read would take so long to reach the terminal that the print would be the first one there. This will guarantee syncronicity in I/O so that the print finishes sending is output to the device before the read starts. In general I use finish-output and I check my streams when I have weird output. Also you might use the TRACE macro on print and read-line just to check the order of execution which should be left to right. --dan
lavinus@csgrad.cs.vt.edu (02/23/91)
Yo out there... Everyone seems to be missing a basic point of Lisp philosophy: If you do something like (foo a) (foo2 b), you should not count on that being evaluated left-to-right or right-to-left. Generally, it is good programming practice (in general, but especially in Lisp) not to make any assumptions about order of evaluation unless the *language* (not the compiler) guarantees some particular order (the only example I can think of offhand is C - it guarantees order of evaluation of most everything). So long... Joe Lavinus -- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= = Joseph W. Lavinus = \ / = = Virginia Tech, Blacksburg, Virginia = \/__V = = email: lavinus@csgrad.cs.vt.edu = /\ =
barmar@think.com (Barry Margolin) (02/23/91)
In article <964@creatures.cs.vt.edu> lavinus@csgrad.cs.vt.edu () writes: >Everyone seems to be missing a basic point of Lisp philosophy: If you do >something like (foo a) (foo2 b), you should not count on that being evaluated >left-to-right or right-to-left. Generally, it is good programming practice >(in general, but especially in Lisp) not to make any assumptions about order >of evaluation unless the *language* (not the compiler) guarantees some >particular order (the only example I can think of offhand is C - it guarantees >order of evaluation of most everything). The original question was about KCL, which is an implementation of Common Lisp. Common Lisp *does* guarantee left-to-right order of evaluation, just as its predecessors Maclisp and Zetalisp did. Scheme doesn't specify the order of evaluation of function arguments. Also, in the example he gave the two expressions weren't even arguments to a function, they were top-level forms in a function definition. All recent Lisps that I'm aware of guarantee that top-level forms in a function will be evaluated in order (maybe some concurrent Lisps are exceptions). As if you hadn't put your foot in your mouth far enough, you then get it wrong regarding C as well. C doesn't specify the order of evaluation of arguments to functions and some operators. -- Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
lavinus@csgrad.cs.vt.edu (02/24/91)
Hello out there! Well, folks, this is where I acknowledge a fatal "Engage Brain Before Mouth" failure (and hopefully end the rain of flames). It's quite a task to say two utterly wrong things in the same sentence :-) but I did it. (1) I went and said that Common Lisp does not specify its order of evaluation, but being a Scheme hacker, I should not have presumed to know the finer details of CL in the first place, as I was dead wrong. Second, I had to go further and say that C *does* specify order of evaluation, when what I had in mind was expresion evaluation and not function argument evaluation, which I now realize was pretty much irrelevant to the discussion. Anyway, I accept the full weight of my ignorance, and will be more careful to think before I speak (or type) in the future. To those of you who flamed me, well, I'd like to defend myself, but I deserved it. Yours truly, Joe Lavinus -- _______________________________________________________________ _ _ __ Joseph W. Lavinus (lavinus@csgrad.cs.vt.edu) | / \ |_ Virginia Tech, Blacksburg, Virginia __| \_/ |_
toma@sail.LABS.TEK.COM (Tom Almy) (02/26/91)
In article <964@creatures.cs.vt.edu> lavinus@csgrad.cs.vt.edu () writes: >Everyone seems to be missing a basic point of Lisp philosophy: If you do >something like (foo a) (foo2 b), you should not count on that being evaluated >left-to-right or right-to-left. Generally, it is good programming practice >(in general, but especially in Lisp) not to make any assumptions about order >of evaluation unless the *language* (not the compiler) guarantees some >particular order (the only example I can think of offhand is C - it guarantees >order of evaluation of most everything). I believe you are exactly backwards on this, with one small exception. Quoting from CL:TL (2nd Edition) page 75: "X3J13 voted in October 1988 to clarify that while the arguments in a function call are always evaluated in strict left-to-right order, whether the function to be called is determined before or after argument evaluation is unspecified." On the other hand, from "The C Programming Language" (1st edition) pages 49 and 50: "C, like most languages, does not specify in what order the operands of an operator are evaluated." "Similarly, the order in which function arguments are evaluated is not specified." -- Tom Almy toma@sail.labs.tek.com Standard Disclaimers Apply
jeff@aiai.ed.ac.uk (Jeff Dalton) (02/26/91)
In article <964@creatures.cs.vt.edu> lavinus@csgrad.cs.vt.edu () writes: >Everyone seems to be missing a basic point of Lisp philosophy: If you do >something like (foo a) (foo2 b), you should not count on that being evaluated >left-to-right or right-to-left. Generally, it is good programming practice >(in general, but especially in Lisp) not to make any assumptions about order >of evaluation unless the *language* (not the compiler) guarantees some >particular order (the only example I can think of offhand is C - it guarantees >order of evaluation of most everything). It is of course a good point that one should never rely on order that is not guaranteed by the language. However, some Lisps, such as Common Lisp, do guarantee the order in most cases. Common Lisp guarantees more than C. The guarantee in C is fairly complex and does not include the order of evaluation of parameters to a procedure.
lkramer@brahms.udel.edu (Laurence Kramer) (02/26/91)
Jeff, Your comments are well taken. I guess I was a little too quick to pounce on a bug in KCL in order to make my anti-CommonLisp points. I guess someone used to working with compiled languages would feel more at home with CL. As for me, Lisp is a liberation from type declarations, etc., and a vehicle to write even higher level languages, and unleash productivity and creativity. In my Lisp if a say (pack* 'abc "def") I get |abcdef|. (I don't first have to worry about coercing the types of the arguments.) Larry
bnolan@ccvax.ucd.ie (Breanndan O Nuallain) (03/01/91)
In article <4211@skye.ed.ac.uk>, jeff@aiai.ed.ac.uk (Jeff Dalton) writes: > In article <12414@helios.TAMU.EDU> e343ca@tamuts.tamu.edu (Colin Allen) writes: >>In article <12413@helios.TAMU.EDU> e343ca@tamuts.tamu.edu I asked: >>>Can anyone tell me why foo1 below appears to execute the read-line >>>before the print, but foo2 executes the print before the read? >>> >>>(defun foo1 () (print 'hello) (read-line)) >>>(defun foo2 () (print 'hello) (read)) >> >>I should add that I have checked this code now in Kyoto and Franz >>Allegro Common Lisp and the weird behavior occurs only in kcl. So >>possibly this is a bug in kcl. Anyone run into this before? Yup, VAX Lisp does this too. It puzzled me for a while because it's not realy what you'd expect. > > The behavior I get in KCL is that foo2 does what yuo expect but > foo1 does something like this: > > >(foo1) > HELLO "" > > > > > That is, read-line returns an empty string and I don't have to type > anything. There is no evidence that the read-line happens before the > print, and indeed it doesn't. > > What happens is that the newline after "(foo1)" is still there when > read-line is called, and since read-line takes the characters up to > the next newline and returns them as a string, you get "". > I go along with this. Further evidence is the following (at least on VAX Lisp, can't say for KCL): > (foo1)Goodbye HELLO "Goodbye"; NIL > (The extra value of NIL is the line-terminated-abnormally flag which I assume Jeff left out for clarity above.) My best guess at what is happening is this. The lisp reader checks what you are typing at it, character by character, until it sees a #\newline at which time it evaluates any completed forms it has collected and holds onto what's left for later evaluation. For example: > (first '(a b c)) (+ 1 2 A > 3) 6 > But it seems to check the typed characters by doing something like a PEEK-CHAR for them since the #\newline character is not consumed when it is taken as an "evaluate what you've got" instruction. This means that in the following, > (foo1) HELLO "" ; NIL > the lisp reader "peeks" a #\newline and so attempts to evaluate the forms typed so far. When it comes to evaluate (READ-LINE) it does as prescribed and reads everything from the #\) at the end of "(foo1)" until the next #\newline (the one peeked in this case) and returns it minus the #\newline. This also accounts for the previous example. The VAX Lisp implementation (and presumably KCL) seems to stem from the preconception that the lisp reader should be like a conventional operating system interface, where the usual mode of interaction is to type some text at it and indicate that you want it to act on your text by finishing with a #\newline. Of course, in lisp we have a different idea about when we're finished typing in a form; we close the last #\). But in VAX Lisp, you have to finish with a #\newline regardless. The question mark hangs over the purpose of a #\newline. VAX treats it as a "yes, I'm happy with what I've typed so far, evaluate it for me if it's a complete form", while CLtL doesn't seem to consider the possibility that a completed form should remain unevaluated until an explicit instruction. > This is, in my opinion, a bug in KCL. But it could be argued that > such behavior is allowed by CLtL. > I agree. It's not desirable but I can't find anything in CLtL that proscribes it. It _does_ present portability problems and so should be tied down. -- ____________________________________________________________ , , , Breanndan O Nuallain Department of Computer Science University College Dublin Phone: +353-1-693244 Belfield, Dublin 4 ext 2487 Ireland ------------------------------------------------------------