有没有办法使用这种基于MACRO的语言迭代计算斐波纳契?

时间:2014-02-22 04:45:27

标签: python macros programming-languages fibonacci

我试图找出一种类似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表示)有没有人有这方面的想法?

1 个答案:

答案 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宏可以将任意代码作为参数,删除它,重新排列它,用不同的东西替换它的一部分,具体取决于条件,递归等。你的宏甚至不能接受参数。