return sum(func_get_args()); }, $n), range(1, $n)) !== sum(range(1, $n)); }, 'arity1' => function () { return arity(function ($a, $b) { }) !== 2; }, 'arity2' => function ($n) { return arity(nary(function () { }, $n % 100)) !== $n % 100; }, 'arity3' => function () { return arity('plus') !== 2; }, 'arity4' => function () { return arity(plus(2)) !== 1; }, 'arity5' => function () { return arity(flip('plus')) !== 2; }, 'key_map' => function () { return key_map('plus', [1 => 2, 4 => 8, 16 => 32]) !== [1 => 3, 4 => 12, 16 => 48]; }, 'flip1' => function () { return flip(array_(2), 1, 2) !== [2, 1]; }, 'flip2' => function () { return flip('map', [-1, -2], plus(5)) !== [4, 3]; }, 'compose1' => function ($x, $y, $z) { return call(compose(plus($x), mult($y)), $z) !== $x + $y * $z; }, 'compose2' => function ($x, $y, $z) { return call(compose(mult($x), plus($y)), $z) !== $x * ($y + $z); }, 'compose3' => function ($x, $y, $z) { $f = flip('map', [$x, $y]); $c = compose($f, 'plus'); return $c($z) !== [$x + $z, $y + $z]; }, 'compose4' => function ($n) { return call(compose('id', 'id'), $n) !== $n; }, 'compose5' => function ($x, $y, $z) {
eval("function {$name}() {\n static \$defined = true; // Used by arity\n static \$f = NULL;\n \$args = func_get_args();\n return (is_null(\$f))? \$f = \$args[0]\n : call_user_func_array(\$f, \$args);\n }"); // Initialise $f to $expr return $name($curry($expr)); }; // Make these functions available in curried form $defun('defun', $defun); defun('op', function ($x) use($op) { return in_array($x, array('array', 'new')) ? $op($x) : curry($op($x)); }); defun('curry', $curry); defun('curry_', $curry_); defun('arity', $arity); }); defun('key_map', function ($f, $a) { return array_combine(array_keys($a), array_map(op($f), array_keys($a), $a)); }); defun('defuns', key_map('defun')); defuns(array('uncurry' => function ($f, $args) { return call_user_func_array(op($f), $args); }, 'up_to' => function ($n) { return $n ? range(0, $n - 1) : array(); }, 'random' => function ($_) { return abs(mt_rand()); })); // Like call_user_func but uses curry & op. We don't curry call since it's nary. function call() { $args = func_get_args(); $f = op(array_shift($args)); return call_user_func_array($f, $args); }
} defun('implode_', 'implode'); defun('join_', implode_('')); defun('concat', function ($n) { return compose('join_', array_($n)); }); defun('thunk', function ($x, $_) { return $x; }); defun('nil', thunk([])); defuns(['filter' => flip(nary('array_filter', 2)), 'sum' => nary('array_sum', 1)]); defuns(['keys' => nary('array_keys', 1), 'values' => nary('array_values', 1), 'merge' => nary('array_merge', 2), 'foldr' => function ($f, $zero, $arr) { // Take args in a sane order return array_reduce($arr, $f, $zero); }, 'key_foldr' => function ($f, $zero) { return compose(foldr($f, $zero), key_map(array_(2))); }, 'subscript' => function ($x, $y) { return $x[$y]; }, 'take' => function ($n, $a) { return array_slice($a, 0, $n); }, 'cons' => function ($x, $y) { return merge([$x], $y); }, 'snoc' => function ($x, $y) { return merge($y, [$x]); }, 'echo_' => function ($x) { echo $x; return $x; }, 'id' => function ($x) { return $x; }, 'chain' => function ($x, $y, $z) { return $x($z, $y($z));
<?php require_once __DIR__ . '/vendor/autoload.php'; key_map(function ($name, $test) { echo "Checking {$name}: "; if ($result = $test()) { var_dump($result); die; } echo "Passed\n"; }, array('sample counts correctly' => function () { $n = abs(mt_rand()) & 255; $result = sample(function () { return null; }, $n); return $result === array_fill(0, $n, null) ? 0 : get_defined_vars(); }, 'truthy tests fail' => function () { $result = runtests(function () { return true; }); return count($result) === 0 ? 0 : get_defined_vars(); }, 'falsy tests pass' => function () { $pre = runtests(null); deftest('falsy', function () { }); $results = array_diff_key(runtests(null), $pre); return array() === $results ? 0 : get_defined_vars(); }));
<?php set_error_handler(function () { var_dump(array('args' => func_get_args(), 'trace' => debug_backtrace())); die; }); defun('sample', function ($f, $n) { return array_map($f, up_to($n)); }); defuns(call_user_func(function () { $tests = array(); $run = function ($t) { return call_user_func_array($t[0], sample('random', $t[1])); }; return array('deftest' => function ($name, $test) use(&$tests) { $tests[$name] = array($test, arity($test)); }, 'runtests' => function ($t) use(&$tests, $run) { return is_array($t) ? $run($t) : array_filter(array_map($run, $tests)); }, 'deftests' => key_map('deftest')); }));