-1

I'm trying to implement the Towers of Hanoi.I'm not printing out anything between my recursive calls yet, but I keep getting an error saying

'('(LIST) 'NIL 'NIL) should be a lambda expression

I've read that the reason this happens is because of a problem with the parenthesis, however I cannot seem to find what my problem is. I think it's happening in the pass-list function when I am trying to call the hanoi function. My code:

(defun pass-list(list)
   (hanoi('('(list)'()'())))
)

(defun hanoi ('('(1) '(2) '(3)))

    (hanoi '('(cdr 1) '(cons(car 1) 2) '(3)))

    (hanoi '('(cons(car 3)1) '(2)'(cdr 3)))
 )
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
KoolAid
  • 299
  • 1
  • 4
  • 13

1 Answers1

2

This code has many syntax problems; there are erroneous quotes all over the place, and it looks like you're trying to use numbers as variables, which will not work. The source of the particular error message that you mentioned comes from

(hanoi('('(list)'()'())))

First, understand that the quotes in 'x and '(a b c) are shorthand for the forms (quote x) and (quote (a b c)), and that (quote anything) is the syntax for getting anything, without anything being evaluated. So '(1 2 3) gives you the list (1 2 3), and '1 gives you 1. quote is just a symbol though, and can be present in other lists, so '('(list)'()'()) is the same as (quote ((quote (list)) (quote ()) (quote ()))) which evaluates to the list ((quote (list)) (quote ()) (quote ())). Since () can also be written nil (or NIL), this last is the same as ('(list) 'NIL 'NIL). In Common Lisp, function calls look like

(function arg1 arg2 ...)

where each argi is a form, and function is either a symbol (e.g., list, hanoi, car) or a list, in which case it must be a lambda expression, e.g., (lambda (x) (+ x x)). So, in your line

(hanoi('('(list)'()'())))

we have a function call. function is hanoi, and arg1 is ('('(list)'()'())). But how will this arg1 be evaluated? Well, it's a list, which means it's a function application. What's the function part? It's

'('(list)'()'())

which is the same as

'('(list 'NIL 'NIL))

But as I just said, the only kind of list that can be function is a lambda expression. This clearly isn't a lambda expression, so you get the error that you're seeing.

I can't be sure, but it looks like you were aiming for something like the following. The line marked with ** is sort of problematic, because you're calling hanoi with some arguments, and when it returns (if it ever returns; it seems to me like you'd recurse forever in this case), you don't do anything with the result. It's ignored, and then you go onto the third line.

(defun pass-list(list)
  (hanoi (list list) '() '()))

(defun hanoi (a b c)
  (hanoi (rest a) (cons (first a) b) c)  ; **
  (hanoi (cons (first c) a) b (rest c)))

If hanoi is supposed to take a single list as an argument, and that list is supposed to contain three lists (I'm not sure why you'd do it that way instead of having hanoi take just three arguments, but that's a different question, I suppose), it's easy enough to modify; just take an argument abc and extract the first, second, and third lists from it, and pass a single list to hanoi on the recursive call:

(defun hanoi (abc)
  (let ((a (first abc))
        (b (second abc))
        (c (third abc)))
    (hanoi (list (rest a) (cons (first a) b) c))
    (hanoi (list (cons (first c) a) b (rest c)))))

I'd actually probably use destructuring-bind here to simplify getting a, b, and c out of abc:

(defun hanoi (abc)
  (destructuring-bind (a b c) abc
    (hanoi (list (rest a) (cons (first a) b) c))
    (hanoi (list (cons (first c) a) b (rest c)))))
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • Hey there. Thank you! And yea I'm trying to make a list, of lists. (So a single list that contains 3 individual lists inside of it). Also, if you read in my original post, you will see that I wrote that I have nothing between the recursive calls YET. I will be putting a print statement there. – KoolAid Nov 11 '13 at 01:42
  • @user2974646 OK, but even so, that first recursive call to `hanoi` doesn't _modify_ anything. In the second call, `a`, `b`, and `c` are exactly what they were before the first recursive call. If that's what you expected, good. I just wanted to make sure. – Joshua Taylor Nov 11 '13 at 02:09
  • I'm really still stuck. Like I said I want a list of lists. So a list, which contains 3 lists inside it. I want the recursive call to replace everything in the first list except for the first item in the list (so I used CDR). I then want the second list to have just the first item in the first list put into it, and then I want the third list to remain the same. – KoolAid Nov 11 '13 at 02:32
  • @user2974646 You mean that `hanoi` should take a list of three lists? If `a`, `b`, and `c` are all lists, just use `(list a b c)`. – Joshua Taylor Nov 11 '13 at 02:51
  • When I try to call on the hanoi function it is saying that hanoi now requires 4 parameters. I'm not sure why though. Is it because I have 3 lists (a b and c) as well as a list around those 3 lists? (i.e. 4 lists total). – KoolAid Nov 11 '13 at 03:01
  • @user2974646 None of the definitions of `hanoi` that _I_ gave take four arguments. `(defun hanoi (a b c) ...)` takes three, and `(defun hanoi (abc) ...)` takes one. What's your new definition? Did you write `(defun hanoi (list a b c) ...)`? I meant that you'd _call_ `hanoi` with `(list a b c)`. E.g., your recursive call could be `(hanoi (list a b c))` (since `hanoi` would just take _one_ argument). The _definition_ of `hanoi` in that case would be `(defun hanoi (abc) ...)`. – Joshua Taylor Nov 11 '13 at 03:04
  • Ohhh okay... I would also need to change the parameters for when I call the hanoi function then to something that would pass it a single list if it was (defun(hanoi(abc) ... ) – KoolAid Nov 11 '13 at 03:25
  • Also, just to clear things up for me. When you say (let ((a (first abc)) etc.. Is that simply equating a to the first portion of abc? – KoolAid Nov 11 '13 at 03:27
  • @user2974646 In general, `(first x)` is the first element of the list `x` (and similarly for `second` and `third`. So, if `abc` is a list of three lists, then `(first abc)` is the first of those lists, `(second abc)` the second, and `(third abc)` the third. “portion” doesn't have much technical meaning to me, but it's correct to say that `(first abc)` is the first _element_ of `abc`. – Joshua Taylor Nov 11 '13 at 04:07
  • I really appreciate all of this help. You were correct in that my recursive call does infact recurse forever, except now I am trying to fix that. I'm pretty sure that the two recursive calls should be (hanoi (a c b) and (hanoi (c b a) – KoolAid Nov 11 '13 at 04:30