Динамическое добавление слов в контекст в REBOL - PullRequest
7 голосов
/ 04 ноября 2008

Представьте себе следующий код REBOL:

foo: context [bar: 3]

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

Я пробовал:

set/any in foo 'baz 3

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

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

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

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

Ответы [ 3 ]

8 голосов
/ 10 января 2009

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

>> foo: make object! [bar: 3]
>> foo: make foo [baz: 3]
>> probe foo
make object! [
    bar: 3
    baz: 3
]
4 голосов
/ 10 января 2009

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

Возможно, вы можете просто использовать BLOCK! S вместо 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

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

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

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

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

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

После этого вы можете сохранить объект, сохраняя его, только сохраняя ссылки на контейнер.

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

1 голос
/ 18 ноября 2010

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

...