Проблема № 1: Разница сбрасывает дубликаты с обоих входов
Во-первых, difference
не следует рассматривать как оператор "вычитания". Это дает вам один из каждого элемента, который уникален в каждом блоке:
>> difference [1 1 2 2] [2 2 2 3 3 3]
== [1 3]
>> difference [2 2 2 3 3 3] [1 1 2 2]
== [3 1]
Таким образом, вы получите эквивалентный набор, если сравнить с [a: 1 b: 1]
и [1 a: b:]
. Вот почему второй 1
отсутствует в вашем конечном выводе. Даже различие с пустым набором удалит все повторяющиеся элементы:
>> difference [a: 1 b: 1] []
== [a: 1 b:]
Если вы на самом деле ищите и замените известный последовательный шаблон , то скорее всего вам нужно replace
с заменой в качестве пустого набора:
>> replace [a: 1 b: 1] [b: 1] []
== [a: 1]
Проблема № 2: равенство функций основано на идентичности
Две отдельные функции с одним и тем же определением будут оценивать два разных функциональных объекта. Например, обе эти функции не принимают параметров и не имеют тела, но когда вы используете get-word!
для их извлечения и сравнения, они не равны:
>> foo: func [] []
>> bar: func [] []
>> :foo == :bar
== false
Итак, еще один фактор в вашем странном результате заключается в том, что f:
вычитается из набора, и две (разные) пустые функции уникальны и, таким образом, оба являются членами разностного набора.
R2 немного страннее, чем R3, и я не могу заставить :o/f
работать. Но вот способ получить «искусственно выглядящую версию» разницы, которую вы пытаетесь достичь:
>> foo: func [] []
>> o: make object! [a: 1 f: :foo b: 2]
>> difference third o compose [f: (:foo)]
== [a: 1 b: 2]
Здесь вы используете тот же идентификатор функции, который вы поместили в объект в блоке, который вычитаете.
В R3, difference
не поддерживает значения функций таким образом. Это может относиться к базовой реализации, основанной на map!
, которая не может иметь «функциональные значения» в качестве ключей. Также в Rebol 3 использование различий на объекте недопустимо. Так что даже ваш первый случай не сработает. (
Проблема № 3: Это не то, как добавлять и удалять свойства
В Rebol 3 вы можете добавлять свойства к объекту динамически без проблем.
>> obj: object [a: 1]
== make object! [
a: 1
]
>> append obj [b: 2]
== make object! [
a: 1
b: 2
]
Но, насколько я знаю, вы не можете удалить их, как только они были добавлены. Конечно, вы можете установить их на none
, но API отражения все равно будут сообщать о них как о находящихся там.
Если вы хотите, чтобы попытка их чтения вызвала ошибку, вы можете установить для нее объект ошибки и затем защитить их от чтения. Вариант этого также работает в R2:
>> attempt [obj/b: to-error "invalid member"]
== none
>> probe obj
== make object! [
a: 1
b: make error! [
code: 800
type: 'User
id: 'message
arg1: "invalid member"
arg2: none
arg3: none
near: none
where: none
]
]
>> obj/b
** User error: "invalid member"
R3 делает еще один шаг вперед и позволяет защитить участника от записи и даже скрыть от участника новые привязки.
>> protect 'obj/b
== obj/b
>> obj/b: 100
** Script error: protected variable - cannot modify: b
>> protect/hide 'obj/b
== obj/b
>> obj
== make object! [
a: 1
]
Если вам нужно динамически добавлять и удалять элементы в R2, вы можете также рассмотреть элемент данных в вашем объекте, который является блоком. Блоки и объекты взаимозаменяемы для многих операций, например:
>> data: [a: 1 b: 2]
== [a: 1 b: 2]
>> data/a
== 1
>> data/b
== 2
И вы можете удалить вещи из них ...
>> remove/part (find data (to-set-word 'a)) 2
== [b: 2]
Все зависит от вашего приложения. Главное, что у object!
есть над block!
, - это способность служить контекстом для связывания слов ...