- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想用 python 编写一个 lisp 解释器。它适用于非递归表达式。但是,我发现在递归中引用很困惑。
以下程序的描述:
以字符串形式编写的lisp代码在parse()
函数中解析,将空格和圆括号替换为逗号和方括号,传递给python的eval()
函数。
符号和句法词典包含原始程序。
评估以递归方式进行,其中语法模式能够更改环境字典。 (label
=> 扩展当前字典,lambda
=> 创建一个新字典)。 quote
直接返回它后面的内容。至于过程,它通过在评估所有语句后调用它们来工作。
就是这样。
# -*- coding:utf-8 -*-
import re
def parse(s):
l = re.sub(r'\s+', ', ', (' '+s.lower()+' ').replace('(', '[').replace(')', ']'))[2:-2]
return eval(re.sub(r'(?P<symbol>[\w#%\\/^*+_\|~<>?!:-]+)', lambda m : '"%s"' % m.group('symbol'), l))
def cons(a, d):
if atom(d):
return (a, d)
return (lambda *args : list(args))(a, *d)
def car(s):
return s[0]
def cdr(s):
if len(s) == 1:
return []
return s[1:]
def atom(s):
return not isinstance(s, list)
def eq(s, t):
return s == t
def cond(l, d):
for [p, e] in cdr(l):
if eval_(p, d):
return eval_(e, d)
class lambda_object:
count = 0
def __init__(self, l, d):
self.dic = d
self.li = l[1]
self.ex = l[2]
lambda_object.count += 1
self.serial = lambda_object.count
def __call__(self, *args):
for i in range(len(self.li)):
self.dic[self.li[i]] = args[i]
return eval_(self.ex, self.dic)
def __str__(self):
return 'COMPOND-PROCEDURE-#%d' % self.serial
__repr__ = __str__
def label(l, d):
d[l[1]] = eval_(l[2])
def quote(l, d):
return l[1]
symbol_s = {'cons':cons, 'car':car, 'cdr':cdr, 'atom?':atom, 'eq?':eq, '#t':True, '#f':False}
syntax_s = {'cond':cond, 'lambda':lambda_object, 'quote':quote, 'label':label}
def eval_(l, s=symbol_s):
print 'code =>', l
if atom(l):
return symbol_s[l]
#if not atom(l[0]):
# l[0] = eval_(l[0])
if l[0] in syntax_s:
return syntax_s[l[0]](l, s)
else:
根据答案,以下几行是不正确的:
for i in range(len(l))[1:]:
l[i] = eval_(l[i])
print 'sval =>', l
if isinstance(l[0], str):
l[0] = s[l[0]]
return l[0](*l[1:])
它们应该是:
operator = eval_(l[0], s)
operands = map(lambda e: eval_(e,s), l[1:])
print 'sval =>', operator, '<<', operands
return operator(*operands)
这就是程序。
运行时:
code = '''
(label ff
(lambda (s)
(cond
((atom? s) s)
(#t (ff (car s))))))
'''
print eval_(parse(code))
print symbol_s
print eval_(parse("(ff (quote (((a b) c))))"))
它产生了一些东西:
code => ['label', 'ff', ['lambda', ['s'], ['cond', [['atom?', 's'], 's'], ['#t', ['ff', ['car', 's']]]]]]
code => ['lambda', ['s'], ['cond', [['atom?', 's'], 's'], ['#t', ['ff', ['car', 's']]]]]
None
{'cons': <function cons at 0x10efcaf98>, 'ff': COMPOND-PROCEDURE-#1, 'eq?': <function eq at 0x10efcaf28>, 'car': <function car at 0x10efca978>, '#f': False, 'atom?': <function atom at 0x10efcad68>, 'cdr': <function cdr at 0x10efcab38>, '#t': True}
code => ['ff', ['quote', [[['a', 'b'], 'c']]]]
code => ['quote', [[['a', 'b'], 'c']]]
sval => ['ff', [[['a', 'b'], 'c']]]
code => ['cond', [['atom?', 's'], 's'], ['#t', ['ff', ['car', 's']]]]
code => ['atom?', 's']
code => s
sval => ['atom?', [[['a', 'b'], 'c']]]
code => #t
code => ['ff', ['car', 's']]
code => ['car', 's']
code => s
sval => ['car', [[['a', 'b'], 'c']]]
;; from this line, the quotation disappeared
sval => ['ff', [['a', 'b'], 'c']]
code => ['cond', [[<function atom at 0x10efcad68>, [[['a', 'b'], 'c']]], 's'], ['#t', [COMPOND-PROCEDURE-#1, [['a', 'b'], 'c']]]]
code => [<function atom at 0x10efcad68>, [[['a', 'b'], 'c']]]
code => [[['a', 'b'], 'c']]
code => [['a', 'b'], 'c']
code => ['a', 'b']
code => b
Traceback (most recent call last):
File "slisp.py", line 113, in <module>
print eval_(parse("(ff (quote (((a b) c))))"))
...
File "slisp.py", line 66, in eval_
return symbol_s[l]
KeyError: 'b'
我知道有问题,但我不知道如何解决。在评估 (ff (quote (((a b) c))))
时,它在下一个递归中更改为 (ff ((a b) c))
没有引号。
这是怎么回事?
最佳答案
因为 ff
是一个程序,它计算它的参数。在第一种情况下,它有参数 (quote (((a b) c)))
在它适用它:
code => ['ff', ['quote', [[['a', 'b'], 'c']]]]
code => ['quote', [[['a', 'b'], 'c']]]
sval => ['ff', [[['a', 'b'], 'c']]]
第二次它有参数 (car s)
其中 s
是一个绑定(bind)变量。
code => ['ff', ['car', 's']] ;; unevaluated expression
code => ['car', 's']
code => s
sval => ['car', [[['a', 'b'], 'c']]] ;; what apply gets for car
;; from this line, the quotation disappeared
sval => ['ff', [['a', 'b'], 'c']] ;; what apply gets for ff
据我所知,我在这里看不到任何错误。它完全按照它应该做的去做。
可能其他地方有错误。当您查看从一个递归到另一个递归的 cond 输出时:
code => ['cond', [['atom?', 's'], 's'], ['#t', ['ff', ['car', 's']]]]
code => ['cond', [[<function atom at 0x10efcad68>, [[['a', 'b'], 'c']]], 's'], ['#t', [COMPOND-PROCEDURE-#1, [['a', 'b'], 'c']]]]
除了环境之外,这些应该是相同的,因为它的代码相同。如果你看看你在 eval_
中做了什么,我看到你做了:
`l[i] = eval_(l[i])`
这很糟糕,因为 l 包含你的 AST。第二次您重新访问它时,评估将不再是代码的符号,而是您上次获得的值。您需要将运算符和操作数评估为其他内容,然后应用它们。
我不是 python 程序员,但我猜你正在寻找这样的东西:
operator = eval_(l[0], s)
operands = map(lambda e: eval_(e,s), l[1:])
return operator(*operands);
虽然你在几个地方都这样做了,但是你在任何地方使用代码 =
都可能会发生变化。
关于python - Lisp 解释器引用,在 python 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44263385/
你们能帮帮我吗,这是我们的讲师给我们的教程问题,无论我们尝试了多少,我们实际上似乎都无法破解它。请帮忙 ; perform some type/error checking, ; then ca
在 Common Lisp 中编写、编译和测试一个函数,该函数接受一个列表并计算列表中正整数的总数。必须编译然后执行包含函数的 .lisp 文件。在编译该文件后开始传递它,列出要生成的结果的结果,从而
我是 Lisp 初学者,我很难理解为什么下面的代码会给我一个错误。 (dolist (elem '(mapcar mapcon)) (when (fboundp `
我听说 Lisp 可以让你重新定义语言本身,我也试图研究它,但没有任何地方明确的解释。有人有一个简单的例子吗? 最佳答案 Lisp 用户将 Lisp 称为 可编程编程语言 .用于符号计算 - 用符号计
Closed. This question is off-topic. It is not currently accepting answers. Learn more。 想改进这个问题吗Updat
这些是 cons 参数的不同组合的输出。我刚开始学习 lisp。有人可以帮我理解这些吗? Break 80 [81]> (CONS '(A) 'B) ((A) . B) Break 80 [81]>
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
我想问一下为什么这个功能不起作用... (defun nenum(ls) (cond ((null ls) nil) ((listp car(ls)) (nenum (rest ls)
如果我有一个原子,例如“a4”,我需要能够将 1 添加到“4”部分以使其成为 a5,但是因为它被认为是一个字符串,所以这是不可能的,所以如果我可以拆分 (a4 ) 到 ((a)(4)) 中,然后我可以
我有一个关于动态构建函数(或类似的东西)的问题。在 Java 中,我可以通过编程将一些 Source 写入字符串,编译该字符串并像函数一样执行它多次。 假设我有一些遗传算法来创建最佳代码以获取 n 个
我是 Common Lisp 的新手,正在学习教程,但无法全神贯注 (equal '(reverse (a b)) '(b a))) 返回零。 非常感谢您的协助。 M. 最佳答案 在 lisp 中引
我有一个使用列表表示的树。例如: (1 ((2 (3)) (3 (2)))) (2 ((1 (3)) (3 (1)))) (3 ((1 (2)) (2 (1)))))` 现在我需要在维护层次结构树的同
在此站点:http://www.gigamonkeys.com/book/practical-a-simple-database.html有如下列出的用户入口函数: (defun prompt-rea
我对 lisp 比较陌生,对在以下上下文中使用嵌套列表的最佳方法很好奇: 所以,我有以下功能: (defun get-p0 (points) (loop for (label x y) in
我正在为 CLOS 类编写一个函数,该函数反转所述类对象的列表元素。 我有一个返回反向列表的方法,但如何让它将对象的列表设置为该列表?我可以在存储列表的函数中有一个实例变量,然后将元素设置为那个吗?或
我知道,严格来说,没有编译语言或解释语言这回事。 但是,一般来说,LISP 是用来编写 Python、bash 脚本、批处理脚本之类的脚本的吗? 还是像 C++、JAVA 和 C# 这样的通用编程语言
在此站点 http://jatha.sourceforge.net/快速函数的示例是通过递归。是不是递归通常比 Lisp 中的迭代更快并且性能更好? 编辑:Lisp 是否比其他语言更优化递归? 最佳答
另一个新手(常见)LISP 问题: 基本上在大多数编程语言中,函数都有一种方法接收对变量的引用而不仅仅是值,即通过引用传递而不是通过值传递。比方说,为了简单起见,我想编写一个 LISP 函数来接收一个
这个问题在这里已经有了答案: How do I find the index of an element in a list in Racket? (3 个答案) 关闭 9 年前。 如果我有这样的列
我在为这个程序生成正确的输出时遇到了一些问题。我的输出几乎是正确的,但缺少一些步骤。我的代码如下: (defun kt (x y m n) ;set the
我是一名优秀的程序员,十分优秀!