2

In the following code, we can assign the result of a GET-WORD to p through a SET-WORD, and then use it under the new name:

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

But what if you are using COMPOSE, and you find a situation such as this?

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

That gives an error:

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

So it's like function values in a block are "live" when seen in the interpreter...whether they were fetched as an evaluative result or not. (It would seem they should be inert unless fetched or applied somehow, otherwise such assignments are not possible from within a COMPOSE or similar.)

It seems you have to quote a get-word, such as:

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

That could do the trick to make p the print function. But can you do it without going through a GET-WORD or similar as a proxy?

3 Answers3

3

Yes, you can "disarm" the active function! value with a feature of the DO-dialect:

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

They key here is the special argument passing mode used for the single argument of QUOTE:

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

This argument passing mode, unimaginatively called "get arguments", inhibits evaluation of the argument value. So in our particular case, it prevents the "active" nature of the function! value to come to bear.

For more details about argument passing modes, you might want to have a look at this recent treatise about literal and get arguments, which compares the differences between Rebol 2 and Rebol 3 to give a historical perspective.

earl
  • 40,327
  • 6
  • 58
  • 59
  • Good to point out. I hadn't thought to try the quote outside of the parentheses, and that's better than the other ways I was doing. Though my technical question is specifically if there's anything I could put inside the parentheses of the COMPOSE vs. outside to disarm it, so the answer (at least to what I meant to ask) is "no". – HostileFork says dont trust SE Dec 30 '14 at 13:29
  • 1
    No, you certainly cannot. Because it's not the COMPOSE that "arms" it. For COMPOSE, active vs inactive values does not exist as a distinction. That's _only_ a peculiarity of the DO dialect, which you then explicitly invoke via DO. – earl Dec 30 '14 at 13:32
  • 1
    It seems to me, that what you actually want to do, is splice a value into a block and want that value to be "inactive" in respect of the DO dialect. In this particular example, you want that so that you can be sure that the value will always be assigned in context of a preceding set-word!. So to achieve that, you have to _either_ create a construct that has the desired semantics in the DO dialect, _or_ exert control over the surrounding code (such as by injecting QUOTE in the proper place, as in my answer). – earl Dec 30 '14 at 13:58
2

Use the following way to create the get-word, it buys you an additional level of indirection:

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

If you want the assignment to be done using a DO [...] form, then you need a word assigned to the anonymous function in order to manipulate it in a passive way.

An alternative option is to do the assignment outside of the composed block:

p: first compose [(:print)]
DocKimbel
  • 3,127
  • 16
  • 27
  • If you want the assignment to be done using a DO [...] form, then yes, you need a word assigned to the anonymous function in order to manipulate it in a passive way. An alternative option is to do the assignment outside of the composed block: **p: first compose [(:print)]**. – DocKimbel Dec 30 '14 at 09:07
0

The first question is what do you need this for?

Because it works without compose.

Do [p: :print]
P 1

And without a get-word

Do [p: get first [print]]

Edit:

I don't understand the implications for the C++ binding, but 'compose is used to evaluate parts of a block selectively. In your example you want to evaluate a part, but still want it not being evaluated, so you need to stop it from being evaluated too early, for example:

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

If you want to use compose, and no get-/lit-word!, you could try quote:

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

The inner 'quote guards 'print from being evaluated during compose, the outer one guards durng the 'do, so that 'get can get the value.

ingo
  • 521
  • 3
  • 7
  • It affects value assignments of functions in [the C++ binding](https://github.com/hostilefork/rencpp/blob/09dca1a36737a2445de62b2b05ed10019a18e436/examples/extension-test-1.cpp). I phrased it here more generally if you are composing something and want the result to go into an assignment. – HostileFork says dont trust SE Dec 26 '14 at 00:30
  • I'm still not sure I understand the real question, but I've edited my original answer. – ingo Dec 26 '14 at 13:34