1

I just started learning LISP today just for the heck of it, so I am completely new to it. I do have experience in other languages though. I tried to write a function that returns a list exactly as is, except without the last element.

While I intend to rewrite this function anyway since I'm sure there's a simpler way of doing it, my version produced some very unusual output. For the record, I'm using the CLISP environment.

(defun my-butlast (L)
    (if (null (rest L))
      nil
      (if (eq nil (my-butlast (rest L)))
         (first L)
         (cons (first L) (my-butlast (rest L)))
      )
    )
)

(my-butlast '(1 2 3 4 5))

This produced the output (1 2 3 . 4)

And so my question is, where did the point come from?

Also, if I try to run (length (my-butlast '(1 2 3 4))) I get a mystifying error: A proper list must not end with 4. What does that mean?

Charles
  • 50,943
  • 13
  • 104
  • 142
  • You don't need the second if. Change the alternative to the second if alternative since (list x) is the same as (cons x '()) – Sylwester Aug 15 '13 at 07:37
  • 1
    Please spend a few minutes learning [how to format Lisp code](http://dept-info.labri.u-bordeaux.fr/~idurand/enseignement/PFS/Common/Strandh-Tutorial/indentation.html). – danlei Aug 18 '13 at 10:37

2 Answers2

6

. is used in the representation of a cons whose cdr is not NIL. E.g.

(cons 1 2)

is displayed as

(1 . 2)

Consider what happens in your function if you do

(my-butlast '(1 2))

The test (eq nil (my-butlast (rest L)) will be true, so it returns (first L). Notice that this is just the number 1, not a list containing 1. You need to change to:

(if (eq nil (my-butlast (rest L)))
    (list (first L))
    (cons (first L) (my-butlast (rest L)))
)

Incidentally, it's more idiomatic to write (null (my-butlast (rest L))).

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • There's a bit more detail about printed representation of lists and proper versus improper lists in [my answer to a distinct, but related question](http://stackoverflow.com/a/16379759/1281433). – Joshua Taylor Aug 15 '13 at 11:40
2

Try doing I believe for your base case (it's been a while since I wrote lisp):

(list (first L))

(first L) will not return a list and cons of one element to another will create the structure you are looking at. Essentially your linked list is ending in [3|4] instead of [3|->] [4|0] with my lame ascii box diagrams.

Daniel Williams
  • 8,673
  • 4
  • 36
  • 47