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

Darrell Brogdon
  • 6,843
  • 9
  • 47
  • 62

3 Answers3

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
Brett
  • 428
  • 3
  • 11
  • 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). – rgchris Aug 23 '13 at 14:10
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
Adrian
  • 741
  • 4
  • 14
kealist
  • 1,669
  • 12
  • 26
  • 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. – HostileFork says dont trust SE Aug 23 '13 at 05:14
  • 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"` – rgchris Aug 24 '13 at 00:22
3
probe do (rejoin [foo "_result_data"])

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

Xevelion
  • 859
  • 6
  • 9