This is a read-only archive of lispforum.com. The forum was locked to new users and posts and is preserved here as static HTML from a database snapshot taken on 2019-09-07.

Is this a bug in LispWorks?

9 posts · 2372 views

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:
 (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:
       (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:
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?

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?

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?

Ramarren wrote:Your code as posted has unbalanced parentheses, so it is hard to tell.
I'll try again below:
(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?

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.
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?

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:
(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?

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:
(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
    (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?

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?

Tip: whenever you have (reduce <function1> (mapcar <function2> <list>) ...) you can replace it with (reduce <function1> <list> :key <function2> ...), avoiding intermediate garbage.