yra*_*lik 72 scheme functional-programming
我想知道这些操作之间有什么区别.我在Stack Overflow中看到了类似的问题,但它们是关于Lisp的,并且没有三个运算符之间的比较.所以,如果已经提出这个问题,请告诉我.
我在Scheme中编写不同类型的命令,我得到以下输出:
(eq? 5 5) -->#t
(eq? 2.5 2.5) -->#f
(equal? 2.5 2.5) --> #t
(= 2.5 2.5) --> #t
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么会这样吗?
Aad*_*hah 135
我会逐渐回答这个问题.让我们从=等价谓词开始.该=谓词用于检查两个数字是否相等.如果您提供除了数字之外的任何其他内容,那么它将引发错误:
(= 2 3) => #f
(= 2.5 2.5) => #t
(= '() '()) => error
Run Code Online (Sandbox Code Playgroud)
所述eq?谓词用于检查其两个参数是否respresent同一对象在内存中.例如:
(define x '(2 3))
(define y '(2 3))
(eq? x y) => #f
(define y x)
(eq? x y) => #t
Run Code Online (Sandbox Code Playgroud)
但请注意'(),内存中只有一个空列表(实际上内存中不存在空列表,但是指向内存位置的指针0被视为空列表).因此,比较空列表时eq?将始终返回#t(因为它们代表内存中的同一对象):
(define x '())
(define y '())
(eq? x y) => #t
Run Code Online (Sandbox Code Playgroud)
现在,根据实现eq?可能会或可能不会返回#t原始值,如数字,字符串等.例如:
(eq? 2 2) => depends upon the implementation
(eq? "a" "a") => depends upon the implementation
Run Code Online (Sandbox Code Playgroud)
这是eqv?谓词出现的地方.它eqv?与eq?谓词完全相同,只是它总是返回#t相同的原始值.例如:
(eqv? 2 2) => #t
(eqv? "a" "a") => depends upon the implementation
Run Code Online (Sandbox Code Playgroud)
因此eqv?是一个超集,eq?在大多数情况下你应该使用eqv?而不是eq?.
最后我们来到equal?谓词.的equal?谓词是完全一样的eqv?谓词,不同之处在于它也可以被用来测试是否两个列表,载体等具有满足相应的元件eqv?谓词.例如:
(define x '(2 3))
(define y '(2 3))
(equal? x y) => #t
(eqv? x y) => #f
Run Code Online (Sandbox Code Playgroud)
一般来说:
=当您希望测试两个数字是否相等时,请使用谓词.eqv?当您希望测试两个非数字值是否相等时,请使用谓词.equal?当您希望测试两个列表,向量等是否相同时,请使用谓词.eq?除非您确切知道自己在做什么,否则不要使用谓词.eq?是#t什么时候它是相同的地址/对象.通常,人们可以期望#t用于相同的符号,布尔和对象,#f用于不同类型的值,具有不同的值,或者不同的结构 Scheme/Lisp实现具有在其指针中嵌入类型和嵌入的传统如果空间足够,则在同一空间中的值.因此,一些指针实际上不是地址而是值,如char R或Fixnum 10.这些将是eq?因为"地址"是嵌入式+值.一些实现还重用不可变常量.(eq?'(1 2 3)'(1 2 3))在解释时可能是#f但编译时可能是#t,因为它可能得到相同的地址.(与Java中的常量String池一样).因此,涉及的许多表达eq?都是未指定的,因此评估为#t或#f是依赖于实现的.
eqv?是#t用于同样的事情eq?.它也是#t,如果它是一个数字或字符,它的值是相同的,即使数据太大而不适合指针.因此,对于那些eqv?检查该类型的额外工作是受支持的,两者都是相同的类型,并且它的目标对象具有相同的数据值.
equal?是#t用于相同的东西eqv?,如果它是一个复合类型,如pair,vector,string和bytevector,它递归地处理equal?部分.在实践中,如果两个对象看起来相同,它将返回#t.在R6RS之前,equal?在圆形结构上使用是不安全的.
=就像eqv?但它仅适用于数字类型.它可能更有效率.
string=?就像equal?,但它只适用于字符串.它可能更有效率.
equal? 递归地比较两个对象(任何类型)的相等性.
请注意,对于大型数据结构而言,这可能很昂贵,因为必须遍历整个列表,字符串,向量等.
如果对象只包含一个元素(EG:数字,字符等),则与之相同eqv?.
eqv? 测试两个对象以确定两者是否"通常被视为同一对象".
eqv?并且eq?是非常相似的操作,它们之间的差异将在某种程度上与实现有关.eq?是相同eqv?但可能能够辨别更精细的区别,并且可以更有效地实施.
eqv?.= 比较数字相等的数字.
(= 1 1.0 1/1 2/2)