我试图找出一种类似python的语言,结合MACRO的功能(很奇怪,但只是为了好玩..),例如,分析计算斐波纳契seq的代码就像this:< / p>
from math import *
def analytic_fibonacci(n):
sqrt_5 = sqrt(5);
p = (1 + sqrt_5) / 2;
q = 1/p;
return int( (p**n + q**n) / sqrt_5 + 0.5 )
print analytic_fibonacci(10),
我可以像python一样用MACRO语言重写它:
from math import sqrt
sqrt
def analytic_fibonacci(n):
_2(5)
(1+_1)/2
1/_1
return int((_2**n+_1**n)/_3+0.5)
print analytic_fibonacci(10)
这个想法是使用行号来扩展表达式,这样就不需要显式赋值。 _2
表示将表达式替换为比当前行小2行的表达式,因此第4行中的_2
成为第2行中的表达式,即sqrt
,并且_2(5)
已扩展为sqrt(5)
。 (当前行以_
开始后,当前行之前的行以|
开头)
上面的例子很简单。当我试图重写一个更复杂的例子时,我遇到了问题:
def fibIter(n):
if n < 2:
return n
fibPrev = 1
fib = 1
for num in xrange(2, n):
fibPrev, fib = fib, fib + fibPrev
return fib
我不知道如何使用基于行号的MACRO来表达fibPrev, fib = fib, fib + fibPrev
。我认为这个“MACRO langugage”中缺少一些功能,如果我修复它,fibPrev, fib = fib, fib+fibPrev
是可以表达的。(我听说Lisp中的MACRO是Turing Complete所以我认为上面的例子应该由MACRO表示)有没有人有这方面的想法?
答案 0 :(得分:1)
我看到两种解释你的语言的方法。两者都不是很强大。
第一种方法是将宏扩展为表达式而不是值。然后analytic_fibonacci
展开到
def analytic_fibonacci(n):
return int(((1+sqrt(5))/2**n+1/(1+sqrt(5))/2**n)/sqrt(5)+0.5)
你可能想要一些括号;根据您定义语言的方式,可能会或可能不会为您添加。
这很没用。多重评估问题比比皆是(每次宏引用它时都会重新执行一个函数),它只允许你做普通表达式所做的事情。
第二种解释是,每个由Python表达式组成的语句都会隐式地将该表达式赋给变量。这也没用,因为只有一个语句可以分配给任何这些隐式变量。没有办法
x = 0
for i in range(5):
x += i
因为您不能使用等效的x
来参考 _2
或 _0
,具体取决于最后的位置任务来自。而且,这根本不是一个宏观系统。
使用第二种解释,我们可以添加一个新的运算符来恢复普通变量赋值的功能。我们称之为合并运算符。
merge(_1, _2)
评估为_1
或_2
,具体取决于最近评估的内容。如果尚未评估其中一个参数,则默认为另一个参数。 fibIter
然后变成
def fibIter(n):
if n < 2:
return n
1 # fibPrev
1 # fib
for num in xrange(2, n):
merge(_2, _-1) # temp
merge(_4, _-1) + merge(_3, _0) # fib
_2 # fibPrev
return merge(_2, _5)
这很尴尬;实质上,我们必须将x
之类的变量的每次使用替换为可能已分配的每个位置的merge
。它还需要笨拙的行计数,这使得很难判断哪个“变量”是哪个,并且它不处理多个赋值,for
循环目标等。我不得不使用负索引来引用未来的行,因为我们需要一些方法来引用后来分配的东西。
Lisp宏比你的语言更强大,因为它们允许你将任意Lisp代码应用于你的Lisp代码。您的语言只允许宏扩展为固定表达式。一个Lisp宏可以将任意代码作为参数,删除它,重新排列它,用不同的东西替换它的一部分,具体取决于条件,递归等。你的宏甚至不能接受参数。