Общий лисп: есть ли менее болезненный способ ввода математических выражений?

Мне нравится обычная шепелявка, но иногда очень больно вводить простые математические выражения вроде

a(8b^2+1)+4bc(4b^2+1)

(Конечно, я могу это преобразовать, но это довольно медленно, я сначала пишу (+ () ()), а затем в каждой скобке помещаю (* () ()) ...)

Мне интересно, знает ли кто-нибудь лучший способ ввести это. Я думал написать математический макрос, где

(math “a(8b^2+1)+4bc(4b^2+1)”) 

расширяется до

(+ (* a (1+ (* 8 b b))) (* 4 b c (1+ (* 4 b b))))

но синтаксический анализ является проблемой для переменных с длинными именами.

У кого-нибудь есть предложения получше?


person h__    schedule 12.08.2012    source источник
comment
(а) Если вам не нравится лисп в качестве калькулятора, воспользуйтесь чем-нибудь другим. Я рекомендую python (b) выполнение такого рода преобразований - это базовое упражнение по информатике. Я настоятельно рекомендую вам разобраться в этом самостоятельно, по крайней мере, в части манипуляций со строками, и вернуться, когда вы столкнетесь с проблемами, превратив их в удобный макрос.   -  person Marcin    schedule 12.08.2012
comment
Хорошо. Я думаю, что это моя вина, что Project Euler шепелявил ...   -  person h__    schedule 12.08.2012
comment
Lisp абсолютно подходит для Project Euler. Конечно, вводить длинное математическое выражение может быть неудобно; с другой стороны, Common Lisp очень подходит для восходящего подхода к построению решений, который требуется для решения многих проблем в PE.   -  person Haile    schedule 13.08.2012
comment
@Haile Что вы имеете в виду (создавайте решения снизу вверх)? Вы можете привести пример?   -  person h__    schedule 13.08.2012
comment
@hyh Вы разбиваете проблему на мелкие кусочки. Вы сосредотачиваетесь только на каждой части. Вы пробуете короткие фрагменты кода на REPL. Вы начинаете составлять эти фрагменты в функциях, чтобы обеспечить небольшие базовые функции. Вы сразу же тестируете эти функции, используя REPL. Вы пишете свое решение постепенно, взаимодействуя с интерпретатором. Вы объединяете уже проверенные функции в более крупные. И так далее..   -  person Haile    schedule 16.08.2012
comment
Да я вижу. Именно этим я и занимаюсь ...   -  person h__    schedule 17.08.2012


Ответы (3)


Для этого есть макросы считывателя.

См .: http://www.cliki.net/infix

Например:

CL-USER 17 > '#I(a*(8*b^^2+1)+ 4*b*c*(4*b^^2+1) )
(+ (* A (+ (* 8 (EXPT B 2)) 1)) (* 4 B C (+ (* 4 (EXPT B 2)) 1)))

' - обычная цитата. #I( some-infix-expression ) - это макрос для чтения.

person Rainer Joswig    schedule 12.08.2012
comment
Спасибо, могу я спросить, что здесь означает '#I? - person h__; 12.08.2012
comment
Это макрос чтения, который определен в библиотеке infix. - person Svante; 13.08.2012


Недавно я написал макрос cl именно для этой цели, он может вам пригодиться. Это называется ugly-tiny-infix-macro.

Вы можете записать рассматриваемое выражение как:

($ a * ($ 8 * (expt b 2) + 1) + 4 * b * c * ($ 4 * (expt b 2) + 1))

Он расширен до

(+ (* A (+ (* 8 (EXPT B 2)) 1)) (* (* (* 4 B) C) (+ (* 4 (EXPT B 2)) 1)))

Объяснение: $ - это имя макроса. Аргументы рассматриваются как список выражений и, следовательно, широкое использование пробелов для отделения чисел / форм от символов, обозначающих операторы.

Рассмотрим следующие примеры, чтобы лучше понять функцию этого макроса:

($ 1 + 2)       ; gets converted to (+ 1 2), where name of the macro is $
($ t and nil)   ; gets converted to (and t nil)
($ 3 > 5)       ; gets converted to (> 3 5)
($ 1 + 2 + 3)   ; gets converted to (+ (+ 1 2) 3)
($ 1 + 2 *  3)      ; gets converted to (+ 1 (* 2 3))
($ 1 < 2 and 2 < 3) ; gets converted to (AND (< 1 2) (< 2 3))

Все, что находится в круглых скобках в позиции операнда, рассматривается как форма шепелявости.

($ 2 + (max 9 10 11)) ; gets converted to (+ 2 (max 9 10 11)). It could have been any function / lisp form.
($ 6 / ($ 1 + 2))     ; gets converted to (/ 6 ($ 1 + 2)), and then subsequently to (/6 (+ 1 2))

Я считаю, что это легче рассуждать и более выгодно, чем макрос чтения, поскольку он может легко смешиваться с формами lisp, поэтому вы можете вкладывать формы lisp в выражение. Например, (exp b 2) мог быть любой формой lisp, например (max a b c) или вашим собственным (foobar a b c), заданным пользователем.

Дополнительную информацию можно найти в README на github. Это также доступно на quicklisp.

person Peeyush Kushwaha    schedule 10.07.2016