Incorporting WhatIf

2003-04-04 Thread David Storrs
I recently discovered a CPAN module called WhatIf 
(http://search.cpan.org/author/SIMONW/Whatif-1.01/).  This module has
the ability to provide rollback functionality for arbitrary code.

I don't really understand continuations yet (although I'm reading up
on them), so perhaps they would allow this to be done trivially.
However, I think it would be very cool to roll this module into the
core language and provide the keyword support in core.

Is this feasible?  What would the overhead costs be?

--Dks


Re: Incorporting WhatIf

2003-04-04 Thread Luke Palmer
 I recently discovered a CPAN module called WhatIf 
 (http://search.cpan.org/author/SIMONW/Whatif-1.01/).  This module has
 the ability to provide rollback functionality for arbitrary code.

Crazy... I was just thinking about this for an experimental language
called Snapshot I'm about to implement for my job.

 I don't really understand continuations yet (although I'm reading up
 on them), so perhaps they would allow this to be done trivially.
 However, I think it would be very cool to roll this module into the
 core language and provide the keyword support in core.

This is what Larry wants with 

let subcall();

(from Appendix C of A6).  It would be great to have it in the core, if
it's feasable to implement.

The way Snapshot will probably do it is have a local mark on all its
variables. Then when a variable is set, it will set a field
corresponding to that local mark, and append itself to the queue
associated with that mark.  Correspondingly, when it's accessed, it
would instead return the value in the local mark if it has one.

Then, upon success, it would go through that mark's queue and tell the
variables to commit themselves (maybe onto another mark field, if the
let is nested).  Upon failure, it would go through the queue and tell
them to rollback.

This could be implemented with very little overhead for variables that
don't ever get assigned to during a hypothetical state.

 Is this feasible?  What would the overhead costs be?

I'm thinking about whether this could be done as a module in P6.  If
so, wow, what an extensible language.

Maybe you could, by very early on overriding the builtin Scalar
container.  I'm not sure what implications that would have for
variables declared Cint, and such.  Probably just wouldn't work for
them.

Like:

our LocalMark @*LOCAL_MARK;

class LocalMark {
method add(Ref $in) {
push @.set: $in;
}
method commit() {
for @.set { 
.commit;
}
}
method rollback() {
for @.set {
.rollback;
}
}
has Ref @.set is Set;
}

my class NewScalar is Scalar {
method STORE($newval is copy) {
[EMAIL PROTECTED] = $newval;
}
method FETCH() {
for @*LOCAL_MARK {
return %.mark{$_} if %.mark.exists($_)
}
undef;
}
method commit() {
[EMAIL PROTECTED] = [EMAIL PROTECTED];
}
method rollback() {
%.mark.delete(@*LOCAL_MARK[0]);
}
has %.mark is keyed(LocalMark);
}

Scalar := NewScalar;

And then:

sub {
let foo();
}

Turns into:

sub {
unshift @*LOCAL_MARK, new LocalMark;
foo();

KEEP {
@*LOCAL_MARK[0].commit;
shift @*LOCAL_MARK;
}
UNDO {
@*LOCAL_MARK[0].rollback;
shift @*LOCAL_MARK;
}
}

Or something.

I think it's a very powerful concept at the language level, however.

Luke