问题 #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:函数平等基于同一性
具有相同定义的两个独立函数将评估为两个不同的函数对象。例如,这两个函数都没有参数也没有函数体,但是当你使用 aget-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!
能够作为绑定单词的上下文......