r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[!REBOL3]

Geomol
17-May-2011
[8697x2]
parse *for* set-word!
It would be easier in R2 to create CLOSURE this way:

>> closure: :func
>> f: closure [a b] [[a + b]]
>> do f 1 2
== 3
BrianH
17-May-2011
[8699]
R3 has two context types: object and function. R2 only has one context 
type: object. This is why you can create a persistent context using 
a function in R2, while you can't in R3.
Geomol
17-May-2011
[8700]
I know. So functions are closures in R2.
BrianH
17-May-2011
[8701x4]
R2's functions have object contexts that are reused on subsequent 
calls, so you can't count on the context to persist if the function 
is called again. That is the difference between R2's functions and 
R3's closures.
Creating a new context every time the function is called is the whole 
point to closures, the only reason that you would use them instead 
of a function.
The PARSE statement in CLOSURE creates the code for a call to a function 
that the resulting outer function creates every time it is called. 
If you want to understand what the PARSE statement is doing, make 
a function with CLOSURE and look at its source.
Why does R2's CLOSURE parse of set-word! in the spec?


The set-word! in the PARSE spec is a special-case, so that set-words 
aren't counted in the set word any-word! portion of the next alternate 
in the rule. Set-words in function specs are keywords for special 
purposes in function creation (just return: in R2), they don't refer 
to parameters, and the other word types are collected as parameters.
Geomol
17-May-2011
[8705]
Creating a new context every time the function is called is the whole 
point to closures

And R2 is not doing this with its functions?
BrianH
17-May-2011
[8706x3]
>> f: func [a] ['a]
>> w1: f 1
== a
>> w2: f 2
== a
>> get w1
== 2    ; note that the value has changed

>> c: closure [a] ['a]
>> w1: c 1
== a
>> w2: c 2
== a
>> get w1
== 1    ; note that the value persists
>> source c

c: func [a][native action function! [[throw] :a [any-type!]] ['a] 
a]
Those first three values in the source of C are direct references 
to the functions DO, MAKE and the type function!, so there are no 
word conflicts.
Geomol
17-May-2011
[8709]
(just return: in R2)

Can you create a function with a return: set-word! in the spec?
BrianH
17-May-2011
[8710]
The type is reserved for future use. If it's an error, the MAKE function! 
at the end will catch it.
Geomol
17-May-2011
[8711x2]
Where did you get this info?
Interesting example, you gave with W1 and W2. Funny how recursive 
functions works then!?
BrianH
17-May-2011
[8713]
From Carl, years ago. Set-words in function specs are supposed to 
be used for more in R3 later.
Geomol
17-May-2011
[8714]
Did Carl write about the set-word! in function spec anywhere?
BrianH
17-May-2011
[8715x2]
There is a bug in CLOSURE though. This line:
    insert tail bdy to word! :word

will have problems with some datatypes. I'll fix it for the next 
version.
Set-words in function specs are used by the routine! type now.
Geomol
17-May-2011
[8717]
It's not so good and almost sad, that Carl used so much energy to 
include new stuff (like also routine!) instead of concentrating on 
making the old stuff (from R2) work correctly first.
GrahamC
17-May-2011
[8718]
And now he's burnt out?
BrianH
17-May-2011
[8719]
R2 has routine!, R3 doesn't.
Geomol
17-May-2011
[8720]
I would expect anybody to be burnt out when taking that approach 
to things. It's like building a skyscraper by loosely make all floors 
first, then trying ot fix everything. Better to get first floor solid 
before moving on.
BrianH
17-May-2011
[8721]
Recursive functions in R2 work by pushing the block of values in 
a context onto a stack during the recursive calls, then popping them 
off on return. In R2, function contexts are stack-relative, which 
makes word dereferencing 27% slower relative to object contexts, 
but function calls in general faster. Closures bind to object contexts, 
which are recreated with every function call.
Geomol
17-May-2011
[8722]
R2 has routine! from what version of R2?
BrianH
17-May-2011
[8723]
Any version with library support.
Geomol
17-May-2011
[8724]
:) And when did library support get in?
BrianH
17-May-2011
[8725x2]
I don't know, a little less than 10 years ago?
Whenever /View/Pro or /Command was invented.
Geomol
17-May-2011
[8727x2]
Ok, that's old then.
Does routine! work flawlessly?
BrianH
17-May-2011
[8729]
Don't know. R2's library support was never flexible enough for me 
to be able to use. Others seem to be able to make it work.
Geomol
17-May-2011
[8730x3]
RAMBO holds 15 tickets, when searching for "routine!". 9 are Reviewed, 
6 Built.
Oldest dated 20-Oct-2004, newest 18-Apr-2010.
I would say, we desperately needs a replace for REBOL, so all the 
man-years of work, people have done in creating software with it, 
isn't wasted. It's not all wasted, nomatter what happens, as many 
things work and is used, but many would like to move on, I guess.
BrianH
17-May-2011
[8733x2]
I prefer to think of a combination of R3 and Red as potentially being 
that replacement, but other people may have other plans.
Never mind what I said about the bug in CLOSURE. It's not a bug.
Gabriele
18-May-2011
[8735]
Geomol: syntax is insignificant, translating from one to another 
is easy.


Anyway, the problem with a Scheme using REBOL-like syntax is that 
you give up dialecting (static binding is pretty important for that).
Geomol
19-May-2011
[8736]
I found an bad effect of not binding words in blocks at all, before 
the block is evaluated. Functions like LOOP take 2 args, count and 
block. By not binding the block content before it's evaluated, the 
count arg local to LOOP is found, if a count var is used in the block.

So I guess the REBOL early bind of words is better.
BrianH
19-May-2011
[8737]
LOOP's count arg is not bound to the block of code, so it is not 
local. This is why LOOP is the fastest loop. REPEAT is the version 
of LOOP with a bound local arg.
Geomol
19-May-2011
[8738]
The backside of REBOL's binding is all the unset words, we start 
out with. R2 has 1865 unset words registered in system/words. They 
can be seen with this code:


 foreach w first system/words [if unset? get/any to lit-word! w [prin 
 [w ""]]]
Maxim
20-May-2011
[8739x2]
but doesn't this list disapear with the new multi-level booting of 
R3?  since those words are now not sent in the user context but stay 
in their lower levels?
but its not a big deal... unset words are created just by loading 
any word in a block.  it just means, I've seen this symbol before 
and it now has its reserved number in the word list/hash table. any 
future reference will reuse the same word id (number).
Geomol
20-May-2011
[8741x5]
Yeah, they will be reused. But the way, REBOL do it, if you have 
an application, that do a lot of block parsing for example, with 
new words coming in all the time, then that global context will just 
grow and grow. In reality, it will probably come to an end, as there 
are a finite number of words in a human language, if that's what 
being parsed.


If words were not bound by just being loaded, but only when evaluated 
(or compiled, if that's the case), then parsing blocks would not 
produce any unset! words in the global context. But a consequence 
of this is, that blocks of code being sent to a function (like LOOP), 
will be able to see the words local to that function, unless the 
block is first bound outside the function, like

	count: 1
	loop 10 bind [print count] 'count
, which will then print the number 1 10 times.
I just realized, the global context in R2 and the user context in 
R3 (system/contexts/user) wont grow by this:

to block! "some_random_word"

but it will grow by this:

[some_random_word]
The consequence:

>> count: 1
>> blk: [print]
>> append blk to block! "count"
== [print count]
>> do blk
** Script Error: count word has no context

I wonder, why TO BLOCK! works like this.
Maybe that's the way to have blocks of lots of words, which are just 
data and not bound to anything.
So to not exhaust the global context (if that's a problem), we should 
parse like this:


parse to block! "a few words and then some more" to block! "'a 'few 
'words to end"
Rebolek
20-May-2011
[8746]
AFAIK, to block! doesn't do binding, you have to LOAD the block.