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

World: r3wp

[Core] Discuss core issues

Anton
30-Apr-2006
[4235x3]
Just getting the function body.
>> A: context [a: 1 b: 2 c: 3]
>> storage: context [list-words: does [probe first self]]
>> storage/list-words
[self list-words]
== [self list-words]
>> bind second get in storage 'list-words A
== [probe first self]
>> storage/list-words
[self a b c]
== [self a b c]
read as: "bind the body of list-words to A"
Robert
30-Apr-2006
[4238]
Ok... now I think I got it. I was always trying to bind the WHOLE 
function, not only the body...
Anton
30-Apr-2006
[4239x4]
Yes, bind needs a block! value, not a function!
A function! is a more complex value, which contains a spec and a 
body.
You wouldn't want to bind the whole function, which would probably 
imply binding its spec block as well, since that would unlink the 
argument spec block relative to the body block.
Although, now that I think about it, that *could* be useful in some 
circumstance, maybe.... Many functions with similar argument lists 
could share a context.
Robert
30-Apr-2006
[4243]
ok. Thanks a lot.
Anton
30-Apr-2006
[4244]
no problem..
Robert
30-Apr-2006
[4245x3]
I think I can bind a bunch of functions as well, right?
I mean in one step.
So for example I specify a block of function names, that I want to 
bind.
Anton
30-Apr-2006
[4248]
You could append each function's body block to a single, large block. 
Then bind that.
Robert
30-Apr-2006
[4249]
And it will keep it's link to the original function spec?
Anton
30-Apr-2006
[4250x2]
blk: [] foreach func funcs [append blk second :func]  bind blk ctx-A
Yes, remember it's possible for same-named but differently-bound 
words to coexist together in a block.
Robert
30-Apr-2006
[4252]
Yes, but second FUNC doesn't return the function word. So where is 
this link kept? Or is the reference to the func body bound?
Anton
30-Apr-2006
[4253x3]
example:
>> blk: reduce [in system 'options in face 'options]
== [options options]
>> type? get blk/1
== object!
>> type? get blk/2
== none!
Are you talking about the words you have set to function values ? 
eg:   my-word: func [][]
Each word has a single value slot (per context).
Robert
30-Apr-2006
[4256]
If I'm binding SECOND FUNC the body's reference is used, so this 
particular block is bound. Not a copy.
Anton
30-Apr-2006
[4257]
Correct.
Robert
30-Apr-2006
[4258x2]
Ok.
The 'blk part doesn't work. I get an error for SECOND
Anton
30-Apr-2006
[4260x13]
Did you put function! values into the funcs input block ?
eg:
>> my-func: func [arg][print arg]
>> funcs: reduce [:my-func]
>> type? first funcs
== function!
Hmm... it's not working....
It doesn't look as simple operation as I thought...
That's weird. When you insert the function body into another block 
for binding it doesn't work. These two examples are not producing 
the same result:
>> ctx-A: context [a: 60]
>> my-func: func [][a: 5]
>> bind second :my-func ctx-A
== [a: 5]
>> ?? ctx-A
ctx-A: make object! [
    a: 60
]
>> my-func
== 5
>> ?? ctx-A
ctx-A: make object! [
    a: 5
]
>> ctx-A: context [a: 60]
>> my-func: func [][a: 5]
>> blk: [] append blk second :my-func
== [a: 5]
>> bind blk ctx-A
== [a: 5]
>> ?? ctx-A
ctx-A: make object! [
    a: 60
]
>> my-func
== 5
>> ?? ctx-A
ctx-A: make object! [
    a: 60
]
Insert copies the words into the block unbound from their original 
context.
Ok, so we can do this instead:
foreach func funcs [bind second :func ctx-A]
No reason for that not to work.
Yes, that works:
>> ctx-A: context [a: none]
>> f1: does [a: 1]
>> f2: does [a: 2]
>> foreach func reduce [:f1 :f2][bind second :func ctx-A]
== [a: 2]
>> ?? ctx-A
ctx-A: make object! [
    a: none
]
>> f1
== 1
>> ?? ctx-A
ctx-A: make object! [
    a: 1
]
>> f2
== 2
>> ?? ctx-A
ctx-A: make object! [
    a: 2
]
Robert
30-Apr-2006
[4273x3]
This stuff is always really tricky.
Ok, thanks a lot. That's stuff I'm really going nuts by. I think 
I will collect all kind of examples and publish them.
A BIND how-to, that not only explains what's going on but shows examples, 
examples, examples is what we need.
BrianH
30-Apr-2006
[4276]
Ladislav's Bindology article might help. I think it's on rebol.org...
Robert
30-Apr-2006
[4277x2]
His article is good, but only for gurus to follow.
Nothing for people getting into first touch with BIND.
BrianH
30-Apr-2006
[4279x3]
I actually think that your best bet here is to pass the context you 
will be saving to the saving function as a parameter, like your original 
example  storage/save-record context-to-save  or if you really want 
to delegate you can assign the function as a member of context-to-save 
and call it like  context-to-save/save-record context-to-save , but 
then you are changing the context you are saving wih saving overhead. 
REBOL does direct delegation by default, rather than mixin delegation 
like Delphi, because REBOL doesn't pass the object reference as a 
hidden parameter like object-oriented languages do. Rebinding your 
function body every time would be time-consuming and either non-recursion-safe 
(bind) or consume a lot of memory (bind/copy) - just passing the 
context as a parameter would be quicker.
Also, you could have some conflict with names in both the storage 
context and context-to-save that could cause the block you are rebinding 
to accidently lose its meaning in unexpected ways.
Not that learning about bind wouldn't be fun...
Robert
1-May-2006
[4282]
I might fall back to the parameter solution. My goal is, that with 
BIND the code becomes much more natural to read and maintain. Because 
teh storage context needs some knowledge about the context to save, 
as I'm using a dynamic field-mapping method. Hence I only need to 
alter the context-to-save (add / remove words) and the storage context 
can handle it automatically. I have to deal with scheme evolution 
and versioning.
BrianH
1-May-2006
[4283x2]
In that case, try the stub functions to hide the parameter passing. 
It will use less space, be more efficient and safer.
Logically though, you do have an object that is providing the storage 
infrastructure and is acting on other objects. The objects aren't 
storing themselves and their storage isn't their primary function. 
They are delegating that function to another object. So, other than 
the data that the storage engine needs, you don't really need to 
be distributing the code for storage throughout the data to be stored, 
unless these objects need per-object-specific serialization and versioning 
algorithms.


All the dynamic context manipulations cal be done by your storage 
engine working on the objects to be stored as data - they really 
are anyways.