I'm developing a Lisp interpreter, and have a question
about the "correct" behavior of COND.
While debugging my COND implementation, I
accidentally typed:
(COND (+ x 1))
My interpreter responded with 1 (the number one).
Corman Lisp responds the same way, but LispWorks
Personal Edition complains that "the symbol X is unbound."
What should Lisp do when it encounters this situation?
Thanks in advance!
- BM
Note that COND is a macro, while IF is a special operator (according to
the CLHS), and COND is typically implemented recursively, using IF.
Here's an implementation I just threw together to make sure I know what
I'm talking about. ;)
(defmacro cond (&optional head &rest tail)
(if head
`(if ,(car head) (progn ,@(cdr head)) (cond ,@tail))
nil))
Ari
Ari Johnson <·····@hotmail.com> writes:
> Note that COND is a macro, while IF is a special operator (according
> to the CLHS), and COND is typically implemented recursively, using
> IF.
What is the distinction between special operator and macro that you
wish to make here? Is there some practical upshot to this
difference? Both macros and special forms can control the evaluation
of their arguments.
I see this in the hyperspec about COND as macro and IF as special
operator, but I have also seen in the newsgroup people refering to
some implementation wiggle room on implementating things as macro or
special form. Could a Lisp be conforming and have COND the special
form and IF as a macro?
> Here's an implementation I just threw together to make sure I know
> what I'm talking about. ;)
>
> (defmacro cond (&optional head &rest tail)
> (if head
> `(if ,(car head) (progn ,@(cdr head)) (cond ,@tail))
> nil))
>
> Ari
--
Johan KULLSTAM <··········@comcast.net> sysengr
Johan Kullstam wrote:
> Ari Johnson <·····@hotmail.com> writes:
>
>
>>Note that COND is a macro, while IF is a special operator (according
>>to the CLHS), and COND is typically implemented recursively, using
>>IF.
>
>
> What is the distinction between special operator and macro that you
> wish to make here? Is there some practical upshot to this
> difference? Both macros and special forms can control the evaluation
> of their arguments.
>
> I see this in the hyperspec about COND as macro and IF as special
> operator, but I have also seen in the newsgroup people refering to
> some implementation wiggle room on implementating things as macro or
> special form. Could a Lisp be conforming and have COND the special
> form and IF as a macro?
I believe so, and I think some do. The key, as I see it, is that you
must be able to implement all of your macros in terms of your special
operators. Try (macroexpand-1 '(if t 1 2)) on a few Lisps until you
find one that returns a COND form.
The upshot to using as few special operators and as many macros as
possible is that the macros are written in the same Lisp you are writing
the interpreter for, whereas the special operators probably are not.
On Mon, May 03, 2004 at 10:38:11AM -0400, Johan Kullstam wrote:
> I see this in the hyperspec about COND as macro and IF as special
> operator, but I have also seen in the newsgroup people refering to
> some implementation wiggle room on implementating things as macro or
> special form. Could a Lisp be conforming and have COND the special
> form and IF as a macro?
``An implementation is free to implement a Common Lisp special operator
as a macro. An implementation is free to implement any macro operator as
a special operator, but only if an equivalent definition of the macro is
also provided.'' -- CLHS 3.1.2.1.2.2
The reason for this is to support code-walkers, which can count on the
expansion of macros and a limited set of special operators to handle
otherwise.
--
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
On Mon, May 03, 2004 at 02:50:46AM +0000, Ludix wrote:
> I'm developing a Lisp interpreter, and have a question
> about the "correct" behavior of COND.
>
> While debugging my COND implementation, I
> accidentally typed:
>
> (COND (+ x 1))
>
> My interpreter responded with 1 (the number one).
>
> Corman Lisp responds the same way, but LispWorks
> Personal Edition complains that "the symbol X is unbound."
>
> What should Lisp do when it encounters this situation?
>
> Thanks in advance!
Consider this: at the top-level, the variable named "+" is probably
bound to some form (the previous one entered), and so that branch of the
COND succeeds unless the form is (). What happens next is that the
value of the variable named "X" is looked up and discarded, and then the
value of "1" is returned. If X is unbound, I think this should signal
an error, however Corman (and your implementation) may be optimizing
this out since it has no effect otherwise.
A Lisp should of course attempt to evaluate the condition-form, and if
it evaluates to a true value then should evaluate the following forms as
if enclosed in a PROGN form. Unbound variables should result in errors
at run-time, and perhaps warnings at compile-time, since if it is not a
lexical variable then it must be declared special somewhere for it to be
valid.
--
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
Matthew Danish <·······@andrew.cmu.edu> writes:
> A Lisp should of course attempt to evaluate the condition-form, and if
> it evaluates to a true value then should evaluate the following forms as
> if enclosed in a PROGN form. Unbound variables should result in errors
> at run-time, and perhaps warnings at compile-time, since if it is not a
> lexical variable then it must be declared special somewhere for it to be
> valid.
The CLHS is quite clear about indicating that portable code should not
rely on the signalling of errors. Optimizations like this one seem
reasonable to me (elision of a side-effect-free form whose result is
discarded). Exceptional situations should not be expected/required. :)
--
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Rahul Jain wrote:
> The CLHS is quite clear about indicating that portable code should not
> rely on the signalling of errors.
There are many situations ('error should be signaled', 'should be prepared
to signal an error') where portable code can count on errors being
signaled in safe code (that is, where the optimize setting SAFETY is 3.)
See CLHS, section 1.4.2.
Paul
Rahul Jain <·····@nyct.net> writes:
> The CLHS is quite clear about indicating that portable code should not
> rely on the signalling of errors.
What? Where does it say that?
Christophe
--
http://www-jcsu.jesus.cam.ac.uk/~csr21/ +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%") (pprint #36rJesusCollegeCambridge)
Christophe Rhodes <·····@cam.ac.uk> wrote in message news:<··············@lambda.dyndns.org>...
> Rahul Jain <·····@nyct.net> writes:
>
> > The CLHS is quite clear about indicating that portable code should not
> > rely on the signalling of errors.
>
> What? Where does it say that?
I don't think it does. I think it has some fairly careful definitions
of where exceptions need to be signaled &c, and where they don't. I
also don't think that this case is anything to do with that, it's to
do with whether side-effect-free forms can be optimised-away at
compile time, even though at run-time they might cause errors or fail
to terminate.
Tim Bradshaw wrote:
> I don't think it does. I think it has some fairly careful definitions
> of where exceptions need to be signaled &c, and where they don't. I
> also don't think that this case is anything to do with that, it's to
> do with whether side-effect-free forms can be optimised-away at
> compile time, even though at run-time they might cause errors or fail
> to terminate.
Causing an error is a side effect, and in this case it's required
in safe code.
Section 3.1.2.1.1, paragraph 4:
An error of type unbound-variable should be signaled if an unbound
variable is referenced.
Paul
··········@tfeb.org (Tim Bradshaw) writes:
> Christophe Rhodes <·····@cam.ac.uk> wrote in message news:<··············@lambda.dyndns.org>...
>> Rahul Jain <·····@nyct.net> writes:
>>
>> > The CLHS is quite clear about indicating that portable code should not
>> > rely on the signalling of errors.
>>
>> What? Where does it say that?
>
> I don't think it does. I think it has some fairly careful definitions
> of where exceptions need to be signaled &c, and where they don't. I
> also don't think that this case is anything to do with that, it's to
> do with whether side-effect-free forms can be optimised-away at
> compile time, even though at run-time they might cause errors or fail
> to terminate.
Failing to terminate is arguably not a side-effect, but I'd like to
hear your reasoning behind the suggestion that signalling an error
isn't one.
Christophe
--
http://www-jcsu.jesus.cam.ac.uk/~csr21/ +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%") (pprint #36rJesusCollegeCambridge)
* Christophe Rhodes wrote:
> Failing to terminate is arguably not a side-effect, but I'd like to
> hear your reasoning behind the suggestion that signalling an error
> isn't one.
I think it is. In fact I almost put in a comment that it was and so
it wasn't legitimate for a compiler to optimise the code away. I think
in *this* case - where the compiler could trivially tell that it was
optimising away something that would signal an error in safe code -
then (with suitable safety settings) it shouldn't do that (and with
unsafe settings it should probably signal a warning if it does do
it).
I think the problem with this kind of argument is that you have to be
careful not to take it too literally. What about a compiler that can
(say) optimise tail-calls. Such an optimisation might transform code
which would cause an error (stack overflow) to code that won't. Is
that legal? I hope so!
--tim
Tim Bradshaw wrote:
> I think the problem with this kind of argument is that you have to be
> careful not to take it too literally. What about a compiler that can
> (say) optimise tail-calls. Such an optimisation might transform code
> which would cause an error (stack overflow) to code that won't. Is
> that legal? I hope so!
Sure -- because the standard does not require that stack overflows
cause the signalling of errors.
Paul
* Paul Dietz wrote:
> Sure -- because the standard does not require that stack overflows
> cause the signalling of errors.
Ok, well think of a case where some transformation *could* prevent
errors being signaled, but where it's not something that's trivially
clear to the compiler (or even clear at all).
--tim
Christophe Rhodes <·····@cam.ac.uk> writes:
> Rahul Jain <·····@nyct.net> writes:
>
>> The CLHS is quite clear about indicating that portable code should not
>> rely on the signalling of errors.
>
> What? Where does it say that?
I can't find it quickly, but I could have sworn there was some entry in
the hyperspec that talked about forms like (progn (error ...)
(end-of-the-world)). :\
--
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Rahul Jain <·····@nyct.net> writes:
[excerpted and paraphrased]
> Optimizations like elision of a side-effect-free form whose result
> is discarded seem reasonable to me.
I agree, but it is a matter of contention. What about this case:
(defun foo ()
(do ((i n (1- i)))
((zerop i) nil))
42)
If N starts out as a negative number, the do loop would never finish,
so 42 would never be returned. If N is positive, it could take an
arbitrary amount of time until N reaches zero.
On the other hand, the code is `observationally equivalent' to
(defun foo ()
42)
because it is impossible to write a program that can tell the
difference between the two. (By `tell the difference' I mean
conditionally test the return value.)
--
~jrm
Corman Lisp expands that expression to:
(IF + (PROGN X 1) NIL)
which will signal an error if x is not bound. I assume when you tried it x
was bound for some reason.
Roger Corman
-----
"Ludix" <····@ludix.com> wrote in message news:<································@news.teranews.com>...
> I'm developing a Lisp interpreter, and have a question
> about the "correct" behavior of COND.
>
> While debugging my COND implementation, I
> accidentally typed:
>
> (COND (+ x 1))
>
> My interpreter responded with 1 (the number one).
>
> Corman Lisp responds the same way, but LispWorks
> Personal Edition complains that "the symbol X is unbound."
>
> What should Lisp do when it encounters this situation?
>
> Thanks in advance!
>
> - BM