2008-11-04 4 views
7

Представьте себе следующую REBOL код:Динамическое добавление слов в контексте, в REBOL

foo: context [bar: 3]

у меня теперь есть контекст, в котором foo'bar определен. Как я могу динамически вводить новое слово в этот контекст? Является ли это возможным?

Я пробовал:

set/any in foo 'baz 3

Но это не работает, потому что выражение in foo 'baz терпит неудачу, потому что нет ни слова 'baz определено в foo контексте.

Я хотел бы добавить, что я понимаю, один из способов сделать это заключается в следующем:

foo-prototype: [bar: 3] 
foo: context foo-prototype 
foo: context head append foo-prototype [baz: 3]

Но что, если у вас нет доступа к foo «s прототип блока?

ответ

8

Вы можете добиться того же, используя существующий объект в качестве прототипа для создания нового объекта.

>> foo: make object! [bar: 3] 
>> foo: make foo [baz: 3] 
>> probe foo 
make object! [ 
    bar: 3 
    baz: 3 
] 
+1

Это один из основополагающих аспектов REBOL, но в то время, когда я задавал этот вопрос, я не знал, что вы можете это сделать. – 2009-02-12 05:36:56

4

Существует несколько способов обойти тот факт, что в REBOL/2 просто невозможно расширить объектные контексты.

Вероятно, вы можете просто использовать BLOCK s вместо ОБЪЕКТ 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 

Вы можете даже сделать 'я рабочий, просто добавив сам объект:

>> insert blobject reduce ['self blobject] 
== [[...] foo 1 bar 2] 
>> same? blobject blobject/self 
== true 

Но как вы' ve попросил продлить OBJECT! s, вы можете пойти на решение Peter WA Wood, чтобы просто клонировать объект. Просто имейте в виду, что при таком подходе результирующий клон действительно отличается от исходного.

Так что, если какое-то слово было установлено, чтобы держать объект перед клонированием/расширение, после клонирования объекта, что слово будет по-прежнему держать продленный объект:

>> remember: object: make object! [foo: 1] 
>> object: make object [bar: 2] 
>> same? remember object 
== false 
>> probe remember 
make object! [ 
    foo: 1 
] 

В случае, если это важно для вас, чтобы сохранить «ссылка» на объект нетронутая, вы можете обернуть объект, который необходимо расширить в космическом объекте, как в

>> remember: object: make object! [access: make object! [foo: 1]] 
>> object/access: make object/access [bar: 2] 
>> same? remember object 
== true 

вы можете Safley расширить объект, сохраняя при этом, дали вам хранить только ссылки на контейнер ,

REBOL/3, btw, позволит добавлять слова в объект OBJECT! S.

+0

Очень информативный ответ! Я узнал TON о REBOL, так как я разместил этот вопрос. – 2009-02-12 05:37:53

1

Указанное в REBOL/Ядро Руководство пользователя:.. «Многие блоки содержат другие блоки и строки Когда такой блок копируется, его подсерии не копируются подсерии упоминаются непосредственно и являются одинаковыми серия данные как оригинальный блок. "

+0

Исправьте меня, если я ошибаюсь, но разве это не относится к `object! `s вместо` blocks! `S? – 2017-03-21 00:30:59