Bug! path! in objects don't behave the same as path! outside object
[1/5] from: al::bri::xtra::co::nz at: 25-Sep-2000 12:29
Bug! path! in objects don't behave the same as path! outside object.
REBOL/View 0.10.34.3.1 23-Sep-2000
Copyright 2000 REBOL Technologies. All rights reserved.
>> base: make object! [
[ p: does [print "function 'p in 'base"]
[ ]
>> derived: make object! [
[ p: first [base/p]
[ ]
>> p: first [base/p]
== base/p
>> p
function 'p in 'base
>> :p
== base/p
>> base/p
function 'p in 'base
>> derived/p
== base/p
The above is incorrect, I believe. The result of the above should be the
result of base/p:
function 'p in 'base
_not_ the path:
base/p
Andrew Martin
ICQ: 26227169
http://members.nbci.com/AndrewMartin/
http://members.xoom.com/AndrewMartin/
[2/5] from: rebol:techscribe at: 24-Sep-2000 21:48
Hi Andrew,
you wrote:
>Bug! path! in objects don't behave the same as path! outside object.
Which parallel case involving paths are you thinking of?
Here is an example case that does not involve objects at all and behaves
exactly the case you attribute to objects:
>> base: func [/p] [ either p [print "'p in 'base."] [print "'base"] ]
>> base/p
'p in 'base.
>> derived: make function! [/p] [ either p [p: first [base/p]] [first
[base] ] ]
>> derived
== base
>> derived/p
== base/p
When you create the object (or in my example the function) the expression
first [base/p]
is evaluated. It evaluates to the path base/p
>> type? first [base/p]
== path!
base/p is a value of type path! This value, base/p, is referenced by p in
your make object! example. If you want REBOL to instead assign p as a
reference to the value that the path evaluates to, you must tell REBOL that:
>> first reduce [base/p]
'p in 'base.
i.e.
derived: make object! [
p: first reduce [base/p]
]
>REBOL/View 0.10.34.3.1 23-Sep-2000
>Copyright 2000 REBOL Technologies. All rights reserved.
<<quoted lines omitted: 24>>
>http://members.xoom.com/AndrewMartin/
>-><-
;- Elan [ : - ) ]
author of REBOL: THE OFFICIAL GUIDE
REBOL Press: The Official Source for REBOL Books
http://www.REBOLpress.com
visit me at http://www.TechScribe.com
[3/5] from: al:bri:xtra at: 25-Sep-2000 19:50
> Hi Andrew,
Hi, Elan.
I agree with everything up to here:
> If you want REBOL to instead assign p as a reference to the value that the
path evaluates to, you must tell REBOL that:
> >> first reduce [base/p]
> 'p in 'base.
> i.e.
> derived: make object! [
> p: first reduce [base/p]
> ]
Unfortunately, that doesn't work:
>> base: make object! [p: does [print "function 'p in 'base"]]
>> derived: make object! [p: first reduce [base/p]]
function 'p in 'base
** Script Error: p needs a value.
** Where: p: first reduce [base/p]
I'd like 'p in 'derived to be a path!, which refers to 'p in 'base. Like I
can do with 'p outside of derived. Watch closely:
>> p: first [base/p]
== base/p
>> type? p
function 'p in 'base
== unset!
>> type? :p
== path!
>> probe p
function 'p in 'base
** Script Error: probe is missing its value argument.
** Where: probe p
>> probe :p
base/p
== base/p
Now if this behaviour outside an object were implemented inside an object,
then it would be very easy to write objects that inherit behaviour, and the
storage cost wouldn't involve copying functions into every object. I think
that would be very nice behaviour. I can also show that it's fault in
objects because:
>> derived: make object! [p: first [base/p]]
>> derived/p: :p
== base/p
>> probe derived
make object! [
p: base/p
]
>> derived/p
== base/p
>> p
function 'p in 'base
Andrew Martin
Breaking new paths...
ICQ: 26227169
http://members.nbci.com/AndrewMartin/
http://members.xoom.com/AndrewMartin/
[4/5] from: rebol:techscribe at: 25-Sep-2000 12:10
Hi Andrew,
Aha. Got it. What you are observing is not specific to objects. It is the
result of how REBOL evaluates words and paths.
Let me simplify your example so that we can more easily focus on the
essential difference.
>> base: make object! [ p: "'p in 'base." ]
>> derived: make object! [ p: 'base/p ]
1. Word evaluation:
a) word references a path that evaluates to a string.
>> p: 'base/p
== base/p
>> :p
== base/p
>> p
== "'p in 'base."
b) word references a path that evaluates to a path:
>> r: 'derived/p
== derived/p
>> :r
== derived/p
>> r
== base/p
In both cases when REBOL evaluates a word and the word evaluates to a path,
then REBOL returns the value that is referenced by the path. It stops
dereferencing values at the second level as demonstrate by r. The evaluator
return base/p and did not continue to dereference the path base/p.
Compare to:
2. Path evaluation:
>> derived/p
== base/p
Re: 1. (a and b) When REBOL evaluates a word, and the returned value is a
path, then REBOL returns the value referred to by that path.
Re: 2. When REBOL evaluates a path, then it returns the value that path is
associated with. Unlike case 1., the path returned by evaluating the
top-level path is not dereferenced.
3. In both cases 1. and 2. if the returned value is a function, then that
function is evaluated and the value resulting from evaluating the function
is returned.
So what you are dealing with here is an exception that REBOL evaluator
makes for words, when those words evaluate to paths.
You can say that with respect to this behavior the REBOL evaluator works
something like this:
evaluate: func [something [any-type!]] [
if value? 'something [
either all [
word? get 'something
path? get get 'something
]
[
return get get 'something
][
return get 'something
]
]
return print "unset"
]
>> evaluate p
== "'p in 'base."
>> evaluate derived/p
== base/p
Note that this really has nothing to do with objects. You can do the same
thing with blocks:
>> block: [ p "'p in 'block" ]
== [p "'p in 'block"]
>> block/p
== "'p in 'block"
Word is assigned a path:
>> p: 'block/p
== block/p
When the REBOL evaluator discovers that the word p is referencing a path,
then the path is dereferenced as well:
>> p
== "'p in 'block"
But when REBOL is evaluating a path (this time associated with a block)
then unlike when evaluating a word, the evaluation is not repeated for the
referenced path:
>> derived: [ p block/p ]
== [p block/p]
>> derived/p
== block/p
In short, REBOL is consistent with respect to the distinction it makes
between evaluating words and evaluating paths. The way REBOL treats path is
not specific to objects.
Hope this helps,
;- Elan [ : - ) ]
author of REBOL: THE OFFICIAL GUIDE
REBOL Press: The Official Source for REBOL Books
http://www.REBOLpress.com
visit me at http://www.TechScribe.com
[5/5] from: al:bri:xtra at: 26-Sep-2000 19:55
Hi, Elan. You wrote:
> When the REBOL evaluator discovers that the word p is referencing a path,
then the path is dereferenced as well:
> >> p
> == "'p in 'block"
>
> But when REBOL is evaluating a path (this time associated with a block)
then unlike when evaluating a word, the evaluation is not repeated for the
referenced path:
> >> derived: [ p block/p ]
> == [p block/p]
> >> derived/p
> == block/p
>
> In short, REBOL is consistent with respect to the distinction it makes
between evaluating words and evaluating paths. The way REBOL treats path is
not specific to objects.
I agree.
But it would be very, very nice if the natural value of a path! is the
dereferenced value. So that a path! value operates like a function! value
does.
Andrew Martin
ICQ: 26227169
http://members.nbci.com/AndrewMartin/
http://members.xoom.com/AndrewMartin/
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted