LINUX.ORG.RU

вопрос про макросы в лиспе


0

0

Вот решил я изучить Common Lisp путём написания небольших прог,
и взялся за написание интерпретатора бейсика. 
По ходу написания заметил в функции, разбирающей строку на оператор
и параметры, закономерность:

(cond 
      ((integerp operator) (setf (gethash operator *program*) argument))
      ((eql operator 'rem) (basic-rem argument))
      ((eql operator 'let) (basic-let argument))
      ((eql operator 'list) (basic-list argument))
      ((eql operator 'run) (basic-run argument))
      ((eql operator 'quit) (basic-quit argument))
      (t (syntax-error "Не знаю такого оператора")))

чем дальше я буду писать, тем больше будет становится этот кусок.
можно ли заменить этот кусок макросом? и как тогда из параметра
сделать функцию "basic-параметр"?

Можно преобразовать строку в символ, и вызвать функцию, привязанную к этому символу.

Legioner ★★★★★
()

Лисп и макросы, увы, не помогут волшебным образом написать хороший код.

Может, лучше пересмотреть архитектуру программы, вместо борьбы с искуственно созданной проблемой?

anonymous
()
Ответ на: комментарий от anonymous

>Лисп и макросы, увы, не помогут волшебным образом написать хороший код.

А что поможет?:)

>Может, лучше пересмотреть архитектуру программы, вместо борьбы с искуственно созданной проблемой?

Первый коммент в топике как раз про это, но там поподробнее написано, в какую сторону копать:)

OBOLLlu
() автор топика
Ответ на: комментарий от OBOLLlu

>А что поможет?:)

Наверное, чтобы написать "правильный" интерпретатор (не важно, на каком языке), неплохо бы почитать литературу по теории компиляции/интерпретации.

Вот например, тест (integerp operator). Как оператор может быть числом? Это нонсенс. Наверное, это всё-таки не оператор, а лексема или токен. Возникает подозрение, что ты плохо знаком с терминологией предметной области. Это в свою очередь наводит на мысль, что архитектура интерпретатора продумана плохо, типа вольный полёт фантазии.

(Я тоже не большой спец в интерпретаторах, но Ахо/Сети/Ульмана таки читал).

anonymous
()

Несомненно можно. Скажи, ты зачем поместил в хеш таблицу 'rem,
 если можно было поместить #'basic-rem? Тогда было бы чего-то вроде

(let ((fn (gethash operator *program*)))
  (if fn
    (funcall fn argument)
    (syntax-error "Вы Лох!")))

Ну, и соответственно надобно учесть высказывания предыдущих ораторов, да.

bugmaker ★★★★☆
()

Фишка в том, что это нифига не из просто хеш-таблицы всё берется,
а из хеш-таблицы строк:
http://pastebin.com/m75c1d8e2
(вышеописанный кусок в самом конце, функция basic)
Я начал читать вышеуказанную книгу, и понял, что мой код большей 
частью - говно. Единственное что частично не говно -- преобразование математики в лисп-выражения с последующим скармливанием eval'у (хотя над этим куском ещё работать и работать)

OBOLLlu
() автор топика
Ответ на: комментарий от OBOLLlu

Здесь пример того, как производить макрос подобный тому, о котором ты спрашивал.

http://www.linux.org.ru/jump-message.jsp?msgid=2230047&cid=223133

Но действительно, твой код ужасен, ибо ты записал питоновскую прогу на лиспе. Данная конструкция ИМХО всё равно неуместна и лучше переделать.

bugmaker ★★★★☆
()

Почитал бы ты книгу Ахо про компиляторы...

xTERM ★★
()

Лучше бы ты вместо зоопарка из функций basic-bla-bla сделал одну обобщённую (generic) функцию.

(defgeneric basic-all (operator argument) (:documentation "One function to rule them all"))

(defmethod basic-all ((operator integer) argument) (setf (gethash operator *program*) argument))

(defmethod basic-all ((operator (eql 'rem)) argument) ;; body of basic-rem )

...

-- Lispnik

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.