Search code examples
rebolscopingrebol3red-lang

Can strings be 'late bound' as if they were words in the same positions?


When you LOAD a string, it biases to the user context by default:

>> f: 3

>> outside: object [
    f: 4
    getter: does [
        print reduce compose [(load "f")]
    ]
]

>> outside/getter
3

This turns out to be an artifact of LOAD's implementation, which uses intern to "Import (internalize) words and their values from the lib into the user context."

To get around this, I can save myself the inefficiency of creating a potentially-useless binding via LOAD, use TO-WORD instead, then use the object's self to rebind it:

>> m: 10

>> inside: object [
    m: 20
    getter: does [
        print reduce [(bind to-word "m" self)]
    ]
]

>> inside/getter
20

Now my question: Given the way that definitional "scoping" works, is there simply no way--present or future--for this pattern's getter-code and getter-text to both output 4 20:

>> f: 0

>> m: 0

>> ctx: context [
    f: 4

    m: 10

    both: object [
        m: 20
        getter-code: does [print [f m]]
        getter-text: does [impossible-print ["f" "m"]]
    ]
]

E.g. there is something fundamentally missing to where impossible-print can't be written?


Solution

  • As you quite rightly point out, LOAD biases to the user context. Without access to the contexts you want to bind the words (that will be loaded from "f" and "m") to, your function would indeed be impossible. Fortunately, contexts are first-class objects in Rebol, so an answer might look like this:

    f: m: 0 ctx: context [
        f: 4
        m: 10
        both: object [
            m: 20
            getter-code: does [print [f m]]
            getter-text: does [impossible-print reduce ["f" ctx "m" self]]
        ]
    ]
    impossible-print: func [vars /local r][
        r: copy []
        foreach [v c] vars [append r bind to-word v c]
        print r
    ]