Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > LISP > Синтаксические ошибки


Автор: brockel 15.11.2006, 23:27
Код

; aop = associative operations.
(setq действие () )
(setq результат () )
(setq ошибка 'Нормально)

(defun получить(операция список_операций)
    (COND ( (ENDP список_операций)
        (setq действие () )
        (return-from получить)
        
      )
      
      ( (equal (car (car список_операций)) операция)
        (setq действие (cdr (car список_операций)))
        (return-from получить)
      )
    )
    
    (получить операция (cdr список_операций) )
)

(defun инфикс(выражение ассоц)
;    (setq действие (получить (car выражение) (cdr выражение)) )
    
    (получить (car выражение) (cdr выражение))
    
    (COND ( (equal действие ())
        (setq ошибка 'в_списке_операций)
        (return)
      )
    )
    
    (setq результат (CONS результат 'f ) )
    
    (setq операнды (car (cdr выражение)) )
    (COND ( (ENDP (car (cdr (cdr операнды) ) ) )
        (setq ошибка 'в_выражении)
        (return)
      )
    )
    
    (COND ( (ATOM (car операнды))
        (setq результат (CONS результат (car операнды)) )
        (инфикс (car (cdr операнды)) ассоц)
      )
    )
    
    (инфикс (car операнды) ассоц)
    
    (loop
    (COND ( (NOT (ATOM операнды) )
          (инфикс (car операнды) ассоц)
          )
    )
    
    (COND ( (ENDP операнды)
        (setq результат (CONS результат 'u ) )
         (return)
          )
    )
    
    (setq результат (CONS результат (car операнды)) )    
    (setq операнды (cdr операнды))
    )
)


(инфикс '(ДЕЛИ (МНОЖ C A B) (ПЛЮС 3 (МНОЖ  A 2) X Y)) '((ПЛЮС +) (МНОЖ *) (ДЕЛИ /)) )
(princ результат)


Писал без интерпритатора, как написал запустил в интерпретатор он начал ругаться всё что мог, я исправил, щас пишет:
*** - RETURN-FROM: no block named NIL is currently visible
Но я не понимаю что это значит. И если есть явные синтаксические ошибки - пишите, мне это нужно. У меня с синтаксисом лисп слабо. Использую clisp.

Автор: adejneka 16.11.2006, 06:56
Замените RETURN в ИНФИКС на RETURN-FROM.

Не используйте SETQ.  Если нужно вернуть значение из функции - просто верните его (заодно, это позволит использовать TRACE для отладки). Если нужна временная переменная - создайте ее с помощью LET:
Код

(let ((действие (получить ...)))
  (cond ((eq действие nil) ...)
    ...)))

В Common Lisp есть средства обработки исключений. Если возникает отказ, напишите (throw 'в-выражении) или (error "в выражении ~S встретилась неизвестная операция ~S" выражение операция). Поймать их можно с помощью CATCH или HANDLER-CASE.

LOOP - это не сишный for(;;) {...}.
Код

(defun spread (operation operands)
  (if (null (rest operands))
      (first operands)
      (cons (first operands)
            (loop for operand in (rest operands)
                  collect operation
                  collect operand))))

(spread '+ '(a b c))

Автор: brockel 17.11.2006, 00:13
Хорошо, такой вопрос как хорошо склеивать списки, есть например:
(A B C D (F E) )
(L O L)
Хочу получить: (A B C D (F E) L O L) Что то через Cons неполучается..... получается слишком много скобок при повторных вызовах Cons тоесть он создает - Список от списка от списка от списка....

Автор: Void 17.11.2006, 00:20
См. append.

Автор: brockel 17.11.2006, 11:03
окей вроде почти наченает работать=))) Ещё вопрос (приведу код см. комментарии)

Код


(defun получить(операция список_операций)
    (COND ( (null список_операций)
        (return-from получить Nil )
      )
      
      ( (equal (car (car список_операций)) операция)
        ;(princ операция)
        (return-from получить (cdr (car список_операций)) )
      )
    )
    
    (получить операция (cdr список_операций) )
)

(defun инфикс(выражение операции)    
    (COND ( (null (cdr выражение))
        (prin1 "ошибка_в_списке_операций")
        (return-from инфикс Nil)
      )
    )
    
    (setq действие (получить (car выражение) операции) ) ; set action
    
    (COND ( (null действие )
        (prin1 "ошибка_в_списке_операций")
        (return-from инфикс Nil)
      )
    )
    
    (setq подсписок Nil)
    
    (loop    
    (setq операнд (car (cdr выражение)) )
    (print операнд)
    (COND ( (ATOM операнд)
        (setq подсписок (append подсписок (list операнд)) )
          )
          ( (NOT (ATOM операнд))
            (prin1 "[")
            (print действие) ;///////////////      ЗНАЧЕНИЕ НАПРИМЕР /
            (setq подсписок (append подсписок (list (инфикс операнд операции))) )
            (princ действие) ;///////////////      ПОЧЕМУ-ТО ИЗМЕНИЛОСЬ НАПРИМЕР НА *
            (prin1 "]")
          )
    )
        
    (setq выражение (cdr выражение))
    (COND ( (null (cdr выражение))
        (return-from инфикс подсписок)
          )
    )
    
    (setq подсписок (append подсписок действие))
    )
)

(setq результат (инфикс '(ДЕЛИ (МНОЖ C A B (ДЕЛИ 2 3 4)) (ПЛЮС 3 (МНОЖ  A 2) X Y)) '((ПЛЮС +) (МНОЖ *) (ДЕЛИ /))) )
(princ "Start: ")
(prin1 результат)



так вод setq помоему перестанавливает переменную локальную (действие) как это может быть, я непонимаю. Кто-нибудь обяснити в чем моя ошибка?

Автор: adejneka 17.11.2006, 21:04
ДЕЙСТВИЕ - это не локальная переменная, а необъявленная глобальная; SETQ ее, естественно, переустанавливает. Для того, чтобы переменная стала локальной, ее нужно создать как локальную - например, используя LET. Сравните с языком C:

(setq x 1) ... (f x) <=> { x=1;  ... f(x)... } ; глобальная
(let ((x 1)) ... (f x) ... )  <=> { int x=1; ... f(x); ... } ; локальная

Еще один момент: оператор COND имеет и ветку "иначе"; реально оператор RETURN-FROM используется достаточно редко:

Код

(defun foo (x)
  (cond ((cond1 x) (return-from foo (f1 x)))
        ((cond2 x) (return-from foo (f2 x))))
  (foo (g x)))

(defun better-foo (x)
  (cond ((cond1 x) (f1 x))
        ((cond2 x) (f2 x))
        (t (better-foo (g x)))))

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)