在Rebol中设置对象体和块定义之间的差异操作

发布于 2024-08-15 22:19:34 字数 523 浏览 2 评论 0原文

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

例如,如果我有,

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

输出很奇怪(我说奇怪,也许它听起来不像英语,因为我不是英语为母语:))

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

谢谢。

I want to be able to modify Object dynamically by adding / removing properties or methods on the fly. For Adding no problem, for Removing I thought about using Set Difference Math Operator but it behaves weirdly as far as I can see when removing a method from the object.

For example if I have

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

I can substract [a: 1 b: 1] with no problem

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

But I cannot substract f: func[][]:

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

Output is weird (I put strange maybe it doesn't sound english as I'm not english native :) )

Why and what should I do instead ?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鸢与 2024-08-22 22:19:34

问题#1:Difference 丢弃来自两个输入的重复项

首先,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 [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! 的主要功能是充当绑定单词的上下文...

Issue #1: Difference Discards Duplicates From Both Inputs

Firstly, difference shouldn't be thought of as a "subtraction" operator. It gives you one of each element that is unique in each block:

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

So you'd get an equivalent set by differencing with [a: 1 b: 1] and [1 a: b:]. This is why the second 1 is missing from your final output. Even differencing with the empty set will remove any duplicate items:

>> difference [a: 1 b: 1] []
== [a: 1 b:]

If you're looking to actually search and replace a known sequential pattern, then what you want is more likely replace with your replacement as the empty set:

>> replace [a: 1 b: 1] [b: 1] []
== [a: 1]

Issue #2: Function Equality Is Based On Identity

Two separate functions with the same definition will evaluate to two distinct function objects. For instance, these two functions both take no parameters and have no body, but when you use a get-word! to fetch them and compare they are not equal:

>> foo: func [] []
>> bar: func [] []

>> :foo == :bar
== false

So another factor in your odd result is that f: is being subtracted out of the set, and the two (different) empty functions are unique and thus both members of the differenced set.

R2 is a little weirder than R3 and I can't get :o/f to work. But the following is a way to get an ''artificially correct-looking version'' of the difference you are trying to achieve:

>> foo: func [] []

>> o: make object! [a: 1 f: :foo b: 2]

>> difference third o compose [f: (:foo)]  
== [a: 1 b: 2]

Here you're using the same function identity that you put in the object in the block you are subtracting.

In R3, difference does not support function values in this way. It may relate to the underlying implementation being based on map! which cannot have ''function values'' as keys. Also in Rebol 3, using difference on an object is not legal. So even your first case won't work. :(

Issue #3: This isn't how to add and remove properties

In Rebol 3 you can add properties to an object dynamically with no problems.

>> obj: object [a: 1]
== make object! [
    a: 1
]

>> append obj [b: 2]
== make object! [
   a: 1
   b: 2
]

But as far as I know of, you cannot remove them once they have been added. You can set them to none of course, but the reflection APIs will still report them as being there.

If you want to make trying to read them throw an error you can set it to an error object and then protect them from reads. A variant of this also works in 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 takes this one step further and lets you protect the member from writes, and even hide the member from having any new bindings made to it.

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

If you need to dynamically add and remove members in R2, you might also consider a data member in your object which is a block. Blocks and objects are interchangeable for many operations, e.g:

>> data: [a: 1 b: 2]
== [a: 1 b: 2]

>> data/a
== 1

>> data/b
== 2

And you can remove things from them...

>> remove/part (find data (to-set-word 'a)) 2
== [b: 2]

It all depends on your application. The main thing object! has going over block! is the ability to serve as a context for binding words...

情仇皆在手 2024-08-22 22:19:34

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

You cannot dynamically add or remove words from an object in Rebol 2. If you wish to simulate this behaviour you need to create and return a new object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文