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

World: r3wp

[I'm new] Ask any question, and a helpful person will try to answer.

mhinson
24-May-2009
[2868]
Hi, I am reading about BIND, but I cant understand the concept of 
what it is for. Is there something I should understand first perhaps?

The function summary http://www.rebol.com/docs/words/wbind.html
description is what I am starting with, but I dont understand what 
the examples demonstrate.
Paul
24-May-2009
[2869x2]
being new, it probably isn't good to tackle bind just yet.  Bind 
is more advanced concepts.
'bind is used to bind a word or words to a context.
Henrik
24-May-2009
[2871x2]
mhinson, BIND is all about contexts. A word is usually bound to a 
specific context (or object if you will), giving it a specific value 
that exists in that context. You can have:

a: make object! [
	b: 7
]

c: make object! [
	b: 9
]


'b is a word, but for 'c, it has one value and is bound to 'c's context. 
'a is a different context where 'b has different value.
So if you are in a situation where you have the unbound or incorrectly 
bound word 'b, BIND will allow you to change its context:

>> do [b]
** Script Error: b has no value
** Near: b

; no context above, so we bind:

>> do bind [b] c
== 9


This allows you also to refer to words inside a specific context 
without path notation.
Paul
24-May-2009
[2873]
mhinson, when I made Tretbase 1.0 engine, I used Bind quite a lot. 
 The only time I really like to use 'bind is when I have iterations 
where performance is an issue.   That way I could write a block of 
code and then just bind it into a logic based loop.  This way I didn't 
have to record additional loops to meet the logic.
Henrik
24-May-2009
[2874]
Something more basic, that you may have skipped or forgotten: Contexts 
are just objects. They are just a clumped together set of words with 
values.

The big secret is revealed here:

>> source context
context: func [
    "Defines a unique (underived) object."
    blk [block!] "Object variables and values."
][
    make object! blk
]


So when you make a new object, you make a new context. The definition 
block (shown as blk in the source for context) is then bound to this 
new context. You can run ordinary REBOL code inside the object definition 
block. You are not restricted to the obvious syntax of set-word! 
and value pairs:

d: make object! [
	b: "hello"
	reverse b
]
d/b
== "olleh"


Of course after the definition block has been parsed to become an 
object, only the key/value pairs remain.

Remember that and you can get very far with contexts.
mhinson
24-May-2009
[2875]
I think I have understood what it is that has been preventing me 
from understanding BIND.

I was expecting BIND to make a persistant difference to the contexts, 
but now I have realised that is not the case, it only acts as a function 
to return information when it is called.  That was a tough one to 
fight through.   However, now I understand Henrik's example, but 
the example in the manual still confuses me.  
words: [a b c]

    fun: func [a b c][print bind words 'a]  ;; why is this not  ... print 
    bind words 'a 'b 'c]

Does this mean that bind causes fun to be joined to the context of 
words, for all the variables used in the words context? 

I think I am also still confused about which direction the context 
moves.  Sorry to be asking again, but I do want to understand this 
completely. In Henrik's example it seems to be "do b in the context 
of c" but in the manual example it seems more like "print words (which 
in the global context ) as if the context variables of words had 
been assigned the values of the current context....  I am off to 
bed now to sleep on it.   Thanks.
mhinson
25-May-2009
[2876x2]
I see the bind function can do both the things I noticed above.  
I have stalled with reading Ladislav's Bindology paper at section 

9.1 I dont understand what a-word has become, and why.  I dont understand 
how 'a might be referenced in   bind 'a a-word   as it has no mention 
in the example, so I dont understand what is being demonstrated.
I think I need to work on something that is chalanging, but that 
I can do without resorting to too much guessing.
Steeve
25-May-2009
[2878]
words: [a b c]					;**  words, a, b, and c belong to the global context.

fun: func [a b c][print bind words 'a]		;** 'it is asked to change 
the context of the words comprise in the block "words".

      ;** After that, they are not belonging to the global context anymore, 
      but to the context of the function.
mhinson
25-May-2009
[2879]
Thanks Steeve, I think bind is becoming a bit clearer to me. Your 
comments seem to make sense to me now.
BrianH
25-May-2009
[2880]
Words are immediate values, so BIND returns a new value when passed 
a word. BIND changes blocks passed to it, but BIND/copy changes a 
deep copy. The words in blocks are replaced with new words that have 
the same symbol but a different binding.
mhinson
27-May-2009
[2881]
Hi, I am back to learning by guesswork I am afraid :-(    I am trying 
to do something like this
animal: "fish"  breed: "trout"
creature: reduce[to-word animal [type reduce[breed]]]
But I want the result to be 

[fish [named ["trout"]]]              what do I need to learn about 
to understand why reduce dosn't behave how I want it too please?
Steeve
27-May-2009
[2882x2]
missing a reduce, pal
you got 3 blocks, you need 3 reduces
mhinson
28-May-2009
[2884]
Thanks Steeve.  so I use 
creature: reduce[to-word animal reduce['named reduce[breed]]]

and I have to make sure I need the reduce at every level..  In that 
case why is there no reduce option to reduce all nested blocks? Am 
I doing somthing odd that would make me want that?
Henrik
28-May-2009
[2885]
the alternative is compose which offers a /deep refinement:

creature: compose/deep [(to-word animal) [(named) [(breed)]]]


and all parts you wish to compose in the block must be wrapped in 
()'s.
mhinson
28-May-2009
[2886]
That is very cool...  And I feel happy that I predicted there might 
be a thing that did that too... it is much more elegant than lots 
of reduce statements everywhere.  Thanks.
Graham
28-May-2009
[2887]
Compose wasn't there in the beginning ... it was a later add on because 
of these issues
mhinson
29-May-2009
[2888x2]
Hi, I have been trying for the last hour or two to get this code 
to behave in the way I want. 
data: {
thing toy
 owner child
thing house
 owner adult
}

thing: copy []
owner: copy []
StructuredData: copy []

parse/all data [ 
	any [

  ["thing " copy thing to newline (append StructuredData reduce[to-word 
  thing[]])]

  |[" owner " copy owner to newline (append StructuredData/(to-word 
  thing) compose/deep [owner[(owner)]])]
		| skip
	]
]
probe StructuredData

[toy [owner ["child"] owner ["adult"]] house [owner ["child"] owner 
["adult"]]]


My problem is that the toy & the house are owned by the child & the 
adult. It seems the things are linked to each other in a way I dont 
follow.  If I assign the values directly, rather than using the parse, 
then the StructuredData contains what I expect.
[toy [owner ["child"]] house [ owner ["adult"]]]
Just realised if I dont go to bed now the birds will start singing 
& the sun will be comming up again.. Rebol seems to cause time to 
speed up :-)
Chris
29-May-2009
[2890]
Your problem is this line:


 ["thing " copy thing to newline (append StructuredData reduce [to-word 
 thing []])]

Specifically this part:

	reduce [to-word thing []]


The last block here is never copied.  When you append your data with 
the reduced block, the owners block is always the same (as in 'same?) 
block.  You need to create a new block each time:

	reduce [to-word thing copy []]
or
	reduce [to-word thing make block! 5] ; 5 is arbitrary
mhinson
30-May-2009
[2891]
Thanks Chris.  There are several things I have learnt from this: 
 COPY has more varied use than I was aware of. In this case I think 
COPY is making sure I am adding a unique empty block, rather than 
a link to this one.


I still cant quite get my head round an empty block being something 
that can be referenced again later, although I know I have read about 
it previously & know it is important.

Why do I not seem to need COPY in my following example?
StructuredData: copy []
thing: copy "toy"
append StructuredData reduce[to-word thing[]]
owner: copy "child"

append StructuredData/(to-word thing) compose/deep [owner[(owner)]]

thing: copy "house"
append StructuredData reduce[to-word thing[]]
owner: copy "adult"

append StructuredData/(to-word thing) compose/deep [owner[(owner)]]

probe StructuredData
[toy [owner ["child"]] house [owner ["adult"]]]
Graham
30-May-2009
[2892]
You only need to copy if you use it more than once.
Izkata
30-May-2009
[2893]
It happens because the outer block [to-word thing []] is referencing 
the inner block
Chris
30-May-2009
[2894]
mh: In the case above, when you were using 'reduce, you were evaluating 
the first block, in which the second block is just a value.  When 
you evaluate a block value, it is not in turn evaluated:

	>> [i'm not code]
	== [i'm not code]

It's important to remember when you do some deeper evaluation:

	>> code: [[]]  ; block containing a block value
	== [[]]
	>> append code/1 'a  ; modify block value
	== [a]

 >> result: do code  ; evaluate block, block value returned - now 
 referenced by 'result
	== [a]
	>> append code/1 'b  ; modify block value
	== [a b]
	>> result  ; result is referencing the same value
	== [a b]
	>> append result 'c
	== [a b c]
	>> code
	== [[a b c]]


Every value in REBOL is merely referenced to by the language.  Sometimes 
explicitly:

	result: []
	probe result

Or not:

	code: [[]]
	probe code/1

Or both:

	code: [[]]
	result: code/1
	probe same? code/1 result
mhinson
30-May-2009
[2895]
Thanks Chris, Graham, Izkata   I feel like I half get this, but not 
well enough to be confident yet. I have been trying to create a really 
simple example where two parts of the same block are really the same 
items, so changing either, changes both because I think it will help 
me understand better & that was the behaviour in my original example. 
 Perhaps if I study this for another couple of hours I will get a 
breakthrough with it.  Thanks.
Chris
30-May-2009
[2896x2]
Such as?:

	>> attr: []
	== []
	>> cont: reduce [attr attr]
	== [[] []]
	>> insert attr 'c
	== []
	>> insert first cont 'b
	== [c]
	>> insert second cont 'a
	== [b c]
	>> cont
	== [[a b c] [a b c]]
Note that you can continue to reduce the 'cont block, yet the two 
values remain the same.
mhinson
30-May-2009
[2898]
Hi Chris, I am slowly getting there I think.  Thanks for additional 
example.
Izkata
30-May-2009
[2899]
Try this:  Predict the output of these function calls:
foo: func [/local A B][
   A: []
   B: copy []
   print mold append A {a}
   print mold append B {b}
]
foo
foo
foo
mhinson
31-May-2009
[2900]
;Thanks Izkata, I predicted the outcome correctly. I went on to try 
this:
D: [{bar}]                                        ;; global D
foo1: func [D][D: [] print mold append D {d}]     ;; 
foo2: func [D][D: [] print mold append D {d}]     ;; 
foo1 D  ;; value of global D passed to function (but not used)

foo1 D  ;; function references its own local value of [] to which 
it keep appending {d}
foo2 D  ;; same as foo1 but references its own [] ?pointer? thing
D       ;; still references un changed global D

foo1: func [D][D: [] print mold append D {d}]   ;; rewriting foo1 

foo1 D                                          ;; new foo1 function 
has new [] pointer

foo3: func [][D: [] print mold append D {d}]    ;; D is not passed 
to the function

Foo3          ;; now we are changing global D and making it reference 
foo3 [] pointer 
D             ;; proof global D has changed

;; I think the bit that was making it hard for me to understand was 
that 

;; referencing the same empty block in a function means the actual 
exact function, 

;; a second copy of it even with the same name, sets up a new local 
pointer. And also the unexpected localness confused me.


;; Question, do my comments show that my understanding is now correct 
please?
Izkata
31-May-2009
[2901]
It looks correct to me
mhinson
31-May-2009
[2902x2]
:-) thanks Izkata.. I may be moving forward at last :-)
What is the length limit for a comment line please?  some of my comment 
lines are being intrepreted.  I think it is the length of them.
Graham
31-May-2009
[2904x2]
I'm not aware of any limit.
Are you doing this?

comment {
	mutliple comments?

}
mhinson
31-May-2009
[2906]
no, just ;; in front of a few very long lines.
Graham
31-May-2009
[2907]
well.. as I said, not aware of any limit.  maybe it's your editor?
mhinson
31-May-2009
[2908]
it is like that because I have a bunch of lines that will become 
a function & I am comparing them in some cases, and excludeing them 
in other cases to debug my code.
Graham
31-May-2009
[2909x2]
well, use 'command { }
comment
mhinson
31-May-2009
[2911x2]
;; ownerRule: ["owner "  copy owner to newline  

;; ((if (error? try [StructuredData/(to-word thing)/owner]) [append 
StructuredData/:thing reduce[owner copy[]]])(append StructuredData/(to-word 
thing)/owner compose/deep [(owner)]))

;; ownerRule:   ["owner "  copy owner to newline  (append StructuredData/(to-word 
thing) compose/deep [owner  [(owner)]])]
The comment thing sounds good... I will use that instead.  Thanks.
Graham
31-May-2009
[2913x2]
and you only need a single ;
;; is redundant
mhinson
31-May-2009
[2915]
Those lines I posted still do strange stuff with a single ;  at the 
beginning.  Could it be a bug with the console?  I do 2 ;; to make 
them stand out more, although syntax highliting does that already. 
Thanks.
Maxim
31-May-2009
[2916]
when using the console, always use:
 do clipboard://
mhinson
31-May-2009
[2917]
Thanks, that avoids the anomolie :-)