Passing word in a block as an argument
[1/7] from: tim:johnsons-web at: 9-Feb-2003 17:53
Hello Rebols:
I'd like to be able to initialize a block of words,
pass that block to a function and then get the values
in the words by referencing the names of the words.
Here's an example of what I'm trying to do, just doesn't
work: :-(
rebol[]
test: func[e[block!]][
?? e
print get 'a
]
blk: [1 2 3 4 5 6 7 8 9 10 11 12]
cols: [a b c d]
foreach :cols blk[
?? a ?? b ?? c ?? d
test cols
]
; and here's the <sigh>results</sigh>:
>> do %test.r
Script: "Untitled" (none)
a: 1
b: 2
c: 3
d: 4
e: [a b c d]
** Script Error: a has no value
** Where: test
** Near: print get 'a
So: how do I get the values of a,b,c and d?
TIA
--
Tim Johnson <[tim--johnsons-web--com]>
http://www.alaska-internet-solutions.com
http://www.johnsons-web.com
[2/7] from: tim:johnsons-web at: 9-Feb-2003 18:35
* Tim Johnson <[tim--johnsons-web--com]> [030209 18:23]:
> Hello Rebols:
> I'd like to be able to initialize a block of words,
<<quoted lines omitted: 25>>
> ** Near: print get 'a
> So: how do I get the values of a,b,c and d?
I'm sort of answering my own question here,
but it raises another. I can use forskip
with the desired result, as in:
forskip blk length? cols[
set cols blk
?? a ?? b ?? c ?? d
test cols
]
; so why is there a difference?
--
Tim Johnson <[tim--johnsons-web--com]>
http://www.alaska-internet-solutions.com
http://www.johnsons-web.com
[3/7] from: al:bri:xtra at: 10-Feb-2003 17:26
Tim wrote:
> So: how do I get the values of a,b,c and d?
>> blk: [1 2 3 4 5 6 7 8 9 10 11 12]
== [1 2 3 4 5 6 7 8 9 10 11 12]
>> cols: [a b c d]
== [a b c d]
>> map blk func cols [print [a b c d]]
1 2 3 4
5 6 7 8
9 10 11 12
Use 'map. :)
Andrew Martin
ICQ: 26227169 http://valley.150m.com/
[4/7] from: greggirwin:mindspring at: 9-Feb-2003 21:55
Hi Tim,
TJ> I'd like to be able to initialize a block of words,
TJ> pass that block to a function and then get the values
TJ> in the words by referencing the names of the words.
The words are bound to the context of the FOREACH block so your other
code can't see them. If you just declare them at the top of your script,
so they're global, it will prevent the error. E.g.
a: b: c: d: none
But it still isn't looking at the values for the words as bound to the
FOREACH loop. If you define your function inside your loop, it will
work, but that's probably not what you want to do. :) E.g.
blk: [1 2 3 4 5 6 7 8 9 10 11 12]
cols: [a b c d]
foreach :cols blk [
test: func [e[block!]] [
?? e
print get 'a
]
?? a ?? b ?? c ?? d
test bind cols 'self
]
Beyond that, my poor tired brain isn't aware of a simple solution for
binding to the loop context. I'm sure someone else will chime in and
show us both how easy it is. :)
-- Gregg
[5/7] from: joel:neely:fedex at: 9-Feb-2003 23:04
Hi, Tim,
In a nutshell, the difference is that FOREACH creates a new context
for its word (or block of words) argument. Consider this:
>> i: "nobody home"
== "nobody home"
>> foreach i [0 2 4 6 8] [print i]
0
2
4
6
8
>> print i
nobody home
The I that is used inside the FOREACH isn't the same I as was set
and printed outside that expression. Now see below:
Tim Johnson wrote:
> ... I can use forskip with the desired result, as in:
> forskip blk length? cols[
<<quoted lines omitted: 3>>
> ]
> ; so why is there a difference?
Here the body of the loop uses SET to set the words, therefore
making them global, and therefore accessible to TEST, which is
trying to get a global word via 'A . To see this in more detail,
we can change your original code to contain one extra line, as
follows:
>> a: b: c: d: "Global!"
== "Global!"
>> test: func[e[block!]][
[ ?? e
[ print get 'a
[ ]
>> blk: [1 2 3 4 5 6 7 8 9 10 11 12]
== [1 2 3 4 5 6 7 8 9 10 11 12]
>> cols: [a b c d]
== [a b c d]
>> foreach :cols blk[
[ ?? a ?? b ?? c ?? d
[ test cols
[ ]
a: 1
b: 2
c: 3
d: 4
e: [a b c d]
Global!
a: 5
b: 6
c: 7
d: 8
e: [a b c d]
Global!
a: 9
b: 10
c: 11
d: 12
e: [a b c d]
Global!
This shows (clearly, I hope!) that the A B C and D *inside* the
FOREACH loop aren't the same as any global variables that exist
already (and TEST is trying to see a global A as mentioned above).
-jn-
[6/7] from: carl::cybercraft::co::nz at: 10-Feb-2003 19:26
On 10-Feb-03, Tim Johnson wrote:
> * Tim Johnson <[tim--johnsons-web--com]> [030209 18:23]:
>> Hello Rebols:
<<quoted lines omitted: 37>>
> ]
> ; so why is there a difference?
It's a binding, context problem. foreach words are local to the
foreach block, so your test function doesn't know about them when
it's called. With your fix above though, you're making a, b, c & d
global words, so test does know of them.
I don't know the correct solution to get the foreach approach to work,
but it'll use bind I assume...
>> ? bind
USAGE:
BIND words known-word /copy
DESCRIPTION:
Binds words to a specified context.
BIND is a native value.
ARGUMENTS:
words -- A block of words or single word. (Type: block word)
known-word -- A sample word from the target context. (Type: word)
REFINEMENTS:
/copy -- Deep copies block before binding it.
Online docs and examples here...
http://www.rebol.com/docs/words/wbind.html
Despite having success with bind occasionally, I've never really got
the hang of it, so I'll leave others to attempt a proper
explanation. Their solution may look something like this...
foreach :cols blk[
?? a ?? b ?? c ?? d
bind something something
test cols
]
or it may not... ;-)
Hopefully this puts you on the right track, anyway.
--
Carl Read
[7/7] from: al:bri:xtra at: 10-Feb-2003 19:49
Tim wrote:
> So: how do I get the values of a,b,c and d?
I get a sense of Deja Vu here. I'm sure that we answered this question some
months ago? :-/
Andrew Martin
ICQ: 26227169 http://valley.150m.com/
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted