2013-09-05 2 views
0

Я пытаюсь определить свою собственную функцию, чтобы сделать мой hw2 проще, но он не работает. Не могли бы вы взглянуть на него и рассказать мне, что мне не хватает?Моя определенная функция cond не работает должным образом (LISP)

(DEFUN testAL(x) 
     COND ((ATOMP(x)) 'this-is-an-atom) 
      ((LISTP(x)) 'this-is-a-list) 
      (T 'this-is-neither)) 

Я хочу, чтобы эта условная функция принимала вход X и выводила его, если это атом, список или ни один из них. Проблема в том, что когда я ввожу NIL, я получаю сообщение об ошибке: Попытайтесь принять значение несвязанной переменной `COND '.

Домашнее задание 2 состоит из следующего вопроса:

Which of the following are atoms, which lists, which both and witch neither?

a. nil

b. (expt 10 3)

c. (a b)

d. 64

e. T

f. (No place like home)

g. ‘(+ 3 5 6)

+0

Что такое hw2? Как это облегчит ситуацию? –

+0

@ JoshuaTaylor Технически это было бы больше работы, но я пытаюсь выучить язык. Я добавил hw2 к вопросу выше. – rtrigoso

ответ

6

Вашей скобка не в правильных местах. Скобки, если они не указаны, являются началом приложения-функции.

Он начинается с переменной cond, которая не связана. Это не специальная форма (cond (predicate consequent) (predicate2 consequent2)), так как она не начинается с открытой круглой скобки.

С отступом в одиночку я думаю, вы имели в виду, чтобы написать:

(DEFUN testAL (x) 
    (COND ((ATOM x) 'this-is-an-atom) 
      ((LISTP x) 'this-is-a-list) 
      (T 'this-is-neither))) 

(testal 'test) ; ==> THIS-IS-AN-ATOM 
(testal '(a b c)) ; ==> THIS-IS-A-LIST 

я удалил лишние скобки вокруг x начиная (x) средства применить функцию x в то время как x означает переменную x. С x в другом положении, например (+ x 3), тогда + - это функция, которая должна быть применена, и x является одним из своих операндов.

I изменено atomp до atom. Так как atom является одним из первых примитивов, определяемых с самого первого LISP в 50-х годах, он не имеет постфикса p, как и большинство других предикатов.

Edit: Multiple матч

Вы можете просто иметь несколько cond (или if, так как у вас есть только один тест в каждом) и делать побочные эффекты, такие как (print "THIS-IS-AN-ATOM") с момента вашего базового случая никогда не вызовет (ничего не является ни список ни атома в CL). Это, пожалуй, простое решение.

(DEFUN testAL (x) 
    (if (ATOM x) (print 'this-is-an-atom)) 
    (if (LISTP x) (print 'this-is-a-list))) 

(testal '()) ; ==> THIS-IS-A-LIST (but prints both) 

Для более функционального подхода, который я сделал бы это с более высокими функциями порядка сохраняя код проверяемой и поставить печать-функцию, которая делает побочные эффекты. Помните, что это может быть не так легко читать для новичков:

;; a list of pairs of predicate and their desription 
(defparameter *type-predicates-and-description* 
       '((douglasp . this-is-the-answer-to-everything) 
        (floatp . this-is-a-floating-pont-number) 
        (integerp . this-is-an-integer) 
        (numberp . this-is-a-number) 
        (null . this-is-null) 
        (listp . this-is-a-list) 
        (characterp . this-is-a-character) 
        (stringp . this-is-a-string))) 

;; custom made predicate 
(defun douglasp (x) 
    (and (numberp x) (= x 42))) 

;; returns all the types of a particular value 
(defun get-type-info (x) 
    "return a list if types thet describes argument" 
    (flet ((check-type (acc type-pair) 
      "Accumulate description when predicate match" 
      (if (funcall (car type-pair) x) 
       (cons (cdr type-pair) acc) 
       acc))) 
    ;; test x for each type predicate-description   
    (let ((res (reduce #'check-type 
         *type-predicates-and-description* 
         :initial-value '()))) 
     ;; check of empty list (no types matched) 
     (if (null res) 
      (list 'this-is-neither) 
     res)))) 

;; test it 
(get-type-info '()) ; ==> (THIS-IS-A-LIST THIS-IS-NULL) 
(get-type-info 42) ; ==> (THIS-IS-A-NUMBER 
        ;  THIS-IS-AN-INTEGER 
        ;  THIS-IS-THE-ANSWER-TO-EVERYTHING) 
(get-type-info #()) ; ==> (THIS-IS-NEITHER) 

;; Make a function to do side effects 
(defun print-type-info (x) 
    (format t "~{~a~^, ~}." (get-type-info x))) 

(print-type-info '()) ; ==> NIL 
         ; and prints "THIS-IS-A-LIST, THIS-IS-NULL." 
+0

Я вижу, где я ошибся. Он отлично работает с дополнительными скобками. У меня есть следующий вопрос. COND, похоже, работает как оператор switch, который имеет «break» для каждого случая java. Я надеялся, что COND пройдет через каждую строку, независимо от того, будет ли это верно или нет и напечатать каждую строку, которая истинна. Например, если бы я сделал (testal 'NIL), он напечатал бы «this-is-an-atom» и «this-is-a-list», но он остановится при первом T-состоянии. Мой вопрос: ** есть ли способ, чтобы COND сравнивал X с каждым условием, не останавливаясь на первом T, который он находит? ** – rtrigoso

+0

@rtrigoso Я добавил несколько идей к моему ответу, касающемуся нескольких ответов. – Sylwester

+0

Я вижу, поэтому, имея несколько COND, или в этом случае IFs, распечатки не будут пропущены на случай T? Спасибо – rtrigoso