Как вызвать функцию объекта, используя ее строковое имя - PullRequest
2 голосов
/ 08 февраля 2012

Есть идеи, почему не работает следующее?(R3)

o: make object! [
    foo: does [do "bar"]
    bar: does [print "hello from bar"]
]

o/foo
** Script error: bar has no value
** Where: catch either -apply- do foo
** Near: catch/quit either var [[do/next data var]] [data]

Ответы [ 3 ]

3 голосов
/ 15 февраля 2012

Нет прицела !!!?

Причина, по которой «self / bar» не может знать, где найти «BAR», заключается в том, что в отсутствует область действия в Rebol (по крайней мере, в традиционном значении CS).

Слова в Реболе имеют значение только тогда, когда они статически связаны с контекстом. Это происходит автоматически, когда вы СДЕЛАЕТЕ объект, поэтому многие люди даже не осознают этого даже после нескольких лет использования.

Вот шаги (в общих чертах), когда объект (a.k.a. context) создан.

  • Он забирает все корневые слова набора в своей спецификации (в данном случае [FOO: BAR:])

  • Добавляет их к своим текущим внутренним словам (SELF: по умолчанию, больше, если вы используете объект в качестве основы)

  • Затем связывает все слова в блоке (иерархически) с теми множествами, которые он добавил в свою спецификацию.

  • Выполнение блока.

Итак, вы видите, что когда вы выполняете блок слишком поздно, словам уже присваивается их значение, что позволяет интерпретатору запрашивать их значения (что может вызвать оценку выражения, следовательно, E в REBOL).

Глобальный, потому что все, что там действительно когда-то выполняется,

DO и LOAD не могут автоматически связываться ни с чем, кроме глобального контекста ... потому что не существует такого понятия, как "текущий контекст", который вы имели бы в традиционных ООП и императивных языках (помните, нет контекста). Действительно, после ее выполнения этой информации больше не существует, если только вы не привязали «текущий» контекст к слову ... что и делает «SELF», но для привязки его уже нужно загрузить, который при выполнении строка, никогда не встречающаяся.

невежественные функции

В заключение я добавлю, что это может быть неочевидно с первого взгляда, но, хотя он связывал блок спецификации объекта, он все еще не знал, что на самом деле представляют собой FOO и BAR. фактически FOO и BAR могли получить доступ к объекту O только потому, что их функциональный блок, когда он выполнялся через MAKE, был привязан к объекту ... да, еще до того, как он узнал, что это функция. затем, если функция определила свои собственные локальные объекты, она повторно свяжет свой блок тела с этими новыми локальными объектами ... потому что вы догадались ... функция создает свой собственный внутренний контекст, который получает ту же обработку MAKE (но без внутреннего SELF слово).

Надеюсь, это поможет прояснить ситуацию в более очевидном свете.

вот доказательство того, что код не ограничен:

a: make object! [
    data: "HAHAHAAAAA!!!"
    action: does [print self/data]
]


b: make object! [
    data: "BUMBLING BEHEMOT"
    action: does [print self/data]
]

b/action: get in a 'action

; this will print HAHAHAAAAA!!!
b/action
3 голосов
/ 09 февраля 2012

Попробуйте это:

o: make object! [
    foo: does [do get bind load "bar" self]
    bar: does [print "hello from bar"]
]
o/foo ;this will work

Вам нужен этот BINDing, потому что ваша "полоса" находится в объекте, а не в глобальной области видимости.

Проверьте это также:

my-func: does [print "ok"]
o: make object! [
    foo: does [do "my-func"]
    bar: does [print "hello from bar"]
]
o/foo ;this will work too

Вам нужно ЗАГРУЗИТЬ это, потому что это строка, но это должно быть слово, которое нужно связать. Так что они тоже будут работать (поместите их в ваш объект):

do get bind to-word "bar" self

или

do get bind 'bar self
1 голос
/ 16 февраля 2012

Чтобы объяснить ответ Молиады немного подробнее, см. Следующее объяснение:

Слова REBOL содержат ссылку на их контекст.Разница не в том, где оценивается слово, а в том, где оно объявлено.

из http://blog.revolucent.net/2009/07/deep-rebol-bindology.html

Вот очень хороший пример:

x: 0
b: [] loop 3 [use [x] [x: random 100 append b 'x]]
;== [x x x]   <-- there are three X which looks same words (and they are same actually)

reduce b
;== [95 52 80]  <-- but they have different values in their contexts

probe x
;== 0     <-- in global context, it has another value as well

Это выглядит странно на первый взгляд, но на самом деле это не так.USE создает новый контекст каждый раз в цикле LOOP, мы устанавливаем значение X (в контексте созданного USE) в значение, а затем APDEND WORD (не значение!) К блоку.Все слова, которые мы добавляем в блок, несут с собой свои собственные контексты, но они выглядят одинаково.

Когда мы УМЕНЬШАЕМ (или ПЕЧАТАЕМ и т. Д.), Когда мы ПОЛУЧАЕМ их значения в их собственных контекстах, мы видимчто все они имеют разные значения!

...