[refactoring s-c?]
[1/12] from: rebol665:ifrance at: 13-Mar-2002 22:43
Hi rebollers
Again exploring Ladislav's contexts.html, I have difficulty understanding
the s-c? function. The goal of the s-c? function is to test if two words are
in the same context.
Two Words WORD1 and WORD2 are bound to the same context, if the expression
(s-c? word1 word2) yields TRUE.
Here (1) is the original version of s-c? and (2) my simplified version. Both
return the same result (3). Something is certainly missing in the simplified
version, but what ? what are the purposes of the 'use and 'reduce in the
original version ?
(1)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; s-c? function
undefined?: func [
{determines, if a word is undefined}
word [any-word!]
] [
error? try [error? get/any :word]
]
s-c?: func [
{Are word1 and word2 bound to the same context?}
word1 [word!]
word2 [word!]
] [
found? any [
all [
undefined? word1
undefined? word2
]
all [
not undefined? word2
same? word1 bind use reduce [word1] reduce [
'first reduce [word1]
] word2
]
]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; the (over?) simplified version
(2)
sc: func [
{Are word1 and word2 bound to the same context?}
word1 [word!]
word2 [word!]
] [
print mold use reduce [word1] reduce ['first reduce [word1]]
found? any [
all [
undefined? word1
undefined? word2
]
all [
not undefined? word2
same? word1 first bind [word1] word2
]
]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; tests
(3)
>> o: make object! [a: 1 b: 2]
>> a: 100
== 100
>>
>> word1: 'a
== a
>> word2: second first o
== a
>> word3: third first o
== b
The original s-c? gives :
>>s-c? word1 word2
== false
>>s-c? word1 word3
== false
>>s-c? word2 word3
== true
The simplified version gives
>>sc word1 word2
a
== false
>>sc word1 word3
a
== false
>>sc word2 word3
a
== true
As for the subject of this post, I was just kidding. I'am pretty sure that
Ladislav's code do not need any refactoring.
Patrick
[2/12] from: rotenca::telvia::it at: 14-Mar-2002 14:23
Hi Pat,
> all [
> not undefined? word2
> same? word1 first bind [word1] word2
> ]
> ]
> ]
1) If you do not get 'word1 o reduce [word1], 'word1 is 'word1, not its value
(the real word to test)
2) if 'word1 is not in the context of 'word2, bind does not change it and
same? return true.
>> o: context [b: 2]
>> same? 'a first bind [a] in o 'b
== true
---
Ciao
Romano
[3/12] from: rebol665:ifrance at: 15-Mar-2002 15:24
Thank you romano
I think I have a long way in front of me before I fully understand the s-c?
code. Sometimes it seems the more I go the less I know.
I would be glad if someone (Ladislav ?) could explain it to me.
Patrick
No news of rebol/core 2.6 ? it was supposed to be available this week, isn't
it ?
[4/12] from: lmecir:mbox:vol:cz at: 15-Mar-2002 19:15
Hi Pat,
thanks for looking into that. The goal of the USE and REDUCE usage is to
create a word equal to a given word but not the same as the given word. I
could have defined a function NONSAME as follows:
nonsame1: func [
{
create a word equal to the given word
but not the same as the given word
}
word [word!] {the given word}
] [
use reduce [word] reduce [
'first reduce [word]
]
]
My implementation was incorrect (as I have found out when I looked into it).
A correct implementation should have been as follows:
nonsame: func [
{
create a word equal to the given word
but not the same as the given word
}
word [word!] {the given word}
] [
first use reduce [word] reduce [
reduce [word]
]
]
Can you find my error?
The implementation of the S-C? function could then have been as follows:
s-c?: func [
{Are word1 and word2 bound to the same context?}
word1 [word!]
word2 [word!]
] [
found? any [
all [
undefined? word1
undefined? word2
]
all [
not undefined? word2
same? word1 bind nonsame word1 word2
]
]
]
Cheers (and thanks for your question)
Ladislav
----- Original Message -----
From: "pat665" <[rebol665--ifrance--com]>
To: <[rebol-list--rebol--com]>
Sent: Wednesday, March 13, 2002 10:43 PM
Subject: [REBOL] [refactoring s-c?]
Hi rebollers
Again exploring Ladislav's contexts.html, I have difficulty understanding
the s-c? function. The goal of the s-c? function is to test if two words are
in the same context.
Two Words WORD1 and WORD2 are bound to the same context, if the expression
(s-c? word1 word2) yields TRUE.
Here (1) is the original version of s-c? and (2) my simplified version. Both
return the same result (3). Something is certainly missing in the simplified
version, but what ? what are the purposes of the 'use and 'reduce in the
original version ?
(1)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; s-c? function
undefined?: func [
{determines, if a word is undefined}
word [any-word!]
] [
error? try [error? get/any :word]
]
s-c?: func [
{Are word1 and word2 bound to the same context?}
word1 [word!]
word2 [word!]
] [
found? any [
all [
undefined? word1
undefined? word2
]
all [
not undefined? word2
same? word1 bind use reduce [word1] reduce [
'first reduce [word1]
] word2
]
]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; the (over?) simplified version
(2)
sc: func [
{Are word1 and word2 bound to the same context?}
word1 [word!]
word2 [word!]
] [
print mold use reduce [word1] reduce ['first reduce [word1]]
found? any [
all [
undefined? word1
undefined? word2
]
all [
not undefined? word2
same? word1 first bind [word1] word2
]
]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; tests
(3)
>> o: make object! [a: 1 b: 2]
>> a: 100
== 100
>>
>> word1: 'a
== a
>> word2: second first o
== a
>> word3: third first o
== b
The original s-c? gives :
>>s-c? word1 word2
== false
>>s-c? word1 word3
== false
>>s-c? word2 word3
== true
The simplified version gives
>>sc word1 word2
a
== false
>>sc word1 word3
a
== false
>>sc word2 word3
a
== true
As for the subject of this post, I was just kidding. I'am pretty sure that
Ladislav's code do not need any refactoring.
Patrick
[5/12] from: rebol665:ifrance at: 16-Mar-2002 18:24
Hi Ladislav,
I am even more confused, but I like that!
I can play the luke-who-wants-to-be-a-jedi part, master Yoda.
1. Assuming that nonsame is correct, I have tested that :
a: 100
word1: nonsame 'a
>> s-c? 'a 'word1
== true
I was puzzled because I thought that use will create a new context and
return something bound to this context. I had found an interesting example
of that in the escribe archives :
a: 1
block: [a]
use [a] [a: 2 append tail block [a]]
>> block
== [a a]
>> s-c? first block second block
== false
Fortunately I realized my mistake and that the correct testing was :
>> s-c? 'a word1
== false
That was confirmed by
>> s-c? 'a nonsame 'a
== false
Assertion 1 : nonsame returns a word bound to another context.
Assertion 2 : this context is created by use.
Assertion 3 : nonsame returns a word with the same spelling.
>> mold word1
== "a"
>> mold 'a
== "a"
I am aware that assertion 1 and assertion 3 are certainly bound because it
is not possible to have two words with the same spelling in the same
context.
2. From (1) I have learned that use was required to create a new word with
the same spelling but different. As for comparing nonsame1 and nonsame, I
have learned nothing. As far as I can tell they are equivalent :
>> word2: nonsame1 'a
== a
>> s-c? 'a word2
== false
3. Why reduce ? I have still no idea, but I can try removing it and see what
happens.
ns: func [
word [word!] {the given word}
][
use [word][word]
]
>> ns 'a
** Script Error: word has no value
** Where: ns
** Near: word
Definitively wrong
ns: func [
word [word!] {the given word}
][
use [word] reduce [word]
]
>> ns 'a
== 100
Returns a value. It is not good.
ns: func [
word [word!] {the given word}
][
use [word] reduce ['first reduce [word]]
]
>> ns 'a
== a
Looks better. first is used to extract a word rather than a value. An extra
block is needed to be the body that use requires. However this is not good
because :
>> same? 'a ns 'a
== true
Assertion 4 : I am exhausted !
4. As far as I can tell now, I am not able to explain why nonsame is better
than nonsame1. All my experiments have fail to prove any of :
- nonsame1 and nonsame do not return always the same result
- nonsame1 has an undesired side-effect
- nonsame1 rises an error
5. Epilogue
Learning that I know nothing is indeed a valuable lesson. Knowing that is
certainly better than pretending to know something that I don't. I don't
know if I am ready for understanding the truth. It is not for the apprentice
to decide. I have spent half my day with all these trials and must return
now to a normal life ! Hoping for the best
Patrick
[6/12] from: rotenca:telvia:it at: 17-Mar-2002 1:33
Hi, Pat
> Assertion 4 : I am exhausted !
>
> 4. As far as I can tell now, I am not able to explain why nonsame is better
> than nonsame1. All my experiments have fail to prove any of :
>
> - nonsame1 and nonsame do not return always the same result
> - nonsame1 has an undesired side-effect
> - nonsame1 rises an error
>
Try with the word 'first
---
Ciao
Romano
[7/12] from: lmecir:mbox:vol:cz at: 17-Mar-2002 8:44
Hi Pat,
you are doing well, don't give up (use the source, Luke...), your mail is
nice.
<<Pat>>
...snip...
Assertion 1 : nonsame returns a word bound to another context.
Assertion 2 : this context is created by use.
Assertion 3 : nonsame returns a word with the same spelling.
...snip...
2. From (1) I have learned that use was required to create a new word with
the same spelling but different. As for comparing nonsame1 and nonsame, I
have learned nothing. As far as I can tell they are equivalent :
<</Pat>>
NONSAME1 and NONSAME look so much equivalent, that it confused even me. The
only difference is the usage of 'first. That is the source of the trouble in
NONSAME1:
same? 'first nonsame1 'first
** Script Error: first has no value
** Where: nonsame1
** Near: first [first]
If we try this for NONSAME, we will get:
same? 'first nonsame 'first
== false
<<Pat>>
...snip...
3. Why reduce ? I have still no idea,
...snip...
<</Pat>>
Just in case you need it, here is the reason for REDUCE:
word: 'a
block1: [word]
block2: reduce [word]
block3: reduce [[word]]
block4: reduce [reduce [word]]
<<Pat>>
...snip...
5. Epilogue
Learning that I know nothing is indeed a valuable lesson. Knowing that is
certainly better than pretending to know something that I don't. I don't
know if I am ready for understanding the truth. It is not for the apprentice
to decide. I have spent half my day with all these trials and must return
now to a normal life ! Hoping for the best
Patrick
<</Pat>>
Nice epilogue :-) My feelings are similar, because my implementation of
S-C?, although pretending to be correct, was in fact incorrect. Hope the
trial and error didn't exhaust you too much. Now it should be clearer, but
feel free to ask, if anything remains unclear.
Best regards
L
P.S. The newest version of [Contexts] is at:
http://www.rebolforces.com/~ladislav/contexts.html
P.P.S. How do you like the change in the UNBOUND? function?
[8/12] from: rebol665:ifrance at: 17-Mar-2002 22:16
Hi Ladislav,
1. first 'first
If I understand nonsame1 is equivalent to nonsame except if called with the
word 'first.
<<yoda>>
same? 'first nonsame1 'first
** Script Error: first has no value
<<L>>
So I have tried to find out the part of nonsame1 that breaks ...
In the following line from nonsame1, I see two parts :
use reduce [word] reduce ['first reduce [word]]
or
use <part 1> <part 2>
<part 1> being a block of words, here a block with only one word.
<part 2> being a block to evaluate. Evaluation returning the given word.
A little test shows that <part 1> is correct.
>> myword: 'first
== first
>> reduce [myword]
== [first]
Therefore I concentrate myself on <part 2>. To emulate <part 2> I create
this little function
test: func [x [word!]][do reduce ['first reduce [x]]]
However I was desappointed with the result.
>> test myword
== first
No error, so neither <part 1> or <part 2> is responsible for the error. It
is only when they are bind together by use, that an error rises. I think
also there is nothing wrong with 'first by itself. To clear that, I have
made the following test where 'first is replaced by 'second.
>> test2: func [word [word!]][use reduce [word] reduce ['second reduce
[word]]]
>> test2 'second
** Script Error: second has no value
Bingo ! let's try to remove first ...
>> test2: func [word [word!]][use reduce [word] reduce [reduce [word]]]
>> test2 'first
== [first]
It is almost ok, except that a block is returned instead of a word. And it
was indeed the purpose of using 'first to give us a word. A part that it
returns a block, test2 give us the right thing : a word with the same
spelling but not the same word.
>> first test2 'first
== first
Here we can get the "new" first with the same spelling.
>> same? 'first first test2 'first
== false
And it is not the same as the global first. From that it is easy to build
test3 which is indeed nonsame :
>> test3: func [word [word!]][first use reduce [word] reduce [reduce
[word]]]
>> test3 'first
== first
>> same? 'first test3 'first
== false
2. second reduce
Let's play again with my simplification of use :
use <part 1> <part 2>
where
<part 1> is a block including one word
<part 2> is a block returning that word
Why can't we simply write :
test4: func [x [word!]][use [x][x]]
This is an answer
>> use [x][x]
** Script Error: x has no value
** Where: do-boot
** Near: x
The x in part 2 exists but have never been set. It has no value to return.
In fact, we don't want the value of x but the word associated. May be this
could work.
test4: func [x [word!]][use [x]['x]]
>> test4 'first
== x
Nope, 'x is taken litteraly here.
test4: func [x [word!]][use [x][compose [('x)]]]
>> test4 'first
== [x]
test4: func [x [word!]][use reduce [x][compose [('x)]]]
>> test 'first
== [first [first]]
Yeah, another puzzle: one in -> two out. However it is first that comes out.
So I think I understand the first reduce. Let's replace compose by reduce
too.
test4: func [x [word!]][use reduce [x][reduce [x]]]
>> test4 'first
== [first]
Not bad ! but is it the real one ?
>> same? 'first first test4 'first
== true
No luck again. Indeed it says something. Since we get the global 'first, it
means that the use did not work at all.
This one is a bit tricky
test5: func [x [word!]][use [first][reduce [x]]]
>> test5 'first
== [first]
>> same? 'first test5 'first
== false
It works, however it works only with 'first. It shows anyway that only <part
2> needs to be taken care of. Let's try to see what is wrong in that <part
2>.
test6: func [x [word!]][use reduce [x][print reduce [x]]]
>> test6 'first
** Script Error: first expected series argument of type: series pair event
money date object port
time tuple any-function library struct event
** Where: test6
** Near: first
It seems that x is evaluated again. To prevent evaluation, it can be put in
an extra block.
test6: func [x [word!]][use reduce [x][print [reduce [x]]]]
>> test6 'first
first
As we know that print reduces its argument, all we have to do is to replace
print by reduce.
test7: func [x [word!]][use reduce [x][reduce [reduce [x]]]]
>> test7 'first
== [[first]]
And yet there is an external block to get rid of.
test8: func [x [word!]][use reduce [x] reduce [reduce [x]]]
>> test8 'first
== [first]
>> same? 'first test8 'first
== false
And finally from what we learned from (1.).
test9: func [x [word!]][first use reduce [x] reduce [reduce [x]]]
>> test9 'first
== first
>> same? 'first test9 'first
== false
Which is not a surprise because test9 is nonsame.
3. third contexts.html
I was very proud to see my name in the acknowledgements part. I show it to
everybody in the house except my cat.
4. fourth unbound
I noticed the replacement of error? by any-type? I will look into later,
because I have very few little grey cells available at the moment.
Patrick
[9/12] from: g:santilli:tiscalinet:it at: 17-Mar-2002 15:38
Hi Ladislav,
On Friday, March 15, 2002, 7:15:31 PM, you wrote:
Reading your later posts, and thinking about it...
LM> nonsame: func [
LM> {
LM> create a word equal to the given word
LM> but not the same as the given word
LM> }
LM> word [word!] {the given word}
LM> ] [
LM> first use reduce [word] reduce [
LM> reduce [word]
LM> ]
LM> ]
what about:
nonsame: func [
{
create a word equal to the given word
but not the same as the given word
}
word [word!] {the given word}
] [
use reduce [word] reduce [
to-lit-word word
]
]
It seems to work correctly for me. (Not that is much clearer, or
better in any way --- just a different approach.)
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r
[10/12] from: rotenca:telvia:it at: 18-Mar-2002 2:57
It has the side effect of creating a new global word if the word had been
created with to-block.
Perhaps a more readable version of s-c? could be created with compose.
I use it in my own.
---
Ciao
Romano
[11/12] from: rotenca:telvia:it at: 18-Mar-2002 3:12
> 4. fourth unbound
>
> I noticed the replacement of error? by any-type? I will look into later,
> because I have very few little grey cells available at the moment.
Could be any of
none?
tuple?
error?
datatype?
and so on.
It must accept an any-type! arg and have no side effect.
---
Ciao
Romano
[12/12] from: lmecir:mbox:vol:cz at: 18-Mar-2002 9:02
Hi Gabriele,
exactly as Romano said, your version enlarges (sometimes) the global context
(and it is not as generalizable to any-word types). We can use a variable to
shorten the source:
nonsame: function [
{
create a word with equal spelling as the given word has
but not the same as the given word
}
word [word!] {the given word}
] [block] [
first use block: reduce [word] reduce [block]
]
----- Original Message -----
From: "Romano Paolo Tenca"
Sent: Monday, March 18, 2002 2:57 AM
Subject: [REBOL] Re: [refactoring s-c?]
It has the side effect of creating a new global word if the word had been
created with to-block.
Perhaps a more readable version of s-c? could be created with compose.
I use it in my own.
---
Ciao
Romano