Page 1 of 1

Is this a bug in LispWorks?

Posted: Thu Jun 10, 2010 2:01 am
by lispamour
I'm getting started in Lisp, and working through the problems in Lisp: Gentle Introduction to Symbolic Computation. In Chapter 8 p. 217 is the following Exercise 4:

Write MAPUNION, an applicative operator that takes a function and a list as input, applies the function to every element of the list, and computes the union of all the results. Example:

Code: Select all

 (MAPUNION #'CDR '((1 a b c) (2 e c j) (3 f a b c d)))
should return the set
(a b c e j f d).
Here is my solution:

Code: Select all

       (defun mapunion (f l)
               (cond ((null l)                     nil)
                        ((null (mapcar f l)     nil)
                        (t                             (reduce #'union (mapcar f l)))))
Simple right? Well it crashes under Lispworks (Personal Edition 5.1.1 PowerPC) But works fine under Clozure CL64 (Version 1.4-dev (13119 (PPC64)).

The error message I get back from Lispworks is:

Code: Select all

CL-USER 3 > (mapunion #'cdr '((1 a b c) (2 e c j)))

Error: Illegal instruction(4) [code 20EFE1A0] at 20EFEB78
  1 (abort) Return to level 0.
  2 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed,  or :? for other options

CL-USER 4 : 1 > :b
Call to ERROR
Is there something wrong with my code that would cause it to crash under Lispworks but not Clozure?

Re: Is this a bug in LispWorks?

Posted: Thu Jun 10, 2010 5:43 am
by ramarren
Your code as posted has unbalanced parentheses, so it is hard to tell. Also, the second branch is redundant with the first.

Re: Is this a bug in LispWorks?

Posted: Thu Jun 10, 2010 7:54 am
by gugamilare
It might be a bug in Lispworks. Do you have downloaded their latest version? Also, did you check the parenthesis, didn't you make some mistake while copy-and-pasting the code?

Re: Is this a bug in LispWorks?

Posted: Thu Jun 10, 2010 12:05 pm
by lispamour
Ramarren wrote:Your code as posted has unbalanced parentheses, so it is hard to tell.
I'll try again below:

Code: Select all

(defun mapunion (f l)
  (cond ((null l)              nil)
        ((null (mapcar f l))   nil)
        (t                     (reduce #'union (mapcar f l)))))
Also, the second branch is redundant with the first.
How would you re-write it?

Re: Is this a bug in LispWorks?

Posted: Thu Jun 10, 2010 12:10 pm
by lispamour
gugamilare wrote:It might be a bug in Lispworks. Do you have downloaded their latest version? Also, did you check the parenthesis, didn't you make some mistake while copy-and-pasting the code?
This is their latest version.

Code: Select all

LispWorks Personal Edition

Current Version

The current version is LispWorks 5.1.1 Personal Edition. It includes the new features announced here.

Next Version

LispWorks 6.0 Personal Edition will be released during 2010. Check our user group for announcements.
You're right. I left off a parenthesis while copying and pasting. I've corrected it in the previous post.

Re: Is this a bug in LispWorks?

Posted: Thu Jun 10, 2010 12:29 pm
by ramarren
lispamour wrote:How would you re-write it?
MAPCAR will return NIL only if the list is empty, which is already checked by the first branch. Therefore the second branch will never be true, and hence is pointless. In fact unless I'm missing something the entire function could be reduced to just:

Code: Select all

(defun mapunion (f l)
  (reduce #'union (mapcar f l) :initial-value nil))
But there doesn't seem to be anything wrong as such with the code. I have no idea why it would error out on LispWorks. You should look for minimal subcomponent which fails. It is somewhat unlikely there is a bug in such fundamental constructs.

Re: Is this a bug in LispWorks?

Posted: Sun Jun 13, 2010 10:26 pm
by lispamour
Ramarren wrote:
lispamour wrote:How would you re-write it?
MAPCAR will return NIL only if the list is empty, which is already checked by the first branch. Therefore the second branch will never be true, and hence is pointless. In fact unless I'm missing something the entire function could be reduced to just:

Code: Select all

(defun mapunion (f l)
  (reduce #'union (mapcar f l) :initial-value nil))
But there doesn't seem to be anything wrong as such with the code. I have no idea why it would error out on LispWorks. You should look for minimal subcomponent which fails. It is somewhat unlikely there is a bug in such fundamental constructs.
You're quite right about how the extraneous lines in the cond expression are superfluous. To add to the mystery, I noticed that If I were to type my earlier code directly into the LispWorks Listener, and execute the resulting function

Code: Select all

    (MAPUNION #'CDR '((1 a b c) (2 e c j) (3 f a b c d)))
then the evaluation works fine. It is only when I type the (defun MAPUNION ...) definition into an external file, then compile and load the result into LispWorks that I get the above error.

Is it possible that LispWorks is performing some sort of optimization that generates faulty code after compilation and loading, which does not occur if function were defined in the Listener's interpretive environment?

Re: Is this a bug in LispWorks?

Posted: Sun Jun 13, 2010 11:08 pm
by ramarren
lispamour wrote:Is it possible that LispWorks is performing some sort of optimization that generates faulty code after compilation and loading, which does not occur if function were defined in the Listener's interpretive environment?
It seems so. You could try asking on some LispWorks specific mailing list. I guess PPC64 is not a very well supported architecture. Or maybe there is some sort of environment mismatch?

Re: Is this a bug in LispWorks?

Posted: Tue Jun 15, 2010 5:12 pm
by death
Tip: whenever you have (reduce <function1> (mapcar <function2> <list>) ...) you can replace it with (reduce <function1> <list> :key <function2> ...), avoiding intermediate garbage.