Confusion on when a block gets evaluated
[1/10] from: massung::gmail::com at: 5-Mar-2006 23:38
I'm getting a tad bit confused on when REBOL decides to treat something as
code. If I open up the console and type a couple snippets of code, the
language doesn't quite work the way I expect it to (coming from Lisp). I'm
hoping some of the more experienced here can lend me a quick explanation...
:)
Here I'll show my little test in REBOL along with a Lispy counterpart to
show what I think should happen.
>> test: [ repeat i 9 [ prin i ] ]
== [ repeat i 9 [ prin i ] ]
Okay, now I have a word (test), which is bound to a list of data consisting
of words, an integer, and another list of words. Simple enough:
(setf test '(repeat i 9 (prin i))).
>> do test
123456789
Looks good. It treated the list as a block of code and executed it.
(eval test)
>> print test
123456789?unset?
Huh? Shouldn't it have just printed the list like the original assignment
return value?
(print test) -> (repeat i 9 (prin i))
I know that I can get the original list by doing:
>> get 'test ; or :test
== [ repeat i 9 [ prin i ] ]
But I just figured for the print statement, test would just be evaluated
(after all, test is just a list, evaluating the list would be an extra step,
which is what I assume is what DO does, but it seems that PRINT does it,
too)?
So, now assuming that maybe PRINT is a special case senario, I decided to
try another simple function: JOIN. I get the same "quirkyness" (well, quirky
being defined as "not what I expect :)"):
>> join "foo" test
123456789 == "foo?unset?"
>> join "foo" get 'test
123456789 == "foo?unset?"
>> join "foo" :test
123456789 == "foo?unset?"
>> join "foo" [test]
== "foorepeat i 10 prin i"
I would have expected the first to do what the last did. So, for now, I
gather that that words are evaluated (completely) before being passed on to
another function. So, to test that theory, here's my next statement:
foo: func [block] [
prin "**" do block print "**"
]
>> foo test
**123456789**
If the my hypothesis was correct, what I would have expected as output would
have been:
123456789**?unset?**
So, now I'm utterly confused. :)
Now, I'm sure there's just one tiny snippet of REB-know-how that I'm missing
(or a trivial step in the evaluation process that I'm not aware of) at the
moment that will make this all just "come together" for me. Consider me
waiting to be enlightened. :)
Thanks!
Jeff M.
--
massung-gmail.com
[2/10] from: pwawood::gmail at: 6-Mar-2006 14:09
I'm sure some of the list gurus will have a fuller explanation but this
may help:
On Monday, Mar 6, 2006, at 13:38 Asia/Kuala_Lumpur, Jeff Massung wrote:
>>> print test
> 123456789?unset?
>> print mold test
[repeat i 9 [prin i]]
>> ? mold
USAGE:
MOLD value /only /all /flat
DESCRIPTION:
Converts a value to a REBOL-readable string.
MOLD is a native value.
ARGUMENTS:
value -- The value to mold (Type: any)
Hope this gives you a start.
Regards
Peter
[3/10] from: greggirwin:mindspring at: 5-Mar-2006 23:12
Hi Jeff,
First, you're jumping into deeper water that most newbies, so it's
expected that you'll hit some confusing twists and turns (wait until
you have a local series value in a function! :). It should all make
sense before long and, hopefully, whatever I do to confuse you further
will be addressed by somebody else. :)
>>> test: [ repeat i 9 [ prin i ] ]
JM> == [ repeat i 9 [ prin i ] ]
The main thing to note about this snippet is that REPEAT will return
the last value evaluated in the body block. In this case, that value
is a block containing the result of the PRIN function, which is an
unset! value.
>>> do test
JM> 123456789
Notice that there's no "==" since the result of DOing the block was
unset. Try REDUCE to see the result:
>> reduce test
123456789== [unset]
or try this:
>> print mold do test
123456789** Script Error: mold is missing its value argument
** Near: print mold do test
Now, you can see that DOing the test returns a single unset value,
which PRINT can't consume (it's not a real value...until Ladislav
jumps in to explain that it is, sort of, sometimes, but maybe it
shouldn't be, because it's confusing ;).
>>> print test
JM> 123456789?unset?
Now, you're telling PRINT to print the block *containing* the unset
value returned by evaluating 'test ([unset]). e.g.
>> print [prin '.]
.?unset?
PRINT evaluates on its own, so you don't have to take the extra step
of REDUCE-ing blocks you give to it.
Same issue for JOIN, but you also get into how values are coerced when
they are joined. The main thing is that JOIN is evaluating the block
too.
>>> join "foo" test
JM> 123456789 == "foo?unset?"
That's like this:
>> b: reduce [prin '.]
.== [unset]
>> join "foo" b
== "foo?unset?"
Here JOIN evaluates the block *containing* 'test, which produces a
block that is then coerced to a string, because that's what it is
being JOINed to.
>>> join "foo" [test]
JM> == "foorepeat i 10 prin i"
e.g.
>> form test
== "repeat i 9 prin i"
JM> foo: func [block] [
JM> prin "**" do block print "**"
JM> ]
>>> foo test
JM> **123456789**
JM> If the my hypothesis was correct, what I would have expected as output would
JM> have been:
JM> 123456789**?unset?**
The result of DO is being discarded. The first PRIN call consumes
**
(and nothing more), same for the last PRINT; DO BLOCK returns a
result that isn't used at all. PRINT and PRIN consume a single
argument, be it a block, string, or something else.
Does any of that make sense?
-- Gregg
[4/10] from: pwawood:gmai:l at: 6-Mar-2006 14:26
Jeff
Ladislav Mecir's excellent "essays" may help, particularly
http://en.wikibooks.org/wiki/REBOL_Programming/Advanced/Interpreter
You can access Ladislav's other work via
http://www.fm.vslib.cz/~ladislav/rebol/
Regards
Peter
On Monday, Mar 6, 2006, at 13:38 Asia/Kuala_Lumpur, Jeff Massung wrote:
[5/10] from: lmecir::mbox::vol::cz at: 6-Mar-2006 8:33
Gregg Irwin napsal(a):
>Hi Jeff,
>First, you're jumping into deeper water that most newbies, so it's
<<quoted lines omitted: 26>>
>123456789** Script Error: mold is missing its value argument
>** Near: print mold do test
or this:
type? do test ; == unset!
>Now, you can see that DOing the test returns a single unset value,
>which PRINT can't consume (it's not a real value...until Ladislav
>jumps in to explain that it is, sort of, sometimes, but maybe it
>shouldn't be, because it's confusing ;).
>
LOL
...
maybe a short explanation will suffice:
reduce [1 + 2 3 + 4] ; == [3 7]
form [1 + 2 3 + 4] ; == "1 + 2 3 + 4"
form reduce [1 + 2 3 + 4] ; == "3 7"
You should be aware of the fact, that Print reduces a block it obtains.
You will find out, that there is a couple of functions in Rebol that
reduce their block argument in addition to Print and Join. (e.g. Repend,
c.f. source join)
-L
[6/10] from: massung:gmai:l at: 6-Mar-2006 9:13
Are these functions documented?
I thank everyone for their replies. As per the ?unset?, that wasn't really
bothering me, it was more a question of when 'test' was being evaluated
(which is why I was using PRINT). I gather from the responses (especially
this one) that certain functions just have an inherent "DO" inside them.
That's fine as long as I know which ones they are. :-)
Thanks again!
Jeff M.
--
massung-gmail.com
On 3/6/06, Ladislav Mecir <lmecir-mbox.vol.cz> wrote:
[7/10] from: tim-johnsons:web at: 6-Mar-2006 17:07
* Peter Wood <pwawood-gmail.com> [060305 21:34]:
> Jeff
>
> Ladislav Mecir's excellent "essays" may help, particularly
> http://en.wikibooks.org/wiki/REBOL_Programming/Advanced/Interpreter
>
> You can access Ladislav's other work via
> http://www.fm.vslib.cz/~ladislav/rebol/
You can also use the rebol word
unset?
which is a predicate that checks to see if a value
is unset.
example:
>> unset? print "yes"
yes
== true
This is useful when using a loop to accumulate values. You can use to
first check to see something is unset before adding it to whatever you
are using to accumulate the values.
I generally use unset? inside of small functions, using it by itself,
has caused me some heartburn in the past.
example:
=s: func [
"Check for unset or none values and return an empty string if found"
v [any-type!]
][
either unset? get/any 'v
[""]
[any[v ""]]
] ;; end function
In the interpreter window, enter
>> help unset?
;; and
>> help get
--
Tim Johnson <tim-johnsons-web.com>
http://www.alaska-internet-solutions.com
[8/10] from: pwawood:gm:ail at: 7-Mar-2006 11:19
Jeff
I find the Rebol function dictionary,
http://www.rebol.com/docs/dictionary.html , the best source of
documentation followed by the topic index at
http://www.rebol.org/cgi-bin/cgiwrap/rebol/ml-topic-index.r.
Regards
Peter
On Monday, Mar 6, 2006, at 23:13 Asia/Kuala_Lumpur, Jeff Massung wrote:
[9/10] from: massung::gmail::com at: 6-Mar-2006 21:36
Thanks! I use the dictionary all the time, but didn't know about the topic
index. Great!
Jeff M.
--
massung-gmail.com
On 3/6/06, Peter Wood <pwawood-gmail.com> wrote:
[10/10] from: robert::muench::robertmuench::de at: 7-Mar-2006 13:57
On Tue, 07 Mar 2006 04:19:56 +0100, Peter Wood <pwawood-gmail.com> wrote:
> the best source of documentation followed by the topic index at
> http://www.rebol.org/cgi-bin/cgiwrap/rebol/ml-topic-index.r.
Hi, I must have missed something over the years but this is pretty cool.
Thanks for pointing it out.
--
Robert M. M=FCnch
Mobile: +49 (177) 245 2802
http://www.robertmuench.de
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted