On 8/22/05, Yiyi Hu <[EMAIL PROTECTED]> wrote:
> my( $s, $t ); $s = "value t is $t"; $t = "xyz"; print $s;

I have an answer for you that is much more detailed than what you want
to hear.  The short answer is "yes".

This is possible to implement, provided you appropriately declare $t. 
It all depends on how deep you want the lazy semantics to go.  The
shallowest you can get is using the junctive hook (which I'll call
CallHook right now):

    role CallHook {
        # this is the interface of a role that junctions use for
        # autothreading
        
        # call this with the appropriately curried function whenver
        # a value that does this role is passed to a function
        method CALLHOOK (&call) {
            call($?SELF);
        }

        # call this with the return continuation whenever this
        # value is returned from a function
        method RETURNHOOK (&retcont) {
            retcont($?SELF);
        }

        # call this with the current continuation whenever this value
        # is assigned to a variable
        method ASSIGNHOOK (&cont) {
            cont($?SELF);
        }
        
        # perhaps this role provides more hooks
    }
    
    class LazyValue does CallHook {
        has &.thunk = { undef };
        method CALLHOOK (&call) {
            LazyValue.new( :thunk{ call(.eval) } );
        }
        method RETURNHOOK (&retcont) {
            retcont(.eval);
        }
        method eval () {
            .thunk()();
        }
        method set_thunk (&.thunk) { }
    }

    my $s = LazyValue.new;
    my $t = "Hello, $s!";
    $s = "World";
    say $t.eval;    # Hello World![1]

You could get that pesky eval out of there by defining print (and say)
multimethod variants yourself.  You have to tell it when to evaluate
sometime.

Of course, this behavior will not be default, since it can get you
into a lot of trouble.  You say that in Perl 6 arrays will behave
lazily, but this is *not* what is meant:

    my @array;
    my $string = "Hello, @array[]";
    @array = ("World!");
    say $string;    # "Hello, "  !!!

What we mean by a lazy array is that laziness propagates automatically:

    my @array = <>;   # <> returns a lazy array, so @array is now lazy
    @array = (1,2,3); # (1,2,3) is not lazy, so @array becomes unlazy

Luke

[1] The well-typed version of this follows.  I have hand-checked it
(fairly well, but humans do make mistakes).  Hooray for strong typing
when we want it!

    use traits <typed>;
    role CallHook[::of] {
        method CALLHOOK ( &call:(::of $value --> ::T) --> ::T ) {
            call($?SELF);
        }

        method RETURNHOOK ( &retcont:(::of $value --> ::T) --> ::T ) {
            retcont($?SELF); 
        }

        method ASSIGNHOOK ( &cont:(::of $value --> ::T) --> ::T ) {
            cont($?SELF);
        }
    }

    # I'm Ignoring that you can only parameterize roles, because that's
    # a silly policy, and nobody is executing this code, so I'm
    # writing in Luke's dialect.
    
    class LazyValue[::of] {
        does CallHook of ::of;
        
        # is mock() tells the type checker to trust that I conform to
        # this interface without checking[2].
        is mock(::of);

        has &.thunk = { undef };
        method CALLHOOK (&call(::of $value --> ::T) --> ::T) {
            LazyValue[::T].new( :thunk{ call(.eval) } );
        }
        method RETURNHOOK (&retcont(::of $value --> ::T) --> ::T) {
            retcont(.eval);
        }
        method eval (--> ::of) {
            .thunk()();
        }
        method set_thunk (&.thunk:(--> ::of)) { }
    }

[2] Which is safe to do, because I intercept all method calls on this
object and replace then with something that takes what the methods
take and returns what the methods return[3].

Also, such an "is mock" declaration must turn off optimizations
associated with the type in question.  So all you get is the type
checking.

[3] Unless that method is eval() or set_thunk(), in which case I don't
really conform to ::of.  That probably means that eval() and
set_thunk() should be out-of-band functions, not methods.

Reply via email to