Search code examples
lispcommon-lispecl

Lisp: why does this code throw a "function x is undefined" error?


I am trying to create a card guessing game in lisp (ECL). However i get an error.

(defun random-card ()
  (coerce '(                                        
    (char (random 4) "SCDH")
    (char (random 13) "A23456789JQK"))
  'string)
)

(defun repeat (x n)
  (if (zerop n)
    nil
    (cons (x) (repeat x (1- n)))))

(print (repeat #'random-card 3))

The error:

An error occurred during initialization:
The function X is undefined..

Is the undefined function X the parameter of repeat? What am i missing?


Solution

  • Common Lisp is a Lisp-2, which means that functions and variables have different namespaces. That's why you had to write #'random-card rather than just random-card. random-card as an argument looks in the value namespace. #'random-card is a shortcut for (function random-card), which looks up the name in the function namespace (function itself is not a function; it's one of a handful of special operators which are extremely baked into the Common Lisp system).

    So function takes a name in the function namespace and binds it to a value. Now you've got a value called x in your repeat function. x is a variable in the value namespace, and when you write (x), Common Lisp is looking in the function namespace. That is, it's looking for something that was defuned, fleted, or labelsed. To call a function that's stored in a value-level variable, we use funcall.

    (defun repeat (x n)
      (if (zerop n)
        nil
        (cons (funcall x) (repeat x (1- n)))))