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

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

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))))

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

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

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 ) это макрос читателя.

Один проект, за которым я слежу, - это так называемые " сладкие выражения". Цель проекта - добавить "подслащивание", обратно совместимое с s-выражениями, и достаточно простое, чтобы выражения не мешали макросам. (Например, было замечено, что приоритет оператора действительно мешает макросистеме; следовательно, предлагаемое решение не использует приоритет оператора.)

Следует помнить, что проект находится в зачаточном состоянии, особенно для Common Lisp; тем не менее, проект имеет рабочую реализацию инфиксной нотации, которая опирается на фигурные скобки и простой алгоритм:

{1 + {2 * 3} + {4 exp 5}}

переводит красиво в

(+ 1 (* 2 3) (exp 4 5))

Я просто отсылаю вас по ссылке для более глубокого обсуждения семантики фигурных скобок.

Недавно я написал макрос cl именно для этой цели, вы можете найти его полезным. Это называется уродливый-крошечный-инфикс-макрос.

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

($ 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) могла бы быть любая форма, как (max a b c) или ваш собственный пользователь (foobar a b c),

Вы можете найти больше информации о README на github. Это также доступно на QuickLisp.

Другие вопросы по тегам