Context misery
[1/8] from: gjones05::mail::orion::org at: 5-Jun-2001 8:58
From: "Joel Neely"
...
> (Without going into deep and
> opaque waters, just remember that
> there can be *many* words
> whose names are spelled the same!)
...
snickering out loud!
--Scott Jones
[2/8] from: ptretter:charter at: 5-Jun-2001 10:27
Not sure I know exactly what you want to do but here is my approach I use
for assignment of DCC ports in an irc script I made:
REBOL []
myfunc: func ["Creates a dynamic variable and sets to a value in /local
temp"
string [string!] ; string that will contain the new 'word to be assigned
/local value temp
][
value: [1 2 3]
temp: make set-word! string
mold temp :value
]
[3/8] from: sanghabum:aol at: 5-Jun-2001 12:33
Thanks Joel and all for the various replies,
Maybe I'm thinking more like an Imperial stormtrooper than a Rebol, but the
Rebol model for contexts and global/local variables seems neither simple nor
straightforward, as several previous threads have suggested.
> Unless it is necessary, evaluating strings is generally not
> a good practice. Evaluating strings is less efficient than
<<quoted lines omitted: 4>>
> at best, and a potential source of highly subtle bugs at
> worst.
Thanks for TFM ref. I'd completely failed to R that part. Sounds like we've
both learnt from experience here.
> Why? If you can describe what you're trying to accomplish
> here, perhaps some of the old hands can offer some alternatives
> that won't be so tricky to deal with. For example...
Well, the moment, has passed. I coded what I wanted in another way--the code
involved builds a data update layout dynamically from a CSV file: first row
is the field names, subsequent rows the data, and it was generating global
variables from the field names. It seems like a good idea at the time.
Thanks again,
--Colin.
[4/8] from: carl:rebol at: 5-Jun-2001 10:02
Ah, but what are you really trying to do?
From your example, the variable is not really dynamic
(because you use exactly the string you pass in for it.)
So, just pass the name as a name.
myfunc: func [name] [set name copy [1 2 3]]
myfunc 'example
print example
That will allow 'example to be part of any context,
including objects and locals to functions.
You can also use the shorthand:
myfunc: func ['name] [set name copy [1 2 3]]
myfunc example
print example
And, if you need "code" as part of it:
myfunc: func [name code] [set name do code]
myfunc 'example [1 + 2]
print example
You get the idea,
-Carl
[5/8] from: sanghabum:aol at: 5-Jun-2001 7:13
Hi there,
Could someone with a better grasp of context than me explain why this won't
work?---I think the problem is using a local variable in a DO:
myfunc: func [BlockName [string!]
/local aa bb][
aa: copy [1 2 3]
bb: join BlockName ": copy aa"
print ["aa is " mold aa]
print ["bb is " mold bb]
do bb
]
When I run it I get:
>> myfunc "myblock"
aa is [1 2 3]
bb is "myblock: copy aa"
** Script Error: aa has no value
** Where: myfunc
** Near: myblock: copy aa
>>
All I'm trying to do is create a variable dunamically based on a name passed
to a function.
Thanks!
Colin.
[6/8] from: joel:neely:fedex at: 5-Jun-2001 7:38
Hi!
[Sanghabum--aol--com] wrote:
> Hi there,
> Could someone with a better grasp of context than me explain why this won't
<<quoted lines omitted: 15>>
> ** Near: myblock: copy aa
> >>
The REBOL/Core Users' Guide says (page 3-11):
Unless it is necessary, evaluating strings is generally not
a good practice. Evaluating strings is less efficient than
evaluating blocks, and the context of words in a string is
not known.
I strongly recommend taking that advice to heart! Trying to
construct source code strings that DO what you want is tricky
at best, and a potential source of highly subtle bugs at
worst.
That said, when you define BB using the expression
bb: join BlockName ": copy aa"
and then DO that string, REBOL has no idea that you intend for
the two-letter token "aa" in the string to indicate the LOCAL
word AA in the current function. (Without going into deep and
opaque waters, just remember that there can be *many* words
whose names are spelled the same!)
To get the value that's in your local variable to be the
value stored in the (possibly!) new variable named by the
BLOCKNAME parameter, you will need to force evaluation of
your local AA and then use that result to construct the
string. One possible (and possibly clumsy) way to do this is:
>> myfunc: func [BlockName [string!] /local aa bb] [
[ aa: copy [1 2 3]
[ bb: rejoin [BlockName ": copy " mold aa]
[ print ["aa is " mold aa]
[ print ["bb is " mold bb]
[ do bb
[ ]
>> myfunc "myblock"
aa is [1 2 3]
bb is "myblock: copy [1 2 3]"
== [1 2 3]
>> myblock
== [1 2 3]
>>
But *please* remember the old joke: "Doc, it hurts when I
do this!" "Well, then don't do that!" ;-)
> All I'm trying to do is create a variable dunamically based
> on a name passed to a function.
>
Why? If you can describe what you're trying to accomplish
here, perhaps some of the old hands can offer some alternatives
that won't be so tricky to deal with. For example...
You can think of REBOL contexts as being like mini-dictionaries
that map strings (the word names) to other values. (Now you
see why different contexts can have words with the same name!)
If you're trying to keep up with some data and you *really*
need to associate values with names you can't know in advance,
you could build your own "dictionary" as follows:
fw: make object! [
storage: copy []
learn: func [
token [string!] value [any-type!]
/local where
][
either none? find storage token [
append storage reduce [token value]
][
change/only storage value
]
]
fetch: func [token [string!]] [
select storage token
]
]
>> fw/learn "myblock" copy [1 2 3]
== ["myblock" [1 2 3]]
>> fw/learn "yourblock" copy [4 5 6]
== ["myblock" [1 2 3] "yourblock" [4 5 6]]
>> fw/learn "anyblock" [9 8 7]
== ["myblock" [1 2 3] "yourblock" [4 5 6] "anyblock" [9 8 7]]
>> fw/fetch "myblock"
== [1 2 3]
This is just a Q&D sample; an obvious improvement is to have
LEARN return the VALUE argument as its result to facilitate
embedding in larger expressions. Implementing that, and any
other improvements, is left as an exercise to the reader! ;-)
Hope this helps!
-jn-
------------------------------------------------------------
Programming languages: compact, powerful, simple ...
Pick any two!
joel'dot'neely'at'fedex'dot'com
[7/8] from: lmecir:mbox:vol:cz at: 5-Jun-2001 15:02
Hi Colin,
try this instead:
myfunc: function [
BlockName [word!]
] [aa bb] [
aa: copy [1 2 3]
bb: reduce [to set-word! BlockName 'copy 'aa]
print ["aa is " mold aa]
print ["bb is " mold bb]
do bb
]
Cheers
Ladislav
[8/8] from: sanghabum:aol at: 5-Jun-2001 18:07
Hi Carl,
> Ah, but what are you really trying to do?
> From your example, the variable is not really dynamic
<<quoted lines omitted: 3>>
> myfunc 'example
> print example
Well, it's dynamic insofar as I don't know what it is when the program
starts. It is read as a string from a file. So (the original intention was)
it goes into the function as a string, and comes out as a global variable. So
I can use your function like this:
myfunc to word! FieldName
where Fieldname is the string.
And that solves the original problem. Thanks!
While I've got your attention, can I just say that I really really like this
language! Thank you all for creating it.....I think my main problem is trying
to run before I can walk, and often running straight into brick walls before
donning the right head gear.
--Colin.
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted