Evaluating a "variable variable"
Asked Answered
S

3

5

I'm creating a dynamic variable ("Variable variable" in PHP parlance) with the following:

foo: "test1"
set to-word (rejoin [foo "_result_data"]) array 5

But how do I get the value of the resulting variable named "test1_result_data" dynamically? I tried the following:

probe to-word (rejoin [foo "_result_data"])

but it simply returns "test1_result_data".

Sixgun answered 23/8, 2013 at 3:8 Comment(0)
L
3
probe do (rejoin [foo "_result_data"])

from http://www.rebol.com/docs/core23/rebolcore-4.html#section-4.6

Lionize answered 23/8, 2013 at 3:28 Comment(1)
Bah. So obvious now that I see it. Thank you. :)Sixgun
W
8

As your example code is REBOL 2, you can use GET to obtain the value of the word:

>> get to-word (rejoin [foo "_result_data"])
== [none none none none none]

REBOL 3 handles contexts differently from REBOL 2. So when creating a new word you will need to handle it's context explicitly otherwise it will not have a context and you'll get an error when you try to set it. This is in contrast to REBOL 2 which set the word's context by default.

So you could consider using REBOL 3 code like the following to SET/GET your dynamic variables:

; An object, providing the context for the new variables.
obj: object []

; Name the new variable.
foo: "test1"
var: to-word (rejoin [foo "_result_data"])

; Add a new word to the object, with the same name as the variable.
append obj :var

; Get the word from the object (it is bound to it's context)
bound-var: in obj :var

; You can now set it
set :bound-var now

; And get it.
print ["Value of " :var " is " mold get :bound-var]

; And get a list of your dynamic variables.
print ["My variables:" mold words-of obj]

; Show the object.
?? obj

Running this as a script yields:

Value of  test1_result_data  is  23-Aug-2013/16:34:43+10:00
My variables: [test1_result_data]
obj: make object! [
    test1_result_data: 23-Aug-2013/16:34:43+10:00
]

An alternative to using IN above could have been to use BIND:

bound-var: bind :var obj
Westhead answered 23/8, 2013 at 6:39 Comment(1)
I'd strongly recommend this answer. Aside from being reflexively against using 'do for such things, there is a good balance between 'set and 'get (or 'unset).Waaf
S
5

In Rebol 3 binding is different than Rebol 2 and there are some different options:

The clumsiest option is using load:

foo: "test1"
set load (rejoin [foo "_result_data"]) array 5
do (rejoin [foo "_result_data"])

There is a function that load uses--intern--which can be used to bind and retrieve the word to and from a consistent context:

foo: "test1"
set intern to word! (rejoin [foo "_result_data"]) array 5
get intern to word! (rejoin [foo "_result_data"])

Otherwise to word! creates an unbound word that is not easy to utilize.

The third option is to use bind/new to bind the word to a context

foo: "test1"
m: bind/new to word! (rejoin [foo "_result_data"]) system/contexts/user
set m array 5
get m
Standpoint answered 23/8, 2013 at 5:10 Comment(2)
I find myself reverting to LOAD a lot in these circumstances, but is there a formulation using BIND? Sometimes you have something that might be WORD! or SET-WORD! etc, and stringifying it and LOADing it is very awkward.Lussi
As per chat discussion, one way of avoiding LOAD is to use INTERN (the source of which offers even more elemental control of a word's context). SET INTERN TO WORD! "arbitrary-word" "Something" GET INTERN TO WORD! "arbitrary-word"Waaf
L
3
probe do (rejoin [foo "_result_data"])

from http://www.rebol.com/docs/core23/rebolcore-4.html#section-4.6

Lionize answered 23/8, 2013 at 3:28 Comment(1)
Bah. So obvious now that I see it. Thank you. :)Sixgun

© 2022 - 2024 — McMap. All rights reserved.