From: ········@pobox.com
Subject: (or T <error>)
Date: 
Message-ID: <1139005581.504106.266030@f14g2000cwb.googlegroups.com>
I'm just an occasional Lisp hobbyist, returning oafter a few years. I
decided to go through the exercises in Graham's ANSI Common Lisp as a
refresher. In the first set, there is

"What could occur in the place of x in . . . (x 13 (/ 1 0))?

Since Lisp has lazy evaluation for OR, I figured that would work, no
problem. But Corman is giving me

;;; An error occurred in function /:
;;; Error: Divide by zero error: 1 / 0
;;; Entering Corman Lisp debug loop.

I checked the hyperspec, and indeed it says that evaluation stops as
soon as one form evaluates as true. So why should the error ever get in
the way?

From: ·······@gmail.com
Subject: Re: (or T <error>)
Date: 
Message-ID: <1139007973.508012.312560@z14g2000cwz.googlegroups.com>
OR works in CLISP, LispWorks, and is a correct answer.  I don't know
why you're running into the error.  Perhaps spacing error?

CL-USER> (or 13 (/ 1 0))
13
From: ········@pobox.com
Subject: Re: (or T <error>)
Date: 
Message-ID: <1139008219.392341.107450@g44g2000cwa.googlegroups.com>
Copeid and pasted straight from Corman:

(or 13 (/ 1 0))
;;; An error occurred in function /:
;;; Error: Divide by zero error: 1 / 0
;;; Entering Corman Lisp debug loop.
;;; Use :C followed by an option to exit. Type :HELP for help.
;;; Restart options:
;;; 1   Abort to top level.
From: Kaz Kylheku
Subject: Re: (or T <error>)
Date: 
Message-ID: <1139012223.629826.256730@z14g2000cwz.googlegroups.com>
········@pobox.com wrote:
> Copeid and pasted straight from Corman:
>
> (or 13 (/ 1 0))
> ;;; An error occurred in function /:
> ;;; Error: Divide by zero error: 1 / 0
> ;;; Entering Corman Lisp debug loop.
> ;;; Use :C followed by an option to exit. Type :HELP for help.
> ;;; Restart options:

Too bad there isn't a restart that substitutes a value and keeps going.
:)

> ;;; 1   Abort to top level.

As you probably know, Corman Lisp compiles everything, including
expressions you evaluate interactively.

This does look like a problem with over-zealous constant-folding in the
compiler. That is, the compiler is looking for constant expressions to
reduce, without regard for the context in which they occur. This is
okay as long as the expressions are well-defined. But if they have a
problem like division by zero, it blows up.

If you put it in a LAMBDA, does it happen right away? Or do you have to
FUNCALL the resulting function? Try this:

  (lambda () (or 13 (/ 1 0)))

If that blows up right away, then the division by zero is indeed
actually happening in the compiler itself!

As a workaround, just don't write code like that. :)  If it occurs in
code that is generated and is hard to avoid, see whether defining your
own OR macro solves the problem. It could if the problem is a bug in
the compiler's handling of the OR special form rather than a general
problem with constant expressions.

If you are working in your own package, you can shadow the OR from the
CL package with your own.

Even if it's a problem with constant folding, your OR macro could take
care of that.

The function CONSTANTP checks whether a form is a constant expression.
Your OR macro could do its own constant folding, so that

  (OR 13 (/ 1 0))

will actually macro-expand to 13. The compiler will just see that 13
and not blow up on any division. Here is a macro that tries to reduce
any initial sequence of constant expressions at macro-expansion time.
Anything that evaluates to NIL is simply eaten. The first constant
expression that evaluates to non-NIL becomes the replacement for the
entire OR. If no true constant expression is encountered in the first
initial sequence of constant expressions, then the macroexpansion is
the standard Common Lisp OR applied to the remaining arguments.

(defpackage :my-package
  (:use :cl)
  (:export :or)
  (:shadow :or))

(in-package :my-package)

(defmacro or (&rest args)
  (cond
    ((null args) t)
    ((constantp (first args))
     (let ((val (eval (first args))))
       (if val val `(or ,@(rest args)))))
    (t `(cl::or ,@args))))
From: ········@pobox.com
Subject: Re: (or T <error>)
Date: 
Message-ID: <1139013533.941434.143510@o13g2000cwo.googlegroups.com>
(lambda () (or 13 (/ 1 0)))
;;; An error occurred in function /:
;;; Error: Divide by zero error: 1 / 0

Yep, it's the compiler.

Fortuantely (or not) I don't actually ahve any specific task in mind.
I'm home with the flu and picking up my old copy of ANSI Common Lisp
seemed like a way to make the hours go by faster.
From: Stu Glaser
Subject: Re: (or T <error>)
Date: 
Message-ID: <ds0m69$9lf$1@newsreader.wustl.edu>
Both clisp and sbcl give an answer of 13 (without any error).

Regards,
-Stu

> Since Lisp has lazy evaluation for OR, I figured that would work, no
> problem. But Corman is giving me
> 
> ;;; An error occurred in function /:
> ;;; Error: Divide by zero error: 1 / 0
> ;;; Entering Corman Lisp debug loop.
From: Kaz Kylheku
Subject: Re: (or T <error>)
Date: 
Message-ID: <1139012966.203767.6460@g14g2000cwa.googlegroups.com>
Stu Glaser wrote:
> Both clisp and sbcl give an answer of 13 (without any error).

But did you try compiling?

foo:~$ clisp -q

[1]> (lambda () (or t (/ 1 0)))
#<CLOSURE :LAMBDA NIL (OR T (/ 1 0))>
[2]> (compile nil (lambda () (or t (/ 1 0))))

*** - division by zero
Break 1 [3]> :a

[4]> (lisp-implementation-type)
"CLISP"
[5]> (lisp-implementation-version)
"2.33.2 (2004-06-02) (built on foo [10.0.0.1])"
From: Pascal Bourguignon
Subject: Re: (or T <error>)
Date: 
Message-ID: <87u0bf9a91.fsf@thalassa.informatimago.com>
"Kaz Kylheku" <········@gmail.com> writes:

> Stu Glaser wrote:
>> Both clisp and sbcl give an answer of 13 (without any error).
>
> But did you try compiling?
>
> foo:~$ clisp -q
>
> [1]> (lambda () (or t (/ 1 0)))
> #<CLOSURE :LAMBDA NIL (OR T (/ 1 0))>
> [2]> (compile nil (lambda () (or t (/ 1 0))))
>
> *** - division by zero
> Break 1 [3]> :a
>
> [4]> (lisp-implementation-type)
> "CLISP"
> [5]> (lisp-implementation-version)
> "2.33.2 (2004-06-02) (built on foo [10.0.0.1])"

In 2.38 we only get a warning:

[146]> (lambda () (or t (/ 1 0)))
#<FUNCTION :LAMBDA NIL (OR T (/ 1 0))>
[147]> (compile nil (lambda () (or t (/ 1 0))))
WARNING :
Run time error expected: division by zero

#<COMPILED-FUNCTION NIL> ;
1 ;
1
[148]> (funcall *)
T
[149]> 

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

HEALTH WARNING: Care should be taken when lifting this product,
since its mass, and thus its weight, is dependent on its velocity
relative to the user.
From: Eric Daniel
Subject: Re: (or T <error>)
Date: 
Message-ID: <7KSdne-c26eHhnneRVn-tQ@newedgenetworks.com>
In article <··············@thalassa.informatimago.com>, Pascal Bourguignon wrote:
>  In 2.38 we only get a warning:
>  
>  [146]> (lambda () (or t (/ 1 0)))
>  #<FUNCTION :LAMBDA NIL (OR T (/ 1 0))>
>  [147]> (compile nil (lambda () (or t (/ 1 0))))
>  WARNING :
>  Run time error expected: division by zero
>  
>  #<COMPILED-FUNCTION NIL> ;
>  1 ;
>  1
>  [148]> (funcall *)
>  T
>  [149]> 
>  

In CMUCL (18e) we get useful messages as well:

(compile nil (lambda() (or t (/ 1 0))))
; Compiling LAMBDA NIL: 

; In: LAMBDA NIL

;   (/ 1 0)
; Note: Deleting unreachable code.
; 
; Compiling Top-Level Form: 

; Compilation unit finished.
;   1 note




(compile nil (lambda() (/ 1 0)))
; Compiling LAMBDA NIL: 

; In: LAMBDA NIL

;   (/ 1 0)
; Warning: Lisp error during constant folding:
; Arithmetic error DIVISION-BY-ZERO signalled.
; Operation was KERNEL::DIVISION, operands (1 0).
; 
; Compiling Top-Level Form: 

; Compilation unit finished.
;   1 warning

-- 
Eric Daniel
From: Cameron MacKinnon
Subject: Re: (or T <error>)
Date: 
Message-ID: <43e3db92$0$15795$14726298@news.sunsite.dk>
········@pobox.com wrote:

(or 13 (/ 1 0))

> 
> Since Lisp has lazy evaluation for OR, I figured that would work, no
> problem. But Corman is giving me
> 
> ;;; An error occurred in function /:
> ;;; Error: Divide by zero error: 1 / 0
> ;;; Entering Corman Lisp debug loop.
> 
> I checked the hyperspec, and indeed it says that evaluation stops as
> soon as one form evaluates as true. So why should the error ever get in
> the way?

It's possibly a compiler bug related to optimization. The compiler sees 
/ with two constant terms and attempts to precompute the result. Rather 
than computing the correct optimized result (i.e. (error "Divide by zero 
error: 1 / 0") to be executed at runtime, er, eliminated as part of a 
later optimization), the compiler bombs. That's just my guess. I 
discovered an identical bug in a C compiler once (I was on the QA team) 
and had a merry argument with the developers as to whether ANSI allowed 
the behaviour you describe.

Interpreted CMUCL gets the above right, and the compiler returns:
;   (/ 1 0)
; Note: Deleting unreachable code.
From: David Sletten
Subject: Re: (or T <error>)
Date: 
Message-ID: <IlREf.5008$Jg.1126@tornado.socal.rr.com>
········@pobox.com wrote:

> I'm just an occasional Lisp hobbyist, returning oafter a few years. I
> decided to go through the exercises in Graham's ANSI Common Lisp as a
> refresher. In the first set, there is
> 
> "What could occur in the place of x in . . . (x 13 (/ 1 0))?
> 
> Since Lisp has lazy evaluation for OR, I figured that would work, no
> problem. But Corman is giving me
> 
> ;;; An error occurred in function /:
> ;;; Error: Divide by zero error: 1 / 0
> ;;; Entering Corman Lisp debug loop.
> 
> I checked the hyperspec, and indeed it says that evaluation stops as
> soon as one form evaluates as true. So why should the error ever get in
> the way?
> 

The macro OR should indeed behave as you expect. The number 13 is a 
non-nil value, which counts as true. I don't know what the problem is 
with Corman Lisp.

SBCL automatically compiles everything, so I get the following result:
* (or 13 (/ 1 0))
; in: LAMBDA NIL
;     (/ 1 0)
;
; note: deleting unreachable code
;
; compilation unit finished
;   printed 1 note

13

But note that the compiler is not trying to execute the division by 
zero, it's removed unevaluated.

Have you tried (and nil (/ 1 0))?

Aloha,
David Sletten
From: ········@pobox.com
Subject: Re: (or T <error>)
Date: 
Message-ID: <1139008270.707925.113680@o13g2000cwo.googlegroups.com>
Same error:

(and nil (/ 1 0))
;;; An error occurred in function /:
;;; Error: Divide by zero error: 1 / 0
;;; Entering Corman Lisp debug loop.
;;; Use :C followed by an option to exit. Type :HELP for help.
;;; Restart options:
;;; 1   Abort to top level.
From: Roger Corman
Subject: Re: (or T <error>)
Date: 
Message-ID: <4occv19tup51r5ug2pu15rjisatc7k81hu@4ax.com>
Kaz, and others, pretty much nailed this as a compiler issue, which it
is. There is also a simple workaround. Here is a post I made in the
Corman Lisp discussion forums:

Please don't start patching Corman Lisp for this. It works correctly.
Here's the issue. (I am pretty sure we have discussed this before but
I haven't bothered searching for it).

What you are seeing is a compiler-detected error, not a run-time
error. If you execute:

(setf x 0)
(or 13 (/ 1 x))

You will see that OR works as expected.

However, when you enter:

(or 13 (/ 1 0))

this is clearly an erroneous expression. Yes, OR is supposed to not
evaluate the the second expression if the first is true, but the
second is clearly an erroneous expresion and I will argue should never
occur in your code. So the compiler has built-in optimizations where
it tries to determine which arithmetic expressions are constant, and
evaluate them at compile time. If it was smarter it would figure out
that the whole expression is constant (13) but it isn't that smart. It
does not try to optimize away the conditional (OR), but does attempt
to optimize away the division of constants. This generates the error.
Note that just defining a function with this expression generates the
compile-time error:

(defun foo () (or 13 (/ 1 0)))
;;; same error

If you don't like this behavior you can prevent that optimization by:
(setf ccl::*compiler-fold-constants* nil)

This will cause your system to perform like other Lisps in this case,
but at some potential loss of performance. Take your pick.

I guess the fix for this would be to modify the constant-folding code
to catch errors, and, if it gets one, skip the optimization in that
case. This defers it to run time and allows normal run-time exception
handling to be used.

Roger Corman



On 3 Feb 2006 14:26:21 -0800, ········@pobox.com wrote:

>I'm just an occasional Lisp hobbyist, returning oafter a few years. I
>decided to go through the exercises in Graham's ANSI Common Lisp as a
>refresher. In the first set, there is
>
>"What could occur in the place of x in . . . (x 13 (/ 1 0))?
>
>Since Lisp has lazy evaluation for OR, I figured that would work, no
>problem. But Corman is giving me
>
>;;; An error occurred in function /:
>;;; Error: Divide by zero error: 1 / 0
>;;; Entering Corman Lisp debug loop.
>
>I checked the hyperspec, and indeed it says that evaluation stops as
>soon as one form evaluates as true. So why should the error ever get in
>the way?
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: (or T <error>)
Date: 
Message-ID: <87ek21lm5p.fsf@qrnik.zagroda>
Roger Corman <·····@corman.net> writes:

> What you are seeing is a compiler-detected error, not a run-time
> error.

It might be a warning. It may not be an error because the code is
valid.

> but the second is clearly an erroneous expresion and I will argue
> should never occur in your code.

I disagree. It might have been produced by a macro.

> If you don't like this behavior you can prevent that optimization by:
> (setf ccl::*compiler-fold-constants* nil)
>
> This will cause your system to perform like other Lisps in this case,
> but at some potential loss of performance. Take your pick.

An optimization should not change the meaning of the code, unless the
original meaning was underspecified to begin with. Constant folding
should be performed, but it should be careful to not fail in cases
like this, but either leave code which will always signal a condition
when executed, or leave the original division.

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: Pascal Bourguignon
Subject: Re: (or T <error>)
Date: 
Message-ID: <87u0axad75.fsf@thalassa.informatimago.com>
Roger Corman <·····@corman.net> writes:

> Kaz, and others, pretty much nailed this as a compiler issue, which it
> is. There is also a simple workaround. Here is a post I made in the
> Corman Lisp discussion forums:
>
> Please don't start patching Corman Lisp for this. It works correctly.
> Here's the issue. (I am pretty sure we have discussed this before but
> I haven't bothered searching for it).
>
> What you are seeing is a compiler-detected error, not a run-time
> error. If you execute:
>
> (setf x 0)
> (or 13 (/ 1 x))
>
> You will see that OR works as expected.
>
> However, when you enter:
>
> (or 13 (/ 1 0))
>
> this is clearly an erroneous expression. Yes, OR is supposed to not
> evaluate the the second expression if the first is true, but the
> second is clearly an erroneous expresion and I will argue should never
> occur in your code. 

This is ludicruous.  It's similar to say:

   (if t (print :ok) (error "Bad"))

should generate an error at compilation time because the else branch
which will never be taken anyway would raise an error at run-time!


> So the compiler has built-in optimizations where
> it tries to determine which arithmetic expressions are constant, and
> evaluate them at compile time. If it was smarter it would figure out
> that the whole expression is constant (13) but it isn't that smart. It
> does not try to optimize away the conditional (OR), but does attempt
> to optimize away the division of constants. This generates the error.

It must not generate such an error.


> Note that just defining a function with this expression generates the
> compile-time error:
>
> (defun foo () (or 13 (/ 1 0)))
> ;;; same error
>
> If you don't like this behavior you can prevent that optimization by:
> (setf ccl::*compiler-fold-constants* nil)

It's rather coarse...


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

COMPONENT EQUIVALENCY NOTICE: The subatomic particles (electrons,
protons, etc.) comprising this product are exactly the same in every
measurable respect as those used in the products of other
manufacturers, and no claim to the contrary may legitimately be
expressed or implied.
From: Roger Corman
Subject: Re: (or T <error>)
Date: 
Message-ID: <28jpv150rfr5q7lelvrklpb47aurr24vi8@4ax.com>
I wasn't trying to deny this was an error (it is), or that I don't
plan to fix it (I do). Rather I was trying to point out that the
problem the original poster inferred was that there was an
order-of-evaluation problem with Corman Lisp, at least with the OR
operator, which there isn't. I think you will agree that it would be a
more serious problem than a compiler optimization error (which is
clearly noticeable when it happens).

Roger
From: Christophe Rhodes
Subject: Re: (or T <error>)
Date: 
Message-ID: <sqr761v90b.fsf@cam.ac.uk>
Roger Corman <·····@corman.net> writes:

> Please don't start patching Corman Lisp for this. It works correctly.
> Here's the issue. (I am pretty sure we have discussed this before but
> I haven't bothered searching for it).

I do not think you can claim that Corman Lisp works correctly
according to the spec in this respect.  It may work to your design.
(That may have been what you meant in the context of your discussion
forum).

> If you don't like this behavior you can prevent that optimization by:
> (setf ccl::*compiler-fold-constants* nil)
>
> This will cause your system to perform like other Lisps in this case,
> but at some potential loss of performance. Take your pick.

I agree with the other respondents to this: this is rather poor.  In
addition, I think your phrasing is ambiguous; the other lisps get this
right, in that the other Lisps both perform constant-folding in the
normal case and also do not throw compile-time errors when folding
constant expressions which are defined to produce run-time errors.

> I guess the fix for this would be to modify the constant-folding code
> to catch errors, and, if it gets one, skip the optimization in that
> case. This defers it to run time and allows normal run-time exception
> handling to be used.

Indeed, this is what I would expect implementations to do.  SBCL's
constant-folding uses the following utility function to call known
pure functions with constant arguments

  (defun careful-call (function args node warn-fun context)
    (values
     (multiple-value-list
      (handler-case (apply function args)
        (error (condition)
          (let ((*compiler-error-context* node))
            (funcall warn-fun "Lisp error during ~A:~%~A" context condition)
            (return-from careful-call (values nil nil))))))
     t))

which produces compiler output of the form

  ; in: LAMBDA NIL
  ;     (/ 1 0)
  ;
  ; caught STYLE-WARNING:
  ;   Lisp error during constant folding:
  ;   arithmetic error DIVISION-BY-ZERO signalled
  ;   Operation was SB-KERNEL::DIVISION, operands (1 0).

(though not on the form (or t (/ 1 0)) itself, because SBCL also
derives that (/ 1 0) is unreachable.)

Christophe
From: Coby Beck
Subject: Re: (or T <error>)
Date: 
Message-ID: <U4vJf.1211$Nr5.434@clgrps13>
"Roger Corman" <·····@corman.net> wrote in message 
·······································@4ax.com...

> I guess the fix for this would be to modify the constant-folding code
> to catch errors, and, if it gets one, skip the optimization in that
> case. This defers it to run time and allows normal run-time exception
> handling to be used.

Hi Roger,

That sounds like the best solution, and maybe not too difficult?

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")