From: Blair
Subject: My if statement seems to be unreachable
Date: 
Message-ID: <1142224844.092426.145010@e56g2000cwe.googlegroups.com>
I'm working on ACL4.1, and in the process my if statement kept getting
dropped as unreachable.  So I hacked together the following code to try
to copy the basic problem:

(defun equal-p (array)
	   (let ((dim (array-dimensions array))
		 (foo '(z z z)))
	     (format t "~A" dim)
	     (format t "~A" foo)
	     (if (eql (car dim) (cadr dim))
		 '3
		 '(a b)))
	   'done)

and I've tested it with (equal-p #2a((a b) (c d))) and (equal-p #2a((a
b z) (c d v))).

I expect to see:

(2 2)(Z Z Z)3
DONE

for the former and

(2 2)(Z Z Z)(A B)
DONE

for the latter, but I never do.  Instead I see:

(2 2)(Z Z Z)
DONE

every time.  As far as I can tell, IF is being optimized as
unreachable.  But why?  If the two previous format statements are
reachable, what makes the IF statement special that it is no longer
reachable?

Or am I missing something more subtle here?

Thanks for your help.

From: Eric Hanchrow
Subject: Re: My if statement seems to be unreachable
Date: 
Message-ID: <871wx7gcoe.fsf@blarg.net>
>>>>> "Blair" == Blair  <········@gmail.com> writes:

    Blair> I'm working on ACL4.1, and in the process my if statement
    Blair> kept getting dropped as unreachable.  So I hacked together
    Blair> the following code to try to copy the basic problem:

    Blair> (defun equal-p (array) (let ((dim (array-dimensions array))
    Blair> 	   (foo '(z z z))) (format t "~A" dim) (format t "~A"
    Blair> 	   foo) (if (eql (car dim) (cadr dim)) '3 '(a b)))
    Blair> 	   'done)

    Blair> and I've tested it with (equal-p #2a((a b) (c d))) and
    Blair> (equal-p #2a((a b z) (c d v))).

    Blair> I expect to see:

    Blair> (2 2)(Z Z Z)3 DONE

    Blair> for the former and

    Blair> (2 2)(Z Z Z)(A B) DONE

    Blair> for the latter, but I never do.  Instead I see:

    Blair> (2 2)(Z Z Z) DONE

    Blair> every time.  As far as I can tell, IF is being optimized as
    Blair> unreachable.  But why?  If the two previous format
    Blair> statements are reachable, what makes the IF statement
    Blair> special that it is no longer reachable?

    Blair> Or am I missing something more subtle here?

I imagine you've forgotten to call format on the 3.  Since you
haven't, it won't get printed.  The only reason the 'DONE gets printed
is that it's the returned value from the expression.

Change the "if" statement to look like this

    (if (eql (car dim) (cadr dim))
                     (format t "~A" '3)
                     (format t "~A" '(a b)))

and I think you'll get what you want.

-- 
I'm a libertarian with a fascist heart.
        -- Jim Blandy
From: Blair
Subject: Re: My if statement seems to be unreachable
Date: 
Message-ID: <1142311326.049618.231750@i40g2000cwc.googlegroups.com>
That just goes to show that my mock-up was a good idea, but poorly
executed.

Here's the code I'm working on for ACL 4.1:

(defun quarter-turn (array)
  (let ((dim (array-dimensions array))
	(arr '()))
    (if (eql (car dim) (cadr dim))
	(progn
	  (setf arr (make-array '(dim dim)))
	  (do ((x 0 (1+ x)))
	      ((>= x dim))
	    (do ((y 0 (1+ y)))
		((>= y dim))
					; copy from array into arr
	      (setf (aref arr (- dim x) (- dim y))
		    (aref array x y))))
	  arr)
	nil)))

In this case it does actually appear that code I want to run is being
deleted as unreachable by the compiler.  I'm totally flustered.

Thanks for your kind help.
From: Pascal Bourguignon
Subject: Re: My if statement seems to be unreachable
Date: 
Message-ID: <87r755iibt.fsf@thalassa.informatimago.com>
"Blair" <········@gmail.com> writes:
> That just goes to show that my mock-up was a good idea, but poorly
> executed.
>
> Here's the code I'm working on for ACL 4.1:
>
> (defun quarter-turn (array)
>   (let ((dim (array-dimensions array))
> 	(arr '()))
>     (if (eql (car dim) (cadr dim))
> 	(progn
> 	  (setf arr (make-array '(dim dim)))
> 	  (do ((x 0 (1+ x)))
> 	      ((>= x dim))
> 	    (do ((y 0 (1+ y)))
> 		((>= y dim))
> 					; copy from array into arr
> 	      (setf (aref arr (- dim x) (- dim y))
> 		    (aref array x y))))
> 	  arr)
> 	nil)))
>
> In this case it does actually appear that code I want to run is being
> deleted as unreachable by the compiler.  I'm totally flustered.

And if you wrote:

(defun quarter-turn (array)
  (let ((dim (array-dimensions array))
        (arr (quote ())))
    (if (eql (car dim) (cadr dim))
        (progn
          (setf arr (make-array (quote (dim dim))))
          (do ((x 0 (1+ x)))
              ((>= x dim))
            (do ((y 0 (1+ y)))
                ((>= y dim))
                                        ; copy from array into arr
              (setf (aref arr (- dim x) (- dim y))
                    (aref array x y))))
          arr)
        nil)))

would it be clearer?  Do you see the problem now?



I would write it as:

(defun QUARTER-TURN (array)
  (let ((dims (array-dimsensions array)))
    (assert (= 2 (length dims)))
    (when (eql (first dims) (second dims))
      (loop with turned = (make-array dims)
         for x below (first dims)
         do (loop for y below (second dims)
               do (setf (aref turned (mystery-function-1 x y dims)
                                     (mystery-function-2 x y dims))
                        (aref array x y)))
         finally (return turned)))))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we. -- Georges W. Bush
From: Geoffrey Summerhayes
Subject: Re: My if statement seems to be unreachable
Date: 
Message-ID: <x2ERf.7159$ng.299242@news20.bellglobal.com>
"Pascal Bourguignon" <······@informatimago.com> wrote in message 
···················@thalassa.informatimago.com...
>
> I would write it as:
>
> (defun QUARTER-TURN (array)
>  (let ((dims (array-dimsensions array)))
>    (assert (= 2 (length dims)))
>    (when (eql (first dims) (second dims))
>      (loop with turned = (make-array dims)
>         for x below (first dims)
>         do (loop for y below (second dims)
>               do (setf (aref turned (mystery-function-1 x y dims)
>                                     (mystery-function-2 x y dims))
>                        (aref array x y)))
>         finally (return turned)))))
>

I don't really see why the OP insists on a square
array at this level so for me it would be:

(defun QUARTER-TURN (array)
  (assert (= 2 (array-rank array)))
  (let ((dims (array-dimensions array))
         (turned (make-array (reverse (array-dimensions array)))))
     (dotimes (x (first dims) result)
         (dotimes (y (second dims))
           (setf (aref turned (mystery-function-3 x y dims)
                              (mystery-function-4 x y dims))
                 (aref array x y))))))

---
Geoff 
From: David Sletten
Subject: Re: My if statement seems to be unreachable
Date: 
Message-ID: <woGRf.287$%d.209@tornado.socal.rr.com>
Blair wrote:
> That just goes to show that my mock-up was a good idea, but poorly
> executed.
> 
> Here's the code I'm working on for ACL 4.1:
> 
> (defun quarter-turn (array)
>   (let ((dim (array-dimensions array))
> 	(arr '()))
>     (if (eql (car dim) (cadr dim))
> 	(progn
> 	  (setf arr (make-array '(dim dim)))
> 	  (do ((x 0 (1+ x)))
> 	      ((>= x dim))
> 	    (do ((y 0 (1+ y)))
> 		((>= y dim))
> 					; copy from array into arr
> 	      (setf (aref arr (- dim x) (- dim y))
> 		    (aref array x y))))
> 	  arr)
> 	nil)))
> 
> In this case it does actually appear that code I want to run is being
> deleted as unreachable by the compiler.  I'm totally flustered.
> 
> Thanks for your kind help.
> 

Dude, this function is all kinds of messed up...

First, the fact that you're assigning a dummy value to ARR is a warning 
sign that you've established too wide a scope for it.

Second, do you understand what '(dim dim) evaluates to? The QUOTE 
prevents the variable DIM from being evaluated, so you wind up with a 
list of 2 symbols not 2 numbers. This won't suffice to specify the 
dimensions for MAKE-ARRAY.

Third, you create the variable DIM and recognize that it's a list. You 
use CAR and CADR on it after all. Yet then you start treating it as a 
number, comparing it with >= and trying to subtract with it...

Fourth, your indexing is off. Assuming that DIM actually referred to the 
first dimension of the array, then on the first iteration of your loops 
when X = 0 and Y = 0 you would be assigning to (aref arr dim dim), which 
is an invalid element.

Finally, it simply doesn't do what it's supposed to do. Assuming all of 
the other problems were fixed, you would transform #2A((a b) (c d)) into 
#2A((d c) (b a)) rather than #2A((c a) (d b)) as Graham specifies.

Here is a fixed version:
(defun quarter-turn (array)
   (let ((dim (array-dimensions array)))
     (if (= (first dim) (second dim))
         (let ((arr (make-array dim))
               (n (first dim)))
           (do ((x 0 (1+ x)))
               ((= x n))
             (do ((y 0 (1+ y)))
                 ((= y n))
               (setf (aref arr x y)
                     (aref array (- n y 1) x))))
           arr)
         nil)))

And for comparison, here's a simpler way of doing it:
(defun quarter-turn (a)
   (let ((dim (array-dimensions a)))
     (assert (= (first dim) (second dim))
             (a)                          ;This doesn't update DIM 

             "Array is not square.")
     (let ((b (make-array dim))
           (n (first dim)))
       (dotimes (i n b)
         (dotimes (j n)
           (setf (aref b i j) (aref a (- n j 1) i)))) )))

Both of these produce:
(quarter-turn #2A((a b) (c d))) =>
#2A((C A) (D B))

(quarter-turn #2A((a b c d) (e f g h) (i j k l) (m n o p))) =>
#2A((M I E A) (N J F B) (O K G C) (P L H D))


Aloha,
David Sletten
From: Blair
Subject: Re: My if statement seems to be unreachable
Date: 
Message-ID: <1142398587.177591.198110@j52g2000cwj.googlegroups.com>
Pascal:
> would it be clearer?  Do you see the problem now?

David:
> Second, do you understand what '(dim dim) evaluates to?

Yes, and I didn't catch it when I wrote the code.  I saw it this
morning when I compared what I wrote with what Pascal did to make it
clearer, and felt silly.  Of course it wouldn't work.

David:
> Third, you create the variable DIM and recognize that it's a list. You use CAR and
> CADR on it after all. Yet then you start treating it as a number, comparing it with >=
> and trying to subtract with it...

I'll risk looking entirely stupid, and admit that I was just testing
the code in question, and it wasn't intended as a final solution.  What
I was looking for was how I screwed up the IF, which has been made
sufficiently clear.  What you see was the effort of penciling out the
code during the course of any free time I could find.  Unfortunately,
I'm very much lacking in computer time as of late.  I knew at the time
of writing that I was being fast and loose with DIM.  Sorry I didn't
make that clear.

David:
> Fourth, your indexing is off.
...
> Finally, it simply doesn't do what it's supposed to do.

Yes.  Again, I wasn't to the point of this actually working.  I wasn't
trying to post a finished product.  I'll just come right out and admit
that I was in mid-stream trying to incrementally develop and test my
code in Lisp.  At least, that's what I figure it's good at.
Unfortunately some of what I had was a bit of a brain dump.  I just
wanted to know why my IF was being skipped, so I could go on with
incrementally massaging everything out; I wasn't really looking for a
solution.  I'm more interested in figuring these problems out, than
seeing someone else's solution.  Next time I'll attempt to make that a
little clearer.

But I do appreciate your help.  Your code is fairly instructive and
I'll probably print out and read what's been posted on here to get a
better idea about Lisp style.

Thanks,
Blair
From: David Sletten
Subject: Re: My if statement seems to be unreachable
Date: 
Message-ID: <pxNRf.708$WK1.700@tornado.socal.rr.com>
Blair wrote:


> 
> 
> I'll risk looking entirely stupid, and admit that I was just testing
> the code in question, and it wasn't intended as a final solution.  What
> I was looking for was how I screwed up the IF, which has been made
> sufficiently clear.  What you see was the effort of penciling out the
> code during the course of any free time I could find.  Unfortunately,
> I'm very much lacking in computer time as of late.  I knew at the time
> of writing that I was being fast and loose with DIM.  Sorry I didn't
> make that clear.
> 
> David:
> 
>>Fourth, your indexing is off.
> 
> ...
> 
>>Finally, it simply doesn't do what it's supposed to do.
> 
> 
> Yes.  Again, I wasn't to the point of this actually working.  I wasn't
> trying to post a finished product.  I'll just come right out and admit
> that I was in mid-stream trying to incrementally develop and test my
> code in Lisp.  At least, that's what I figure it's good at.
> Unfortunately some of what I had was a bit of a brain dump.  I just
> wanted to know why my IF was being skipped, so I could go on with
> incrementally massaging everything out; I wasn't really looking for a
> solution.  I'm more interested in figuring these problems out, than
> seeing someone else's solution.  Next time I'll attempt to make that a
> little clearer.
> 
> But I do appreciate your help.  Your code is fairly instructive and
> I'll probably print out and read what's been posted on here to get a
> better idea about Lisp style.
> 

I figured that you probably got tangled up with the compiler warnings 
and hadn't had a chance to actually try whether or not your code did the 
job properly. Don't take it too hard.

In all fairness, this is kind of weird feedback from Lisp. I got 
warnings about unreachable code too when I entered your original 
version. To tell you the truth, I'm not completely sure why the compiler 
(SBCL) is reporting that--the code is syntactically correct (and we've 
already discussed the semantic problems :) ).

Don't give up.

Aloha,
David Sletten
From: Christophe Rhodes
Subject: Re: My if statement seems to be unreachable
Date: 
Message-ID: <sqd5go5amu.fsf@cam.ac.uk>
David Sletten <·····@slytobias.com> writes:

> In all fairness, this is kind of weird feedback from Lisp. I got
> warnings about unreachable code too when I entered your original
> version. To tell you the truth, I'm not completely sure why the
> compiler (SBCL) is reporting that--the code is syntactically correct
> (and we've already discussed the semantic problems :) ).

Do you mean the DEFUN QUARTER-TURN version, or the original original
code?  I get no unreachable code notes from SBCL on the very original
version, which simply didn't contain the right number of side-effects.

As for the second block of code, DEFUN QUARTER-TURN, compiling it
under slime gives
<http://www-jcsu.jesus.cam.ac.uk/~csr21/slime-unreachable.png>.
Mousing over the "(>= x dim)" sexp, which is underlined in a bright
colour, says that "Asserted type REAL conflicts with derived type
(VALUES LIST &OPTIONAL)", which means that SBCL has proved to its own
satisfaction that the execution of that form is necessarily a type
error.  Given that, code that strictly comes after the first execution
of that form is unreachable and can be deleted, which explains the
other underlines.

(If you compile this at the terminal instead, you get exactly the same
information, but it's somewhat easier to understand what's going on if
the annotations are made on the code itself.)

Christophe
From: David Sletten
Subject: Re: My if statement seems to be unreachable
Date: 
Message-ID: <NhRRf.960$%d.821@tornado.socal.rr.com>
Christophe Rhodes wrote:


> 
> Do you mean the DEFUN QUARTER-TURN version, or the original original
> code?  I get no unreachable code notes from SBCL on the very original
> version, which simply didn't contain the right number of side-effects.
> 
> As for the second block of code, DEFUN QUARTER-TURN, compiling it
> under slime gives
> <http://www-jcsu.jesus.cam.ac.uk/~csr21/slime-unreachable.png>.
> Mousing over the "(>= x dim)" sexp, which is underlined in a bright
> colour, says that "Asserted type REAL conflicts with derived type
> (VALUES LIST &OPTIONAL)", which means that SBCL has proved to its own
> satisfaction that the execution of that form is necessarily a type
> error.  Given that, code that strictly comes after the first execution
> of that form is unreachable and can be deleted, which explains the
> other underlines.
> 

I meant his original QUARTER-TURN, not his EQUAL-P test.

I figured that the compiler had determined it couldn't do arithmetic 
with a list, but why didn't that result in a compiler error? It seems as 
though the compiler is saying "Oh, you didn't really mean to type that, 
so I'll just take it out."

David Sletten
From: Christophe Rhodes
Subject: Re: My if statement seems to be unreachable
Date: 
Message-ID: <sq8xrc597j.fsf@cam.ac.uk>
David Sletten <·····@slytobias.com> writes:

> I meant his original QUARTER-TURN, not his EQUAL-P test.
>
> I figured that the compiler had determined it couldn't do arithmetic
> with a list, but why didn't that result in a compiler error? It seems
> as though the compiler is saying "Oh, you didn't really mean to type
> that, so I'll just take it out."

It results in a compiler (full) warning
  ; caught WARNING:
  ;   Asserted type REAL conflicts with derived type (VALUES LIST &OPTIONAL).
  ;   See also:
  ;     The SBCL Manual, Node "Handling of Types"
which is sufficiently serious to cause COMPILE-FILE (for instance) to
return a failure value.  Also, it doesn't take the erroneous code out;
it takes anything which is strictly dominated by the erroneous code
out, because you'll never get there (you'll get an error instead, with
no way of continuing).

Christophe
From: David Sletten
Subject: Re: My if statement seems to be unreachable
Date: 
Message-ID: <oX6Rf.15110$e1.12733@tornado.socal.rr.com>
Blair wrote:

> I'm working on ACL4.1, and in the process my if statement kept getting
> dropped as unreachable.  So I hacked together the following code to try
> to copy the basic problem:
> 
> (defun equal-p (array)
> 	   (let ((dim (array-dimensions array))
> 		 (foo '(z z z)))
> 	     (format t "~A" dim)
> 	     (format t "~A" foo)
> 	     (if (eql (car dim) (cadr dim))
> 		 '3
> 		 '(a b)))
> 	   'done)
> 
> and I've tested it with (equal-p #2a((a b) (c d))) and (equal-p #2a((a
> b z) (c d v))).
> 
> I expect to see:
> 
> (2 2)(Z Z Z)3
> DONE
> 
> for the former and
> 
> (2 2)(Z Z Z)(A B)
> DONE
> 
> for the latter, but I never do.  Instead I see:
> 
> (2 2)(Z Z Z)
> DONE
> 
> every time.  As far as I can tell, IF is being optimized as
> unreachable.  But why?  If the two previous format statements are
> reachable, what makes the IF statement special that it is no longer
> reachable?
> 
> Or am I missing something more subtle here?
> 
> Thanks for your help.
> 

The value returned by a function is the value of the last form 
evaluated. Here this is simply the symbol DONE. Thus your function 
always returns DONE. The 2 FORMAT expressions produce a side effect 
(printing something to your terminal). The value of the IF expression, 
however, produces no side effect and its value is discarded. Don't be 
confused by the output of your function and its return value.

This will do what you expect:
(defun equal-p (array)
   (let ((dim (array-dimensions array))
         (foo '(z z z)))
     (format t "~A" dim)
     (format t "~A" foo)
     (if (eql (car dim) (cadr dim))
         (print 3)
         (print '(a b))))
   'done)

Aloha,
David Sletten