6

我喜欢普通的 lisp,但有时输入简单的数学表达式真的很痛苦,比如

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

但是对于名称很长的变量,解析是一个问题。

有人有更好的建议吗?

4

3 回答 3

27

有用于此目的的阅读器宏。

见: 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 )是阅读器宏。

于 2012-08-12T18:54:30.020 回答
3

我正在关注的一个项目是所谓的“Sweet-expressions”,它是Readable Lisp S-expressions Project的一部分。该项目的目标是添加与 s 表达式向后兼容的“甜味”,并且足够简单,表达式不会妨碍宏。(例如,已经观察到运算符优先级确实会干扰宏系统;因此,建议的解决方案不使用运算符优先级。)

应该记住,该项目还处于起步阶段,尤其是对于 Common Lisp;然而,该项目有一个中缀表示法的工作实现,它依赖于大括号和一个简单的算法:

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

很好地翻译成

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

我将向您推荐链接,以更深入地讨论花括号的语义。

于 2013-04-25T04:11:03.233 回答
1

我最近专门为此目的编写了一个 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))

操作数位置括号内的任何内容都被视为 lisp 形式。

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

我发现它比 reader 宏更容易推理和更有利,因为它可能很容易与 lisp 形式混合,因此您可以在表达式中嵌套 lisp 形式。例如,(exp b 2)可以是任何 lisp 形式,如(max a b c)或您自己的用户定义(foobar a b c)

您可以在 github上找到有关README的更多信息。它也可以在 quicklisp 上找到。

于 2016-07-10T06:01:45.327 回答