WARNING: BRIDGE OUT.
Proceed at your own risk.
You may drive off the road
into a VERY strange stream
(of consciousness).

[EMAIL PROTECTED] wrote:
> 
> I am not happy watching my ability to write what I mean in this case.
>

I have certainly felt that sentiment myself, on a number of occasions!
(Especially recently!  ;-)

> 
> Here is a different approach:
> 
> f: func [] [print "Executed"]
> code: [(:f)]
> do code
> change code :f
> do code
> 
> Results from the Rebol console:
> 
> >> f: func [] [print "Executed"]
> >> code: [(:f)]
> == [(:f)]
> >> do code
> >> change code :f
> == []
> >> do code
> Executed
> 
> Now, my description what has happened:
> 
> I created a Rebol code. (see Code) Then I decided to replace the
> parenthesized expression by it's result, and, voila:
> 
> "There are some cases in Rebol where you can't replace the
> parenthesized expression by it's result and get the same"
> 

Before I continue below, let me paraphrase your expressions just
a tiny bit -- with justification, I hope.  (Please let me know if
this paraphrase does violence to the idea you are trying to
express.)  Let's begin as you did, with:

    >> f: func [] [print "Executed"]
    >> code: [(:f)]
    == [(:f)]
    >> do code
    >>

But it occurs to me to ask REBOL this question:

    >> same? do code :f
    == true

Based on REBOL's assurance that {do code} and {:f} are the same, I
would like to paraphrase your {change code :f} as follows

    >> change code do code
    == []
    >> do code
    Executed

And I get the same result -- the execution of f, which prints the
string "Executed" on the console.

I think that the transcript above is replacing an expression with
the result of its evaluation, but that result is then capable of
producing yet another result upon further evaluation.

(Hmmm...  I don't like how that sentence came out, but don't know how
to word it better, so let me illustrate with some examples.)

Consider the expression evaluations

    >> (2 + 2)
    == 4
    >> 4
    == 4

Once we evaluate 2 + 2, we get what we might call a "pure value".
Since it has "bottomed out" or  "hit the wall", there's nowhere else
for it to go.  Repeated evaluation of the result just keeps giving
back the same value.

The same would have happened if we had used an expression that
evaluated to a string.

    >> (join "some" " string")
    == "some string"
    >> "some string"
    == "some string"

Now, let's wrap these expression evaluations in a block-with-'do
arrangement such as you exhibited (except that I'm lazy, so I'll
use 'k for the name of my container instead of 'code).  First,
the numerical case:

    >> k: [(2 + 2)]
    == [(2 + 2)]
    >> change k do k  k
    == [4]
    >> change k do k  k
    == [4]

then with the string case:

    >> k: [(join "some" " data")]
    == [(join "some" " data")]
    >> change k do k  k
    == ["some data"]
    >> change k do k  k
    == ["some data"]

Evaluation (via the {do k}) takes us from value to value along
these paths:

    [(2 + 2)]  --->  [4]  ---,
                      ^      |
                      |      |
                       `----'

    [(join "some" " string")]  --->  ["some string"]  ---,
                                      ^                   |
                                      |                   |
                                       `-----------------'

Now consider a slightly stranger case

    >> b: ['b b "b"]
    == ['b b "b"]
    >> x: 'b
    == b
    >> y: 'x
    == x

followed by

    >> k: [('y)]
    == [('y)]
    >> change k do k  k
    == [y]
    >> change k do k  k
    == [x]
    >> change k do k  k
    == [b]
    >> change k do k  k
    == ['b b "b"]
    >> change k do k  k
    == ["b" b "b"]
    >> change k do k  k
    == ["b" b "b"]

This case provides us with a path that does not bottom out after a
single step, but continues for a while to give us values that can
be evaluated again to get other values.

    [('y)]  --->  [y]  --->  [x]  --->  [b]  ---,
                                                 |
                                                 |
     .---  ["b" b "b"]  <---  ['b b "b"]  <-----'
    |       ^
    |       |
     `-----'

This is the longest chain of evaluations I've been able to construct
thus far, but here's one that has a limit cycle of length 2 (there
are two values in the final loop) instead of a limit cycle of length
1 (a single value that is transformed into itself):

    >> w: 'v
    == v
    >> v: 'w
    == w
    >> k: [('w)]
    == [('w)]
    >> change k do k  k
    == [w]
    >> change k do k  k
    == [v]
    >> change k do k  k
    == [w]
    >> change k do k  k
    == [v]

which can be pictured as

    [('w)]  --->  [w]  --->  [v]  ---,
                   ^                  |
                   |                  |
                    `----------------'

So...  sometimes evaluation gives us back something capable of
representing (or evaluating to) only itself, but sometimes it gives
us back something capable of evaluation into yet another thing.

WAIT! BEFORE I HIT "SEND" ...

I must retract the second paragraph above.  I believe I can now
show a chain of evaluations that has no limit cycle.  Every
evaluation gives back a new re-evaluatable value.  Consider:

    >> s1: "print to-char (64 + random 26)"
    == "print to-char (64 + random 26)"
    >> s2: "func [] [do s1 do s2]"
    == "func [] [do s1 do s2]"

after which

    >> k: [(do s2)]
    == [(do s2)]
    >> change k do k  k
    == [func [][do s1 do s2]]
    >> change k do k  k
    N
    == [func [][do s1 do s2]]
    >> change k do k  k
    H
    == [func [][do s1 do s2]]
    >> change k do k  k
    C
    == [func [][do s1 do s2]]

Now I can almost hear someone thinking,

   "Wait a minute!  Since the result of the {do s1} part is to
    print a random upper-case letter, how do you justify saying
    that the RESULT (not the printed output!) is different every
    time?  After all, the printed result (after the double equal
    sign) looks the same!"

I claim that we have a chain of similar but distinct functions being
created, because:

1)  The result of the {do s2} part is a newly-defined function

        >> type? do s2
        == function!

    which can be evaluated itself to cause a side-effect (output to
    the console) but to RETURN another function

        >> type? do do s2
        A
        == function!
        >>

2)  Using some variables for convenience (to capture values for
    later examination)

        >> x: do s2
        >> y: x
        S
        >> type? :x
        == function!
        >> type? :y
        == function!
        >> same? :x :y
        == false

    we can see that the result of doing s2 once (captured in x) can
    be evaluated to produce a result (captured in y) that is also a
    function, but is not the same function.

3)  We can make the same test by capturing the first (and only!)
    element of k's value, performing one 'change cycle, and checking
    to see whether we still have the same function.

        >> g: first k
        >> change k do k  k
        P
        == [func [][do s1 do s2]]
        >> type? first k
        == function!
        >> h: first k
        >> same? :g :h
        == false
        >> same? :h first k
        == true

    (The last line above is just to show that 'same? really can tell
     us whether we have the same function.)

Recall that Elan has warned us many times about not confusing console
displays with the "real things".  (My awkward wording, not his.)

    >> z: {func [] [print "something"]}
    == {func [] [print "something"]}
    >> z1: do z
    >> z2: do z
    >> z1
    something
    >> z2
    something
    >> same? :z1 :z2
    == false
    >> source z1
    z1: func [][print "something"]
    >> source z2
    z2: func [][print "something"]

Here's an example of two functions that are not the same, even
though they have identical behavior and were created from the same
string of source code.


I conclude that there are cases in which replacing an expression
with its value doesn't yield something which evaluates the same
as the original.  If the expression returns a function, we can
do so forever without hitting a fixpoint.


Thanks, Ladislav, for inspiring this exploration!  I've really
enjoyed it, even if it bores everyone else to tears!

-jn-

Reply via email to