3v4l.org

run code in 300+ PHP versions simultaneously
<?php namespace igorw\reasoned { // microKanren implementation class Variable { public $name; function __construct($name) { $this->name = $name; } function is_equal(Variable $var) { return $this->name === $var->name; } } function variable($name) { return new Variable($name); } function is_variable($x) { return $x instanceof Variable; } class Substitution { public $values; function __construct(array $values = []) { $this->values = $values; } function walk($u) { if (is_variable($u) && null !== $value = $this->find($u)) { return $this->walk($value); } return $u; } function find(Variable $var) { foreach ($this->values as list($x, $value)) { if ($var->is_equal($x)) { return $value; } } return null; } function extend(Variable $x, $value) { return new Substitution(array_merge( [[$x, $value]], $this->values )); } function length() { return count($this->values); } function reify($v) { $v = $this->walk($v); if (is_variable($v)) { $n = reify_name($this->length()); return $this->extend($v, $n); } if (is_unifiable_array($v)) { return $this->reify(first($v)) ->reify(rest($v)); } return $this; } } class State { public $subst; public $count; function __construct(Substitution $subst = null, $count = 0) { $this->subst = $subst ?: new Substitution(); $this->count = $count; } function next() { return new State($this->subst, $this->count + 1); } function reify() { $v = walk_star(variable(0), $this->subst); return walk_star($v, (new Substitution())->reify($v)); } } function eq($u, $v) { return function (State $state) use ($u, $v) { $subst = unify($u, $v, $state->subst); if ($subst) { return unit(new State($subst, $state->count)); } return mzero(); }; } function unit(State $state) { return new PairStream($state, mzero()); } function mzero() { return new EmptyStream(); } function is_unifiable_array($value) { return is_pair($value) || is_array($value) && count($value) > 0; } class Pair { public $first; public $rest; function __construct($first, $rest) { $this->first = $first; $this->rest = $rest; } } function pair($first, $rest) { return new Pair($first, $rest); } function is_pair($x) { return $x instanceof Pair; } function unify($u, $v, Substitution $subst) { $u = $subst->walk($u); $v = $subst->walk($v); if (is_variable($u) && is_variable($v) && $u->is_equal($v)) { return $subst; } if (is_variable($u)) { return $subst->extend($u, $v); } if (is_variable($v)) { return $subst->extend($v, $u); } if (is_unifiable_array($u) && is_unifiable_array($v)) { $subst = unify(first($u), first($v), $subst); return $subst ? unify(rest($u), rest($v), $subst) : null; } if ($u === $v) { return $subst; } return null; } // $f takes a fresh variable and returns a goal function call_fresh(callable $f) { return function (State $state) use ($f) { $goal = $f(variable($state->count)); return $goal($state->next()); }; } // same as call_fresh, but without fresh var function delay(callable $f) { return function (State $state) use ($f) { $goal = $f(); return $goal($state->next()); }; } function disj(callable $goal1, callable $goal2) { return function (State $state) use ($goal1, $goal2) { return $goal1($state)->mplus($goal2($state)); }; } function conj(callable $goal1, callable $goal2) { return function (State $state) use ($goal1, $goal2) { return $goal1($state)->bind($goal2); }; } function cons($value, array $list) { array_unshift($list, $value); return $list; } function first($list) { if (is_pair($list)) { return $list->first; } return array_shift($list); } function rest($list) { if (is_pair($list)) { return $list->rest; } array_shift($list); return $list; } interface Stream extends \IteratorAggregate { function mplus(Stream $stream2); function bind(callable $goal); } class EmptyStream implements Stream { function mplus(Stream $stream2) { return $stream2; } function bind(callable $goal) { return mzero(); } function getIterator() { return new \EmptyIterator(); } } class CallableStream implements Stream { public $f; function __construct(callable $f) { $this->f = $f; } function mplus(Stream $stream2) { return new CallableStream(function () use ($stream2) { return $stream2->mplus($this->resolve()); }); } function bind(callable $goal) { return new CallableStream(function () use ($goal) { return $this->resolve()->bind($goal); }); } function getIterator() { return $this->resolve()->getIterator(); } function resolve() { return call_user_func($this->f); } } class PairStream implements Stream { public $first; public $rest; function __construct($first, Stream $rest) { $this->first = $first; $this->rest = $rest; } function mplus(Stream $stream2) { return new PairStream($this->first, $this->rest->mplus($stream2)); } function bind(callable $goal) { return $goal($this->first)->mplus($this->rest->bind($goal)); } function getIterator() { yield $this->first; foreach ($this->rest as $x) { yield $x; } } } // recovering miniKanren's control operators function zzz(callable $goal) { return function (State $state) use ($goal) { return new CallableStream(function () use ($goal, $state) { return $goal($state); }); }; } function conj_plus(array $goals) { if (count($goals) === 0) { throw new \InvalidArgumentException('Must supply at least one goal'); } if (count($goals) === 1) { return zzz(first($goals)); } return conj(zzz(first($goals)), conj_plus(rest($goals))); } function disj_plus(array $goals) { if (count($goals) === 0) { throw new \InvalidArgumentException('Must supply at least one goal'); } if (count($goals) === 1) { return zzz(first($goals)); } return disj(zzz(first($goals)), disj_plus(rest($goals))); } function conde(array $lines) { return disj_plus(array_map('igorw\reasoned\conj_plus', $lines)); } // based heavily on mudge/php-microkanren function fresh(callable $f) { $argCount = (new \ReflectionFunction($f))->getNumberOfParameters(); if ($argCount === 0) { return delay($f); } return call_fresh(function ($x) use ($f, $argCount) { return collect_args($f, $argCount, [$x]); }); } function collect_args(callable $f, $argCount, $args) { if (count($args) === $argCount) { return call_user_func_array($f, $args); } return call_fresh(function ($x) use ($f, $argCount, $args) { return collect_args($f, $argCount, array_merge($args, [$x])); }); } // from streams to lists // @todo use iter? function take($n, $stream) { foreach ($stream as $x) { if ($n-- === 0) { break; } yield $x; } } function map(callable $f, $stream) { foreach ($stream as $x) { yield $f($x); } } function to_array($stream) { $array = []; foreach ($stream as $x) { $array[] = $x; } return $array; } // recovering reification function reify($states) { return map(function (State $state) { return $state->reify(); }, $states); } function reify_name($n) { return "_.$n"; } function walk_star($v, Substitution $subst) { $v = $subst->walk($v); if (is_variable($v)) { return $v; } if (is_pair($v)) { $first = walk_star(first($v), $subst); $rest = walk_star(rest($v), $subst); if (is_array($rest)) { return cons($first, $rest); } return [$first, '.', $rest]; } if (is_unifiable_array($v)) { return cons(walk_star(first($v), $subst), walk_star(rest($v), $subst)); } return $v; } // recovering the scheme interface function call_goal(callable $goal) { return $goal(new State()); } function run($n, callable $goal) { return to_array(take($n, reify(call_goal(fresh($goal))))); } function run_star(callable $goal) { return to_array(reify(call_goal(fresh($goal)))); } function all(array $goals) { return conj_plus($goals); } // unicode madness function ≡($u, $v) { return eq($u, $v); } function ⋀(array $goals) { return conj_plus($goals); } function ⋁(array $goals) { return disj_plus($goals); } function run٭(callable $goal) { return run_star($goal); } function condᵉ(array $lines) { return conde($lines); } // user level plumbing function conso($a, $d, $l) { return eq(pair($a, $d), $l); } function firsto($l, $a) { return fresh(function ($d) use ($l, $a) { return conso($a, $d, $l); }); } function resto($l, $d) { return fresh(function ($a) use ($l, $d) { return conso($a, $d, $l); }); } function appendo($l, $s, $out) { return conde([ [eq($l, []), eq($s, $out)], [fresh(function ($a, $d, $res) use ($l, $s, $out) { return all([ conso($a, $d, $l), conso($a, $res, $out), appendo($d, $s, $res), ]); })], ]); } // user level unicode madness function consᵒ($a, $d, $l) { return conso($a, $d, $l); } function firstᵒ($l, $a) { return firsto($l, $a); } function restᵒ($l, $d) { return resto($l, $d); } function appendᵒ($l, $s, $out) { return appendo($l, $s, $out); } // debugging goals (inspired by core.logic) function log($msg) { return function (State $state) use ($msg) { echo "$msg\n"; return unit($state); }; } function trace_subst() { return function (State $state) { var_dump($state->subst); return unit($state); }; } function trace_lvars(array $vars) { return function (State $state) use ($vars) { foreach ($vars as $var) { $v = walk_star($var, $state->subst); $reified = walk_star($v, (new Substitution())->reify($v)); if (is_variable($var) && is_string($reified)) { echo "variable({$var->name}) = $reified\n"; } else if (is_variable($var)) { echo "variable({$var->name}) =\n"; var_dump($reified); } else { var_dump($reified); } } return unit($state); }; } } namespace { use igor\reasoned as i; i\run(function ($q) { return i\eq($q, 'Hello'); }); }

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
8.3.60.0070.01318.43
8.3.50.0230.01021.14
8.3.40.0130.00619.04
8.3.30.0090.01320.29
8.3.20.0060.00318.98
8.3.10.0060.00321.09
8.3.00.0080.00023.61
8.2.180.0090.00917.00
8.2.170.0120.00322.96
8.2.160.0040.01120.65
8.2.150.0040.00424.18
8.2.140.0030.00524.66
8.2.130.0080.00026.16
8.2.120.0040.00419.76
8.2.110.0070.00322.08
8.2.100.0130.00018.09
8.2.90.0090.00018.16
8.2.80.0030.00519.21
8.2.70.0000.00817.75
8.2.60.0000.01018.05
8.2.50.0030.00518.10
8.2.40.0040.00420.58
8.2.30.0040.00421.21
8.2.20.0030.00617.79
8.2.10.0000.00817.85
8.2.00.0000.01217.93
8.1.280.0120.00325.92
8.1.270.0050.00323.99
8.1.260.0040.00426.35
8.1.250.0080.00028.09
8.1.240.0090.00023.84
8.1.230.0060.00622.52
8.1.220.0060.00318.03
8.1.210.0090.00018.91
8.1.200.0030.00617.60
8.1.190.0040.00417.38
8.1.180.0030.00618.10
8.1.170.0030.00618.59
8.1.160.0070.00022.38
8.1.150.0060.00618.77
8.1.140.0060.00317.55
8.1.130.0040.00417.99
8.1.120.0000.00717.60
8.1.110.0030.00517.59
8.1.100.0080.00017.57
8.1.90.0080.00017.47
8.1.80.0050.00217.48
8.1.70.0040.00417.57
8.1.60.0000.00917.71
8.1.50.0000.00817.64
8.1.40.0000.00917.70
8.1.30.0060.00317.77
8.1.20.0030.00617.80
8.1.10.0080.00017.71
8.1.00.0000.00817.71
8.0.300.0090.00021.90
8.0.290.0030.00716.88
8.0.280.0050.00218.65
8.0.270.0040.00417.50
8.0.260.0030.00317.03
8.0.250.0070.00017.20
8.0.240.0000.00817.28
8.0.230.0040.00417.23
8.0.220.0000.00717.12
8.0.210.0000.00717.15
8.0.200.0000.00717.22
8.0.190.0000.00717.16
8.0.180.0000.00817.15
8.0.170.0040.00417.04
8.0.160.0080.00017.04
8.0.150.0080.00017.16
8.0.140.0040.00417.14
8.0.130.0000.00613.64
8.0.120.0040.00417.20
8.0.110.0030.00617.04
8.0.100.0080.00017.04
8.0.90.0030.00617.19
8.0.80.0070.01017.16
8.0.70.0080.00017.24
8.0.60.0050.00317.20
8.0.50.0030.00517.08
8.0.30.0080.01117.43
8.0.20.0120.00617.40
8.0.10.0050.00317.08
8.0.00.0130.00616.88
7.4.330.0000.00616.83
7.4.320.0050.00316.68
7.4.300.0030.00316.73
7.4.290.0000.00816.66
7.4.280.0070.00016.75
7.4.270.0040.00416.63
7.4.260.0030.00313.54
7.4.250.0030.00616.55
7.4.240.0040.00416.75
7.4.230.0000.00816.45
7.4.220.0090.01116.66
7.4.210.0050.01216.75
7.4.200.0040.00416.66
7.4.190.0080.00016.46
7.4.160.0030.01516.53
7.4.150.0170.00617.40
7.4.140.0060.01317.86
7.4.130.0070.01416.70
7.4.120.0040.01516.67
7.4.110.0150.00616.59
7.4.100.0030.01516.87
7.4.90.0140.00716.72
7.4.80.0040.01419.39
7.4.70.0060.01916.57
7.4.60.0040.01416.59
7.4.50.0030.00616.77
7.4.40.0090.00322.77
7.4.30.0070.01216.66
7.4.10.0130.00714.99
7.4.00.0040.01115.23
7.3.330.0050.00013.55
7.3.320.0040.00413.41
7.3.310.0040.00416.30
7.3.300.0030.00416.44
7.3.290.0060.00916.54
7.3.280.0070.01216.53
7.3.270.0090.01117.40
7.3.260.0100.00818.24
7.3.250.0180.02416.59
7.3.240.0070.01016.57
7.3.230.0060.01216.77
7.3.210.0120.00616.80
7.3.200.0070.01119.39
7.3.190.0070.01016.68
7.3.180.0160.00016.70
7.3.170.0110.01416.62
7.3.160.0100.00716.76
7.3.130.0090.00915.09
7.3.120.0070.01115.05
7.3.110.0110.00715.17
7.3.100.0070.01015.06
7.3.90.0050.00914.85
7.3.80.0070.00614.94
7.3.70.0030.01115.09
7.3.60.0080.00314.98
7.3.50.0090.00714.97
7.3.40.0080.00514.98
7.3.30.0070.00814.94
7.3.20.0030.01216.49
7.3.10.0090.00816.50
7.3.00.0060.00316.76
7.2.330.0080.01116.66
7.2.320.0140.01016.58
7.2.310.0140.01116.90
7.2.300.0030.02016.73
7.2.290.0070.01016.83
7.2.260.0100.01015.11
7.2.250.0040.01415.11
7.2.240.0050.01115.09
7.2.230.0070.00914.93
7.2.220.0050.00915.03
7.2.210.0030.01114.97
7.2.200.0100.00315.05
7.2.190.0050.01015.05
7.2.180.0070.00915.00
7.2.170.0020.01115.02
7.2.160.0030.00815.20
7.2.150.0020.01516.73
7.2.140.0040.01116.89
7.2.130.0030.00916.85
7.2.120.0100.00516.75
7.2.110.0080.00816.85
7.2.100.0020.01516.85
7.2.90.0050.00816.88
7.2.80.0070.01016.72
7.2.70.0050.01216.83
7.2.60.0080.00516.80
7.2.50.0110.00516.77
7.2.40.0030.01416.90
7.2.30.0080.00916.83
7.2.20.0040.01116.78
7.2.10.0020.01616.87
7.2.00.0040.01117.62
7.1.330.0100.00615.74
7.1.320.0060.00915.49
7.1.310.0050.00815.82
7.1.300.0050.00815.77
7.1.290.0060.00415.59
7.1.280.0050.00915.73
7.1.270.0050.00915.76
7.1.260.0050.00815.79
7.1.250.0080.00815.79
7.1.240.0030.01015.79
7.1.230.0050.01315.71
7.1.220.0040.00915.71
7.1.210.0040.00715.78
7.1.200.0050.00915.57
7.1.190.0080.00615.65
7.1.180.0080.00515.81
7.1.170.0030.01115.78
7.1.160.0060.00615.73
7.1.150.0080.01015.69
7.1.140.0030.01215.66
7.1.130.0050.01015.67
7.1.120.0030.01115.71
7.1.110.0080.00715.78
7.1.100.0030.01116.38
7.1.90.0030.01115.76
7.1.80.0030.01415.68
7.1.70.0040.00916.06
7.1.60.0020.01316.88
7.1.50.0090.00816.02
7.1.40.0050.01115.56
7.1.30.0090.00415.74
7.1.20.0020.01115.64
7.1.10.0060.01015.79
7.1.00.0050.02518.02
7.0.330.0060.01015.24
7.0.320.0010.01115.36
7.0.310.0040.01015.22
7.0.300.0090.00515.31
7.0.290.0060.00515.37
7.0.280.0080.00815.29
7.0.270.0080.00715.37
7.0.260.0070.00715.43
7.0.250.0050.01115.36
7.0.240.0070.00515.55
7.0.230.0060.00615.26
7.0.220.0060.00615.32
7.0.210.0080.00815.41
7.0.200.0060.00615.89
7.0.190.0100.00315.21
7.0.180.0040.00915.32
7.0.170.0030.01315.38
7.0.160.0080.00815.40
7.0.150.0080.00415.46
7.0.140.0070.02817.67
7.0.130.0060.00615.36
7.0.120.0040.00915.40
7.0.110.0050.00815.40
7.0.100.0160.02417.04
7.0.90.0090.02016.96
7.0.80.0030.02016.98
7.0.70.0060.01716.91
7.0.60.0030.03416.91
7.0.50.0040.02117.16
7.0.40.0030.03015.68
7.0.30.0060.02615.57
7.0.20.0070.01815.57
7.0.10.0040.02115.60
7.0.00.0030.02015.70
5.6.400.0070.00514.35
5.6.390.0060.01014.41
5.6.380.0090.00614.28
5.6.370.0020.01314.41
5.6.360.0060.01114.36
5.6.350.0100.00414.18
5.6.340.0060.00914.34
5.6.330.0070.00614.43
5.6.320.0080.00914.43
5.6.310.0030.00814.58
5.6.300.0070.01014.32
5.6.290.0030.01114.24
5.6.280.0030.03416.66
5.6.270.0020.01314.29
5.6.260.0060.00814.17
5.6.250.0070.03116.64
5.6.240.0020.02416.55
5.6.230.0070.01816.38
5.6.220.0060.01916.42
5.6.210.0070.02116.42
5.6.200.0040.02216.65
5.6.190.0070.02216.66
5.6.180.0090.01616.70
5.6.170.0080.01516.57
5.6.160.0050.02016.56
5.6.150.0060.02316.63
5.6.140.0020.03116.55
5.6.130.0040.02516.73
5.6.120.0040.02016.69
5.6.110.0040.02016.48
5.6.100.0060.02016.74
5.6.90.0070.01816.60
5.6.80.0050.02016.28
5.6.70.0030.01816.34
5.6.60.0030.01916.27
5.6.50.0080.01816.42
5.6.40.0050.01816.35
5.6.30.0050.01816.25
5.6.20.0080.01716.21
5.6.10.0030.01816.38
5.6.00.0040.02216.33
5.5.380.0090.01716.46
5.5.370.0040.01916.38
5.5.360.0020.02316.49
5.5.350.0080.01916.24
5.5.340.0060.02316.34
5.5.330.0040.02716.48
5.5.320.0100.02816.31
5.5.310.0060.03016.58
5.5.300.0040.02716.54
5.5.290.0070.02016.40
5.5.280.0100.01516.58
5.5.270.0040.01916.43
5.5.260.0020.02116.62
5.5.250.0010.02916.29
5.5.240.0040.01716.23
5.5.230.0060.02016.10
5.5.220.0050.01816.15
5.5.210.0030.02016.29
5.5.200.0020.02316.24
5.5.190.0060.02116.21
5.5.180.0020.02216.20
5.5.170.0050.00814.16
5.5.160.0050.02116.26
5.5.150.0050.01916.33
5.5.140.0010.02016.31
5.5.130.0020.03316.27
5.5.120.0090.02416.14
5.5.110.0070.03216.27
5.5.100.0120.02516.06
5.5.90.0070.03116.09
5.5.80.0070.03516.11
5.5.70.0080.03316.27
5.5.60.0070.02616.13
5.5.50.0100.03616.18
5.5.40.0090.02816.20
5.5.30.0060.03016.08
5.5.20.0090.03116.25
5.5.10.0090.02916.16
5.5.00.0060.03316.24
5.4.450.0050.02114.08
5.4.440.0040.01813.96
5.4.430.0030.01814.06
5.4.420.0050.01514.09
5.4.410.0060.01314.02
5.4.400.0030.01713.94
5.4.390.0030.01913.92
5.4.380.0060.02013.92
5.4.370.0050.01513.92
5.4.360.0040.01713.92
5.4.350.0020.02113.86
5.4.340.0050.02113.92
5.4.330.0000.01411.36
5.4.320.0080.02013.92
5.4.310.0030.02313.92
5.4.300.0060.02713.97
5.4.290.0020.03313.96
5.4.280.0040.02613.91
5.4.270.0050.02913.92
5.4.260.0090.02413.92
5.4.250.0030.02413.92
5.4.240.0080.02813.97
5.4.230.0060.02413.92
5.4.220.0050.02213.92
5.4.210.0060.02913.93
5.4.200.0050.03013.87
5.4.190.0060.02213.92
5.4.180.0040.03313.87
5.4.170.0060.03013.97
5.4.160.0070.02713.85
5.4.150.0050.03313.95
5.4.140.0080.01613.04
5.4.130.0090.02413.06
5.4.120.0070.02713.07
5.4.110.0070.02913.07
5.4.100.0030.03113.08
5.4.90.0050.02913.08
5.4.80.0060.02713.01
5.4.70.0070.02713.09
5.4.60.0040.03113.03
5.4.50.0080.02413.07
5.4.40.0070.01513.06
5.4.30.0090.02313.07
5.4.20.0030.02713.02
5.4.10.0040.02813.03
5.4.00.0070.01612.88
5.3.290.0070.01612.44
5.3.280.0080.02912.42
5.3.270.0060.02712.46
5.3.260.0060.02912.45
5.3.250.0100.02512.43
5.3.240.0110.01812.42
5.3.230.0090.02612.42
5.3.220.0110.02412.43
5.3.210.0060.02512.41
5.3.200.0090.02612.47
5.3.190.0040.02812.47
5.3.180.0030.02812.40
5.3.170.0060.02912.42
5.3.160.0050.02612.43
5.3.150.0030.03212.39
5.3.140.0080.02412.45
5.3.130.0070.02512.42
5.3.120.0030.02712.45
5.3.110.0060.01412.47
5.3.100.0050.02212.29
5.3.90.0080.02612.27
5.3.80.0080.01112.26
5.3.70.0040.02312.24
5.3.60.0050.02412.29
5.3.50.0040.02912.22
5.3.40.0010.03212.24
5.3.30.0070.01412.21
5.3.20.0040.02912.19
5.3.10.0080.02512.12
5.3.00.0060.02512.09

preferences:
40.26 ms | 401 KiB | 5 Q