this is a good style, especially the second one, which is more flexible, because it allows you to massively use all kinds of uses of external printing without any ambiguity. when using direct binding, an override of the word external-print or a change of context between two calls to make foo [] can occur and, at the end, points to two different bindings.
static character resolution
For completeness, there is a third option that does not require additional words for customization. I don't have the right name for it, feel free to suggest a better title.
This method ignores any string binding problems because you directly use the value function:
foo: context compose/deep [ ;; within foo, override print and implement using native print directly print: func [value] [ (:print) "About to print" (:print) value (:print) "Done printing" ] ]
Now for the interesting part: if you SOURCE internal print function:
>> p: get in foo 'print >> SOURCE P == p: func [value][native "About to print" native value native "Done printing"]
see how native value The seal is used directly in the body, instead of the word referring to it.
This, in fact, is perhaps the closest to what we can get in some form of compilation in pure REBOL. instead of constantly using symbols for extraction and evaluation, we can simply statically resolve them manually using the abbreviation or layout, as in the above.
pros:
It can never be hacked with any advanced and malicious binding code, i.e. even if there are no direct restrictions on PRINT words in ANY and ALL contexts, you still have a direct link to the original function in your body.
minuses:
This is a very static way of coding and not very "Rebolish".