2010-06-28 3 views
6

Я решил изучить LISP сегодня и немного поиграл с ней. Я написал простую детскую функцию только для того, чтобы проверить свое понимание, и теперь понимаю, что мое понимание не понимает так сильно, как я понял это, чтобы понять. : DПростая функция LISP не работает

В любом случае, вот эта функция. Идея состоит в том, что когда она называется, например, (esexp base x), он должен вернуть базу значений x. Так (esexp 3 4) = 3^4 = 81.

(я использую реализацию CMU в Common Lisp, если это имеет значение.)

(defun esexp (base x) 
    (if (= x 0) 
     1 
     (if (< x 0) 
      (/ esexp (base (+ x 1)) base) 
      (* esexp (base (+ x 1)) base)))) 

Это не работает. Я получаю ошибки, которые выглядят (Предупреждение: эта переменная не определена: SLBEXP) и (Ошибка в KERNEL :: UNBOUND-SYMBOL-ERROR-HANDLER: переменная SLBEXP не связана). Что я делаю не так? И будет ли лучше (или более LISP-ish) писать эту функцию?

ETA

Исправленный код:

(defun esexp (base x) 
    (if (= x 0) 
     1 
     (if (< x 0) 
      (/ (esexp base (+ x 1)) base) 
      (* (esexp base (- x 1)) base)))) 

ответ

11

esexp(base (+ x 1))

должен быть

(esexp base (+ x 1))

esexp функция так же, как +. Синтаксис для вызова функции:

(function-name arg1 arg2 ...) 
+0

Ah duh. Благодарю. – Asker

0

Просто примечание о коде. Я считаю, что это должно быть

(defun esexp (base x) 
     (if (= x 0) 
       1 
       (if (< x 0) 
         (/ (esexp(base (+ x 1)) base)) 
         (* (esexp(base (- x 1)) base)))) 

В противном случае функция никогда не прекратится. (У вас (* (esexp(base (+ x 1)) base)))))

+0

Кроме того, спасибо. Это была ошибка в транскрипции. – Asker

5

Техническое описание ошибки: компилятор был разборе код:

(/ esexp(base (+ x 1)) base) 

как это:

(/ esexp (base (+ x 1)) base) 

, который говорит:

  • первый , добавить 1 к параметру x
  • , затем вызовите функцию под названием base с результатом выше.
  • разделите значение переменной по результату выше. esexp.
  • затем разделите этот результат на параметр base. (Оператор деления в Common Lisp может принимать более двух аргументов.)

Вы видите трюк? Когда слово появляется как первый элемент в s-выражении (и это s-выражение не цитируется), оно обычно рассматривается как имя функции, которую вы хотите вызвать. В противном случае это рассматривается как имя переменной, значение которой вы хотите получить.Кроме того, в Common Lisp символ esexp может быть привязан как к функции , так и к переменной переменной; контекст или специальные выражения, такие как #'esexp (что означает функцию), используются для определения того, что вы имеете в виду.

Компилятор говорил вам, что, хотя esexp был привязан к функции с defun заявления, он еще не был связан с переменной значения , и, следовательно, не может быть использован как таковые. Следовательно, ошибка.