我正在使用的平台是DrScheme。
我已经看到一对(a b)
[由(cons a b)
构建]在语言中实现,就像这样的过程:
(define (cons a b)
(lambda(pick)
(cond ((= pick 1) a)
((= pick 2) b))))
和选择器:
(define (car x) (x 1))
(define (cdr x) (x 2))
然后是列表,使用(cons a (cons b (cons c (cons ...))))
等表达式构建。
现在,我试图理解的是(在DrScheme的提示下输入):
> (define l1 '(a b c))
> (define l2 (list 'a 'b 'c))
> l1
(a b c)
> l2
(a b c)
> (eq? l1 l2)
#f
好的,l2只是一个列表(也就是说,一个程序,等等......)就像我描述过的住所一样,但是...... 什么是l1?一个符号?一系列人物?不管它是什么,它是如何在语言中实现的? 谢谢!
答案 0 :(得分:3)
l1
也只是一个包含相同元素的列表。请注意,这也会返回#f
:
(define l1 '(a b c))
(define l2 '(a b c))
(eq? l1 l2)
这会返回#t
:
(define l1 '(a b c))
(define l2 (list 'a 'b 'c))
(equal? l1 l2)
原因是eq?
检查l1
和l2
是否是对内存中同一对象的引用,而equal?
检查它们是否具有相同的内容。
答案 1 :(得分:1)
列表不是 atoms ,这是重要的部分。符号虽然是原子,但这意味着当它们相同时,它们存在于同一个内存中,它们就像数字一样,确实可以看作是指针。符号也不可变,符号foo
就像数字3
。
列表不是原子,两个列表或字符串,具有相同内容的向量可以很好地驻留在两个不同的内存位置。
eq?
仅测试内存位置。 eqv?
测试等价,这是模糊的,它取决于哪个实现,Scheme标准相当自由,它只表示它必须至少基本上是eq?
的超集。另一端的equal?
测试结构相等并递归,所以这是一个非常昂贵的操作,这就是为什么符号通常比标识符的字符串更受欢迎。
(define l1 (list 1 2 3))
(define l2 (list 1 2 3))
(eq? l1 l2) ; ===> #f in most implementations
(equal? l1 l2) ; ===> #t in all implementations
(eqv? l1 l2) ; ===> #t in some implementations
(define l3 (cdr l1))
(define l4 (cdr l1))
(eq? l3 l4) ; ===> #t, this means that they 'share memory', if you change l3 or l4, l1 will change with it, beware. This is how car and cdr work, they do not copy.
(define l6 (cons 1 l4));
(eq? l1 l6) ; ===> #f again, cons does allocate new memory, but the tails may very well share it, s in this case, l6 does share its tail with all lists except l2 here in memory.
此外,一些术语,缺点创建一对,这与两个元素的列表不同,它创建一对(a . b)
列表(a b)
实际上与对(a . (b . ()))
相同1}}
另外,cons和car和cdr都是原语,你在下面看到的实现是计算机程序的结构和实现中的演示,它表明它们并不是严格需要的,而是将它们作为原语显着提高了性能,因此最好不要重新定义你的缺点,汽车和cdrs。
答案 2 :(得分:1)
> > (define l1 '(a b c))
> > (define l2 (list 'a 'b 'c))
> > l1 (a b c)
> > l2 (a b c)
> > (eq? l1 l2)
> #f
好的,l2只是一个列表(即一个程序,等等......)就像我所描述的那样 住所,但是......什么是l1?一个符号?一系列人物?无论如何 是,它是如何在语言中实现的?谢谢!
定义的格式为:
(定义< name>< expression>)
在运行时,表达式< expression>被评估,结果是一个值。 该值存储在内存中的某个位置。为了使用这个值 其他计算,可以使用名称< name>。术语是那样的 <名称>与价值绑定。
需要注意的重要一点是,名称< name>只出现在你的 源代码。它在运行时不存在。询问名称l1是否为 因此,符号毫无意义。
编译器翻译的一种可能策略(定义< name>< expression>) 如下(忽略Scheme实现有垃圾收集)。
注意,名称< name>不会出现在此列表中。