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

World: r3wp

[!REBOL3]

Ladislav
17-May-2011
[8657]
>> f: make function! reduce [[v] body: [v + a]]
>> o: context [a: 1]
== make object! [
    a: 1
]

>> bind body o
== [v + a]
Geomol
17-May-2011
[8658]
Isn't that the same as my last attemp?
Ladislav
17-May-2011
[8659]
NO
Geomol
17-May-2011
[8660]
:) Need to think.
Ladislav
17-May-2011
[8661]
you *have to* use MAKE FUNCTION!
Geomol
17-May-2011
[8662]
Because FUNC do copy/deep. hmm is this smart?
Ladislav
17-May-2011
[8663x2]
yes
you are protected when using FUNC, while you are allowed to do what 
you want when knowing what you are doing
Geomol
17-May-2011
[8665x2]
What if ... this is radical, but try go with me ... what if block's 
content wasn't bound to any context, when the block is made? And 
then the content is just bound to a context, when and if the block 
is being evaluated (or compiled if a language does that) the first 
time. Doing it this way, words are treated just like any other value 
within the block. They don't hold any other meaning than the words 
themselves. What would the consequences be?
The same could be done with functions, as the function body is just 
a block of data, which may or may not be evaluated (or compiled).
Ladislav
17-May-2011
[8667x2]
What would the consequences be?

 - I do not know, you did not give me enough specifications to be 
 able to guess.
But, my guess is, that if done carefully, such a "change" would be 
indiscernible from the current behaviour.
Geomol
17-May-2011
[8669]
An example:

blk: [a + b]
f: func [blk /local a b] [a: 1 b: 2 do blk]
f blk

If this would work, what other consequences would that have?
Gabriele
17-May-2011
[8670]
Geomol, you want Scheme.
Geomol
17-May-2011
[8671x2]
Gab, doesn't Scheme have such syntax, we don't like?
Seem to have all the paranthesis, Lisp have.
Ladislav
17-May-2011
[8673x2]
This needs some thought, Geomol. Actual example:

f1: closure [/local a][a: 1 [a]]
f2: func [blk /local a][a: 2 do blk]
f3: func [blk /local a][a: 3 do bind blk 'a]

>> f2 f1
== 1

>> f3 f1
== 3
Now tell us, how your preferred code achieving the same result should 
look like.
Geomol
17-May-2011
[8675x2]
I wouldn't have closure, but use object instead (or context, as I 
call them), if that functionality is wanted. And block content isn't 
bound to start with, so if I write:

>> f1: [a]
>> f2: func [blk /local a] [a: 2 do blk]
>> f2 f1
== 2


because 'a' inside f1 is bound to local 'a' in f2, when evaluated. 
If I want another 'a', I could write:


>> context [a: 1 set 'f1 compile [a]]	; f1 will be a block, [a], 
where the 'a' is bound to 'a' in the context
>> f2 f1
== 1

and the last result could be achieved:

>> f3: func [blk /local a] [a: 3 do compile blk]
>> f3 f1
== 3


Calling f3 will be slower, as blk is recompiled each time. This language, 
I illustrate, isn't REBOL, but another with many similarities to 
REBOL, but with a compile function. Maybe kinda the same could be 
achieved in REBOL, if the binding rules was changed, and "compile" 
in my examples above was changed to a "rebind" function.
I need to think it through, if other unwanted consequences is the 
result of this. I'm just wondering, why it's designed as it is in 
REBOL.
Ladislav
17-May-2011
[8677x2]
I wouldn't have closure

 do I understand correctly, that you do want the programmers to enjoy 
 the benefits of having closures?
err, "do not want" is what I wanted to write
Geomol
17-May-2011
[8679]
Well, if function variables is needed, after the function is finished, 
then it can be achieved by putting the function in a context, and 
have the local vars be vars in the context instead. It's simpler, 
I think, to program.
Ladislav
17-May-2011
[8680]
It is not simpler, you just are forbidding a useful feature.
Geomol
17-May-2011
[8681]
I guess, the closure functionality could be achieved by a mezzanine 
and using object! and function! datatypes without having closure! 
datatype. I'm not an expert in closures, so I may be wrong. Are there 
more to them?
Ladislav
17-May-2011
[8682]
So, if you would not forbid the CLOSURE to be implemented as a mezzanine, 
my question remains valid.
Geomol
17-May-2011
[8683]
Is a closure a function, where the vars is in a map (or whatever 
data structure is used for an object/context) instead of on the stack?
Ladislav
17-May-2011
[8684]
You can have a look at

    source closure

in 2.7.7 or above
Geomol
17-May-2011
[8685]
I wouldn't and couldn't forbid closures, if they could be implemented 
using function! and object!, even if the language didn't have closure! 
.
Ladislav
17-May-2011
[8686x2]
In that case, as already mentioned, my example remains valid, and 
the question is, how would you want to implement that functionality.
(the above implementation does not use the object! datatype)
Geomol
17-May-2011
[8688x2]
I just noticed. Interesting! :) I need to read the source to "closure" 
closely.
Do you follow my ideas for blocks without default binding? I think, 
it could work.
Ladislav
17-May-2011
[8690]
So, my question was, how would you implement F1, F2 and F3 in your 
hypothetical language to get:

>> f2 f1
== 1

>> f3 f1
== 3
Geomol
17-May-2011
[8691x3]
It is not simpler, you just are forbidding a useful feature.


If closure! could be avoided, then the C source for the language 
is simpler. That's what I mean. If the closure functionality can 
be achieved by a mezzanine, nothing has been forbidden. Of course, 
if the language doesn't have problems with keeping the C source simple, 
a closure! datatype could be included, as it would possible be faster.
I already gave examples to do that. They were:

>> context [a: 1 set 'f1 compile [a]]
>> f2: func [blk /local a] [a: 2 do blk]
>> f2 f1
== 1
>> f3: func [blk /local a] [a: 3 do compile blk]
>> f3 f1
== 3


I haven't finished reading about CLOSURE, so maybe it can be even 
simpler.
Isn't it correct, that the CLOSURE mezzanine in R2 only work (without 
using object! in any way), because functions are already closures 
in R2?
BrianH
17-May-2011
[8694]
Nope.
Geomol
17-May-2011
[8695x4]
Yeah, it is. Else the CLOSURE mezzanine would work in R3 with R3's 
functions, and it doesn't.
Why does R2's CLOSURE parse of set-word! in the spec? Doesn't make 
sense.
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
[8706]
>> 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