0

我希望能够通过动态添加/删除属性或方法来动态修改对象。对于添加没问题,对于删除,我考虑过使用 Set Difference Math Operator 但在从对象中删除方法时,它的行为很奇怪。

例如,如果我有

O: make object! [
    a: 1        
    f: func [][]
    b: 1
]

我可以毫无问题地减去 [a: 1 b: 1]

>> difference third O [b: 1 a: 1]
== [f: func [][]]

但我不能减去 f: func[][]:

>> difference third O [f: func[][]]
== [a: 1 b: func [][] func []]
>>

输出很奇怪(我说得很奇怪,因为我不是英语母语,所以听起来可能不是英语:))

为什么以及我应该怎么做?

谢谢。

4

2 回答 2

0

在 Rebol 2 中,您不能从对象中动态添加或删除单词。如果您希望模拟这种行为,您需要创建并返回一个新对象。

于 2009-12-24T01:27:56.650 回答
0

问题 #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!能够作为绑定单词的上下文......

于 2010-01-03T03:48:53.797 回答