Реализация проверки на равенство в UNIQUE и других операциях над множествами выглядит как Cmp_Value
, и способ сравнения заключается в вычитании указателей фреймов объектов. Если это вычитание равно нулю (например, это ОДИНАКОВЫЙ объект?), тогда сравнение считается совпадением:
f-series.c Строка 283, R3- Альфа-версия с открытым исходным кодом
Если вы посмотрите на окружающий код, вы увидите вызов Cmp_Block в той же процедуре. В случае Cmp_Block он выполняет рекурсивное сравнение и учитывает чувствительность к регистру... отсюда и разница между действиями блоков и объектов:
Cmp_Block() в f-series.c< /а>
Учитывая, что это написано таким образом, если вы хотите, чтобы операция UNIQUE основывалась на сравнении полей объектов с их идентичностью, нет другого способа сделать это, кроме написания собственной процедуры и вызова EQUAL?... или изменение кода C.
Вот короткий хак, не требующий изменения исходного кода C, который выполняет MAP-EACH по выходу UNIQUE. Тело отфильтровывает любые РАВНЫЕ? объекты, которые уже были просмотрены (поскольку, когда тело MAP-EACH возвращает unset, оно ничего не добавляет к результату):
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
]
]
К сожалению, вы должны использовать БЛОК! а не МАП! следить за объектами, когда вы идете, потому что КАРТА! в настоящее время не позволяет использовать объекты в качестве ключей. Если бы они разрешили это, у них, вероятно, возникла бы та же проблема, связанная с неодинаковым хэшированием одинаковых по полю объектов.
(Примечание. Исправление этой и других проблем находится в поле зрения ветки Ren-C, которая, помимо того, что теперь является самым быстрым интерпретатором Rebol с фундаментальные исправления, а также небольшие улучшения в операциях set. Обсуждения в чате)
person
HostileFork says dont trust SE
schedule
06.11.2015