Skip to content

Instantly share code, notes, and snippets.

@karupanerura
Created February 12, 2012 13:33
Show Gist options
  • Save karupanerura/1808539 to your computer and use it in GitHub Desktop.
Save karupanerura/1808539 to your computer and use it in GitHub Desktop.
flatten_callback
"use strict";
var FuncFlatten = function () {
var codeList = [];
for (var i = 0; i < arguments.length; i++) {
codeList[i] = arguments[i];
}
return {
add: function () {
for (var i = 0; i < arguments.length; i++) {
codeList.push(arguments[i]);
}
},
run: function () {
var runner = new FuncFlattenRunner();
runner['add'].apply(runner, codeList);
return runner['next'].apply(runner, arguments);
}
};
};
var FuncFlattenRunner = function () {
var codeList = [];
for (var i = 0; i < arguments.length; i++) {
codeList[i] = arguments[i];
}
return {
add: function () {
for (var i = 0; i < arguments.length; i++) {
codeList.push(arguments[i]);
}
},
next: function () {
var nextCode = codeList.shift();
return nextCode.apply(this, arguments);
}
};
};
var run_flatten = function () {
var ff = new FuncFlatten();
ff['add'].apply(ff, arguments);
ff.run();
};
run_flatten(
function () {
console.log(1);
var self = this;
setTimeout(function () { self.next(); }, 1000);
},
function () {
console.log(2);
var self = this;
setTimeout(function () { self.next(); }, 1000);
},
function () {// last
console.log(3);
}
);
"use strict";
var run_flatten = function () {
var i = arguments.length - 1;
var code = arguments[i];
while (--i >= 0) {
(function (next, cb) {
code = function () {
var args = [cb];
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
next.apply(this, args);
};
})(arguments[i], code);
}
code();
};
run_flatten(
function (next) {
console.log(1);
setTimeout(next, 1000);
},
function (next) {
console.log(2);
setTimeout(next, 1000);
},
function () {// last
console.log(3);
}
);
use strict;
use warnings;
use utf8;
use 5.10.0;
use AnyEvent;
import Code::Flatten;
my $cv = AnyEvent->condvar;
run_flatten(
sub {
my $next = shift;
say 1;
my $t; $t = AnyEvent->timer(
after => 1,
cb => sub {
$next->();
undef $t;
}
);
},
sub {
my $next = shift;
say 2;
my $t; $t = AnyEvent->timer(
after => 1,
cb => sub {
$next->();
undef $t;
}
);
},
sub {# last
say 3;
$cv->broadcast;
},
);
$cv->wait;
package Code::Flatten;
use strict;
use warnings;
use utf8;
use Carp ();
use Scalar::Util ();
use Class::Accessor::Lite (
rw => [
qw/code_list/
]
);
use overload (
'&{}' => sub {
my $self = shift;
Scalar::Util::weaken($self);
sub { $self->run(@_) };
},
fallback => 1,
);
sub import {
my $class = shift;
my $caller = caller;
my $code = sub { $class->new(@_)->run };
{
no strict 'refs';
*{"${caller}::run_flatten"} = $code;
}
}
sub new {
my $class = shift;
bless(+{ code_list => [] } => $class)->add(@_);
}
sub add {
my $self = shift;
push @{ $self->code_list } => @_;
return $self;
}
sub run {
my $self = shift;
return Code::Flatten::Runner->new(@{ $self->code_list })->next(@_);
}
package Code::Flatten::Runner;
use strict;
use warnings;
use utf8;
use Scalar::Util ();
use overload (
'&{}' => sub {
my $self = shift;
Scalar::Util::weaken($self);
sub { $self->next(@_) };
},
fallback => 1,
);
use Class::Accessor::Lite (
rw => [
qw/code_list/
]
);
sub new {
my $class = shift;
bless(+{ code_list => [] } => $class)->add(@_);
}
sub add {
my $self = shift;
push @{ $self->code_list } => @_;
return $self;
}
sub next {
my $self = shift;
my $code = shift @{ $self->code_list };
Scalar::Util::weaken($self);
return $self->$code(@_);
}
use strict;
use warnings;
use utf8;
use 5.10.0;
use AnyEvent;
my $cv = AnyEvent->condvar;
run_flatten(
sub {
my $next = shift;
say 1;
my $t; $t = AnyEvent->timer(
after => 1,
cb => sub {
$next->();
undef $t;
}
);
},
sub {
my $next = shift;
say 2;
my $t; $t = AnyEvent->timer(
after => 1,
cb => sub {
$next->();
undef $t;
}
);
},
sub {# last
say 3;
$cv->broadcast;
},
);
$cv->wait;
sub run_flatten {
my $code = pop;
while (my $next = pop) {
my $cb = $code;
$code = sub { $next->($cb, @_) };
}
$code->();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment