Как избежать вызова функции в обстоятельствах, подобных КОМПОЗИЦИИ?

В следующем коде мы можем присвоить результат GET-WORD p через SET-WORD, а затем использовать его под новым именем:

p: :print 
p [{Hello} {World}]

Но что, если вы используете КОМПОЗИЦИЮ и обнаруживаете такую ​​ситуацию?

do compose [p: (:print)] 
p [{Hello} {World}]

Это дает ошибку:

*** ERROR
** Script error: -unnamed- is missing its value argument
** Where: do
** Near: do compose [p: (:print)] p ["Hello" "World"]

Таким образом, это похоже на то, что значения функций в блоке «живы», когда их видят в интерпретаторе ... независимо от того, были ли они получены в качестве оценочного результата или нет. (Казалось бы, они должны быть инертными, если они не были извлечены или применены каким-либо образом, иначе такие назначения невозможны из КОМПОЗИЦИИ или подобного.)

Кажется, вам нужно процитировать Get-слово, например:

do compose [p: (quote :print)] 
p [{Hello} {World}]

Это может помочь сделать p функцией печати. Но можно ли это сделать, не используя GET-WORD или что-то подобное в качестве прокси?


person HostileFork says dont trust SE    schedule 24.12.2014    source источник


Ответы (3)


Да, активную функцию можно «снять с охраны»! значение с особенностью DO-диалекта:

>> do probe compose [p: quote (:print)]
[p: quote make native! [[
        "Outputs a value followed by a line break."
        value [any-type!] "The value to print"
    ]]]

>> p [{Hello} {World}]                  
Hello World

Ключевым моментом здесь является специальный режим передачи аргументов, используемый для единственного аргумента QUOTE:

>> source quote
quote: make function! [[
    "Returns the value passed to it without evaluation."
    :value [any-type!]
][
    :value
]]

Этот режим передачи аргументов, невообразимо названный «получить аргументы», запрещает вычисление значения аргумента. Таким образом, в нашем конкретном случае это предотвращает «активный» характер функции! ценность, которую нужно нести.

Дополнительные сведения о режимах передачи аргументов можно найти в недавнем трактат о буквальных и получаемых аргументах, в котором сравниваются различия между Rebol 2 и Rebol 3, чтобы дать историческую перспективу.

person earl    schedule 30.12.2014
comment
Хорошо отметить. Я не подумал попробовать цитату вне скобок, и это лучше, чем другие способы, которые я делал. Хотя мой технический вопрос конкретно заключается в том, есть ли что-нибудь, что я мог бы поместить в круглые скобки в КОМПОЗИЦИЮ или снаружи, чтобы обезвредить его, поэтому ответ (по крайней мере, на то, что я хотел спросить) - нет. - person HostileFork says dont trust SE; 30.12.2014
comment
Нет, конечно, нельзя. Потому что его вооружает не КОМПОЗИЦИЯ. Для КОМПОЗИЦИИ не существует различия между активными и неактивными значениями. Это единственная особенность диалекта DO, который вы затем явно вызываете через DO. - person earl; 30.12.2014
comment
Мне кажется, что на самом деле вы хотите объединить значение в блок и хотите, чтобы это значение было неактивным по отношению к диалекту DO. В этом конкретном примере вы хотите, чтобы вы могли быть уверены, что значение всегда будет назначаться в контексте предыдущего установочного слова !. Итак, чтобы добиться этого, вы должны либо создать конструкцию, которая имеет желаемую семантику на диалекте DO, или осуществлять контроль над окружающим кодом (например, путем ввода QUOTE в правильное место, как в моем ответе). - person earl; 30.12.2014

Используйте следующий способ создания get-word, это дает вам дополнительный уровень косвенности:

>> do compose [p: (to-get-word 'print)]
>> p [{Hello} {World}]
Hello World

Если вы хотите, чтобы присвоение выполнялось с использованием формы [...] DO, вам нужно слово, назначенное анонимной функции, чтобы управлять ею пассивным способом.

Альтернативный вариант - выполнить присваивание вне составного блока:

p: first compose [(:print)]
person DocKimbel    schedule 30.12.2014
comment
Если вы хотите, чтобы назначение выполнялось с использованием формы DO [...], тогда да, вам нужно слово, назначенное анонимной функции, чтобы управлять ею пассивным способом. Альтернативный вариант - выполнить присвоение вне составного блока: p: first compose [(: print)]. - person DocKimbel; 30.12.2014

Первый вопрос: зачем вам это нужно?

Потому что он работает без компоновки.

Do [p: :print]
P 1

И без единого слова

Do [p: get first [print]]

Редактировать:

Я не понимаю последствий привязки C ++, но 'compose используется для выборочной оценки частей блока. В вашем примере вы хотите оценить деталь, но все же хотите, чтобы она не оценивалась, поэтому вам нужно остановить ее слишком раннюю оценку, например:

do compose [p1: (to get-word! 'x)] 

Если вы хотите использовать compose, а не get- / lit-word !, вы можете попробовать процитировать:

do compose [p4: get quote ( quote print)]

Внутренняя «защита цитат» выводится из-за того, что она оценивается во время компоновки, а внешняя «защищает» от «do», так что «get» может получить значение.

person ingo    schedule 26.12.2014