UNIQUE 和其他集合操作中的相等检查的实现似乎是Cmp_Value
,并且进行比较的方式是减去对象的帧指针。如果减法为零(例如,这些是 SAME? 对象),则比较被视为匹配:
f-series.c 第 283 行,R3-Alpha 开源发布
如果您查看周围的代码,您会在同一例程中看到对 Cmp_Block 的调用。在 Cmp_Block 的情况下,它进行递归比较,并尊重区分大小写......因此块和对象的行为方式之间的区别:
f-series.c 中的 Cmp_Block()
鉴于它是这样编写的,如果您希望 UNIQUE 操作基于对象与其身份的逐字段比较,除了编写自己的例程并调用 EQUAL?...或修改 C 代码。
这是一个不需要更改 C 源代码的简短技巧,它在 UNIQUE 的输出上执行 MAP-EACH。身体过滤掉任何 EQUAL?已经看到的对象(因为当 MAP-EACH 的主体返回未设置时,它不会向结果添加任何内容):
my-unique: function [array [block!]] [
objs: copy []
map-each item unique array [
if object? :item [
foreach obj objs [
if equal? item obj [unset 'item break]
]
unless unset? :item [append objs item]
]
:item ;-- if unset, map-each adds nothing to result
]
]
不幸的是,您必须使用 BLOCK!而不是地图!随时随地跟踪对象,因为 MAP!目前不允许对象作为键。如果他们允许它,他们可能会遇到相同的问题,即不将字段相等的对象散列相同。
(注意:修复这个问题和其他问题在 Ren-C 分支的雷达上,除了现在是具有基本修复的最快的 Rebol 解释器之外,还对集合操作进行了一些增强。聊天中的讨论)