问题
Imagine the following REBOL code:
foo: context [bar: 3]
I now have a context foo
in which 'bar
is defined. How can I dynamically inject a new word into this context? Is it possible?
I've tried:
set/any in foo 'baz 3
But that doesn't work because the expression in foo 'baz
fails because there is no word 'baz
defined in the foo
context.
I should add that I realize one way to do this is as follows:
foo-prototype: [bar: 3] foo: context foo-prototype foo: context head append foo-prototype [baz: 3]
But what if you don't have access to foo
's prototype block?
回答1:
You can achieve the same by using the existing object as a prototype to create a new object.
>> foo: make object! [bar: 3]
>> foo: make foo [baz: 3]
>> probe foo
make object! [
bar: 3
baz: 3
]
回答2:
There are several ways to work around the fact that in REBOL/2 it's just not posssible to extend object contexts.
Probably you can just use BLOCK!s instead of OBJECT!s:
>> blobject: [foo 1]
== [foo 1]
>> blobject/bar
** Script Error: Invalid path value: bar
** Near: blobject/bar
>> append blobject [bar 2]
== [foo 1 bar 2]
>> blobject/bar: 3
== 3
You can even make 'self working by just appending the object itself:
>> insert blobject reduce ['self blobject]
== [[...] foo 1 bar 2]
>> same? blobject blobject/self
== true
But as you've asked for extending OBJECT!s, you may go for Peter W A Wood's solution to simply clone the object. Just keep in mind that with this approach the resulting clone really is a different thing than the original object.
So, if some word has been set to hold the object prior to cloning/extending, after cloning the object that word will still hold the unextended object:
>> remember: object: make object! [foo: 1]
>> object: make object [bar: 2]
>> same? remember object
== false
>> probe remember
make object! [
foo: 1
]
In case it's essential for you to keep "references" to the object intact, you might want to wrap the object you need to extend in an outer object as in
>> remember: object: make object! [access: make object! [foo: 1]]
>> object/access: make object/access [bar: 2]
>> same? remember object
== true
You can then safley extend the object while keeping, given you only store references to the container.
REBOL/3, btw, will allow adding words to OBJECT!s.
回答3:
Said in REBOL/Core User Guide: "Many blocks contain other blocks and strings. When such a block is copied, its sub-series are not copied. The sub-series are referred to directly and are the same series data as the original block."
来源:https://stackoverflow.com/questions/263402/dynamically-adding-words-to-a-context-in-rebol