Skip to content

Instantly share code, notes, and snippets.

@loganlinn
Created December 5, 2013 20:16
Show Gist options
  • Save loganlinn/7813092 to your computer and use it in GitHub Desktop.
Save loganlinn/7813092 to your computer and use it in GitHub Desktop.
<?php
function all_gens_valid($gens) {
foreach ($gens as $gen) {
if (!$gen->valid()) {
return false;
}
}
return true;
}
function gen_map($f /*, $gens... */) {
$gens = func_get_args();
array_shift($gens);
while (all_gens_valid($gens)) {
$vals = [];
foreach ($gens as $gen) {
$vals[] = $gen->current();
$gen->next();
}
yield call_user_func_array($f, $vals);
}
}
function gen_reduce($gen, $f, $initial=null) {
$memo = $initial;
foreach($gen as $item) {
$memo = $f($memo, $item);
}
return $memo;
}
function gen_filter($gen, $f=null) {
if (!$f) {
$f = function($item) { return $item !== null; };
}
foreach ($gen as $k => $item) {
if ($f($item)) {
yield $k => $item;
}
}
}
function gen_combine($keyGen, $valGen) {
while ($keyGen->valid() && $valGen->valid()) {
yield $keyGen->current() => $valGen->current();
$keyGen->next();
$valGen->next();
}
}
////////////////////////////////////////////////////////////////////////////////
function xrange($start, $limit, $step = 1) {
if ($start < $limit) {
if ($step <= 0) {
throw new LogicException('Step must be +ve');
}
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
if ($step >= 0) {
throw new LogicException('Step must be -ve');
}
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
function gen_to_array($gen) {
$a = [];
while($gen->valid()) {
$a[$gen->key()] = $gen->current();
$gen->next();
}
return $a;
}
function array_to_gen($array) {
foreach ($array as $k => $v) {
yield $k => $v;
}
}
////////////////////////////////////////////////////////////////////////////////
assert(
gen_to_array(gen_map(function($x) { return $x + 1; }, xrange(0, 1)))
==
array_map(function($x) { return $x + 1; }, range(0, 1))
);
assert(
gen_to_array(gen_map(
function($x, $y) { return $x + $y; },
xrange(0, 2),
xrange(0, 2)
))
==
array_map(
function($x, $y) { return $x + $y; },
range(0, 2),
range(0, 2)
)
);
assert(
gen_reduce(
xrange(0, 10),
function($sum, $i) { return $sum + $i; },
0
)
==
array_reduce(
range(0, 10),
function($sum, $i) { return $sum + $i; },
0
)
);
assert(
gen_to_array(gen_filter(
xrange(0, 10),
function($x) { return ($x % 2 == 0); }
))
==
array_filter(
range(0, 10),
function($x) { return ($x % 2 == 0); }
)
);
assert(
gen_to_array(gen_filter(
[1, null, 2, null, 3, null]
))
==
array_filter(
[1, null, 2, null, 3, null]
)
);
assert(
gen_to_array(gen_combine(
array_to_gen([2, 4, 6]),
array_to_gen([3, 5, 7])
))
==
array_combine(
[2, 4, 6],
[3, 5, 7]
)
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment