English 中文(简体)
Set Difference Operation between an Object Body and a Block definition in Rebol
原标题:
  • 时间:2009-12-18 14:31:55
  •  标签:
  • rebol

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.

最佳回答

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

问题回答

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.





相关问题
Rebol Email Pop Server error

I have tested pop successufully with some POP servers with Rebol but it doesn t work with my hosting server dreamhost (which works with Outlook I have tested http://wiki.dreamhost.com/Outlook_Express )...

Rebol and /local Object

The new function below doesn t work if Obj is local. If I remove it from /local it works. So what to do to make it work with a local Obj thanks ? Sure not hard for you. Person: make object! [ Person:...

In Rebol How to get the Object Path Name (String)?

Let s say I have list: [system/history system/prompt] I want to convert to list-string: ["system/history" "system/prompt"] This may be an obvious answer but I can t see any :) Thanks.

What new Widgets in Rebol 3 Vid? [closed]

Rebol 2 VID was hugely missing Dropdownlist and Treeview, I have made a search on Rebol 3 on Google but couldn t find anything except a discussion. So what will Rebol 3 VID really include as new ...

热门标签