在Rebol中设置Object Body和Block定义之间的差异操作

时间:2009-12-18 14:31:56

标签: rebol

我希望能够通过动态添加/删除属性或方法来动态修改Object。对于添加没有问题,对于删除我想到使用设置差异数学运算符,但它从我从对象中删除方法时可以看到奇怪的行为。

例如,如果我有

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 []]
>>

输出很奇怪(我把它说得很奇怪,因为我不是英国人,所以听起来不是英语:))

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

感谢。

2 个答案:

答案 0 :(得分:0)

您无法在Rebol 2中动态添加或删除对象中的单词。如果您希望模拟此行为,则需要创建并返回一个新对象。

答案 1 :(得分: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:功能平等基于身份

具有相同定义的两个单独函数将评估为两个不同的函数对象。例如,这两个函数都没有参数且没有正文,但是当你使用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!,它可以作为绑定词语的上下文......