@ 2018-10-24T06:57:15Z <?php
$f = function(int $i) {
var_dump($i);
};
// Some::new()
// Some::match()
final class Mangling
{
private $mangle = [];
public function __construct(...$args)
{
foreach ($args as $arg) {
if ($arg !== null) {
if (is_callable($arg)) {
$this->mangle[] = serialize($arg);
} else {
$this->mangle[] = (string) $arg;
}
} else {
$this->mangle[] = '_';
}
}
}
public static function new(...$args): self
{
return new self(...$args);
}
public function implode(string $glue): string
{
return implode($glue, $this->mangle);
}
}
const _ = null;
interface MatchingInterface
{
public function matches(array $cases): void;
}
interface DestructureInterface
{
public function destruct(): array;
}
trait MatchingTrait
{
private $mangling;
private $values = [];
public function __construct(...$values)
{
$this->mangling = new Mangling(...$values);
$this->values = $values;
}
public static function new(...$values): self
{
return new self($values);
}
private static function into(Mangling $mangling): string
{
return sprintf('%s(%s)', static::class, $mangling->implode(','));
}
public static function match(...$values): string
{
return self::into(new Mangling(...$values));
}
private static function unserialize(string $s)
{
return @unserialize($s);
}
private function getPatternMatchWith(array $pattern): array
{
$cp = count($pattern);
$mangle = [];
$params = [];
foreach ($this->values as $index => $value) {
if ($index >= $cp) {
$params[] = $value;
continue;
}
if (array_key_exists($index, $pattern) && $pattern[$index] !== _) {
$pat = $pattern[$index];
if ($pat !== _) {
$closure = self::unserialize($pat);
if (is_callable($closure) && !$closure($value)) {
return ['mangle' => _, 'params' => []];
}
}
$params[] = $value;
$mangle[] = $value;
} else {
$mangle[] = _;
}
}
return ['mangle' => self::into(new Mangling(...$mangle)), 'params' => $params];
}
private static function intoPattern(string $mangling): array
{
$pattern = sprintf('/%s\((.+)\)/i', static::class);
if (preg_match($pattern, $mangling, $matches)) {
return array_map(function(string $param) {
return trim($param) === '_' ? _ : $param;
}, preg_split('/,\s*/', $matches[1]));
}
return [];
}
private function intoMangling(array $pattern): string
{
$output = [];
foreach ($pattern as $index => $value) {
if ($value !== _ && self::unserialize($value) !== false) {
$output[] = $this->values[$index];
} else {
$output[] = $value;
}
}
return self::into(new Mangling(...$output));
}
public function matches(array $cases): void
{
foreach ($cases as $mangling => $closure) {
$pattern = self::intoPattern($mangling);
['mangle' => $mangle, 'params' => $params] = $this->getPatternMatchWith($pattern);
if ($this->intoMangling($pattern) === $mangle) {
$closure(...$params);
break;
}
}
}
public function toString(): string
{
return sprintf('%s(%s)', static::class, $this->mangling->implode(','));
}
public function __toString(): string
{
return $this->toString();
}
}
trait DestructureTrait
{
public function destruct(): array
{
return $this->values;
}
}
interface ADTInterface extends MatchingInterface, DestructureInterface
{
}
trait ADTTrait
{
use MatchingTrait;
use DestructureTrait;
}
final class TypeClosure
{
private $name;
private $typecheck;
private $value;
public function __construct(string $name, callable $typecheck, &$value)
{
$this->name = $name;
$this->typecheck = $typecheck;
$this->value = &$value;
}
public function __invoke($param): bool {
$this->value = ($this->typecheck)($param) ? $param : _;
return $this->value !== _;
}
}
function typeof(string $name, callable $typecheck, &$value): TypeClosure
{
return new TypeClosure($name, $typecheck, $value);
}
function int(&$value = null): TypeClosure
{
return typeof('int', 'is_int', $value);
}
function any(&$value = null): TypeClosure
{
return typeof('any', function() {
return true;
}, $value);
}
function string(&$value = null): TypeClosure
{
return typeof('string', 'is_string', $value);
}
final class LetBinding
{
private $destructure;
public function __construct(DestructureInterface $destructure)
{
$this->destructure = $destructure;
}
public function be(...$closures): bool
{
$params = $this->destructure->destruct();
foreach ($closures as $index => $closure) {
if (array_key_exists($index, $params) && is_callable($closure)) {
$param = $params[$index];
if (!$closure($param)) {
return false;
}
}
}
return true;
}
}
function let(DestructureInterface $destructure): LetBinding
{
return new LetBinding($destructure);
}
interface Option { }
final class Some implements Option, ADTInterface
{
use ADTTrait;
}
$opt = new Some(42, 23);
print '#1: ';
$opt->matches([Some::match(_, 23) => $f]);
print '#2: ';
$opt->matches([Some::match(_) => $f]);
print '#3: ';
if (let($opt)->be(int($x), int($y))) {
var_dump($x);
var_dump($y);
}
print '#4: ';
if (let($opt)->be(_, int($y))) {
var_dump($y);
}
interface Gender { }
final class Male implements Gender, ADTInterface
{
use ADTTrait;
}
final class Female implements Gender, ADTInterface
{
use ADTTrait;
}
final class Other implements Gender, ADTInterface
{
use ADTTrait;
}
function gender1(Gender $gender): void
{
print '#5: ';
$gender->matches([Male::match(string($name), _) => function(string $name) {
var_dump($name);
}]);
}
function gender2(Gender $gender): void
{
print '#5: ';
$gender->matches([Male::match(_) => function(string $name) {
var_dump($name);
}]);
}
$gender = new Male('Hans', 'Franz');
gender1($gender);
gender2($gender);
Enable javascript to submit You have javascript disabled. You will not be able to edit any code.
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).
Version System time (s) User time (s) Memory (MiB) 8.3.6 0.009 0.009 18.80 8.3.5 0.004 0.012 18.40 8.3.4 0.010 0.010 19.35 8.3.3 0.012 0.003 19.21 8.3.2 0.006 0.003 19.33 8.3.1 0.005 0.003 22.07 8.3.0 0.009 0.000 20.71 8.2.18 0.011 0.011 18.71 8.2.17 0.016 0.003 22.96 8.2.16 0.009 0.006 20.99 8.2.15 0.005 0.003 24.18 8.2.14 0.006 0.003 24.66 8.2.13 0.006 0.003 20.07 8.2.12 0.006 0.003 26.35 8.2.11 0.017 0.007 21.06 8.2.10 0.004 0.011 18.16 8.2.9 0.006 0.003 18.00 8.2.8 0.009 0.000 17.97 8.2.7 0.003 0.006 18.18 8.2.6 0.000 0.008 18.41 8.2.5 0.008 0.000 18.10 8.2.4 0.004 0.004 19.45 8.2.3 0.005 0.003 19.30 8.2.2 0.005 0.003 18.14 8.2.1 0.004 0.004 18.13 8.2.0 0.009 0.000 17.98 8.1.28 0.006 0.013 25.92 8.1.27 0.004 0.007 19.08 8.1.26 0.000 0.008 26.35 8.1.25 0.008 0.000 28.09 8.1.24 0.009 0.000 22.63 8.1.23 0.007 0.004 22.30 8.1.22 0.000 0.009 17.91 8.1.21 0.003 0.006 18.77 8.1.20 0.003 0.007 17.63 8.1.19 0.007 0.004 17.60 8.1.18 0.009 0.000 18.10 8.1.17 0.003 0.005 18.60 8.1.16 0.000 0.009 19.13 8.1.15 0.000 0.008 19.10 8.1.14 0.004 0.004 22.34 8.1.13 0.003 0.006 17.67 8.1.12 0.000 0.008 17.75 8.1.11 0.000 0.008 17.73 8.1.10 0.000 0.009 17.75 8.1.9 0.000 0.008 17.69 8.1.8 0.004 0.004 17.69 8.1.7 0.004 0.004 17.57 8.1.6 0.004 0.004 17.75 8.1.5 0.004 0.007 17.60 8.1.4 0.005 0.003 17.71 8.1.3 0.003 0.005 17.81 8.1.2 0.003 0.005 17.92 8.1.1 0.008 0.000 17.71 8.1.0 0.004 0.004 17.63 8.0.30 0.000 0.008 18.90 8.0.29 0.003 0.005 17.00 8.0.28 0.005 0.003 18.61 8.0.27 0.005 0.002 17.31 8.0.26 0.000 0.007 17.18 8.0.25 0.003 0.006 17.25 8.0.24 0.007 0.000 17.18 8.0.23 0.003 0.006 17.28 8.0.22 0.008 0.000 17.25 8.0.21 0.005 0.002 17.22 8.0.20 0.000 0.007 17.26 8.0.19 0.004 0.004 17.22 8.0.18 0.005 0.003 17.28 8.0.17 0.006 0.003 17.16 8.0.16 0.003 0.006 17.21 8.0.15 0.006 0.003 17.14 8.0.14 0.000 0.008 17.14 8.0.13 0.004 0.004 13.69 8.0.12 0.006 0.003 17.21 8.0.11 0.003 0.007 17.22 8.0.10 0.004 0.004 17.02 8.0.9 0.008 0.000 17.21 8.0.8 0.011 0.009 17.17 8.0.7 0.005 0.003 17.20 8.0.6 0.000 0.008 17.18 8.0.5 0.005 0.003 17.27 8.0.3 0.010 0.010 17.40 8.0.2 0.010 0.010 17.53 8.0.1 0.004 0.004 17.45 8.0.0 0.013 0.009 16.97 7.4.33 0.006 0.000 15.55 7.4.32 0.007 0.000 16.85 7.4.30 0.007 0.000 16.90 7.4.29 0.000 0.007 16.86 7.4.28 0.000 0.010 16.83 7.4.27 0.004 0.004 16.94 7.4.26 0.004 0.004 16.81 7.4.25 0.004 0.004 16.82 7.4.24 0.003 0.005 16.95 7.4.23 0.002 0.005 16.69 7.4.22 0.009 0.000 17.04 7.4.21 0.010 0.008 16.87 7.4.20 0.000 0.007 16.95 7.4.16 0.010 0.008 16.94 7.4.14 0.010 0.010 17.86 7.4.13 0.016 0.003 16.83 7.4.12 0.011 0.008 16.89 7.4.11 0.017 0.007 16.80 7.4.10 0.016 0.003 16.88 7.4.9 0.011 0.007 16.66 7.4.8 0.008 0.013 19.39 7.4.7 0.013 0.006 16.92 7.4.6 0.012 0.006 16.80 7.4.5 0.010 0.007 16.93 7.4.4 0.009 0.009 16.93 7.3.33 0.003 0.003 13.67 7.3.32 0.000 0.006 13.57 7.3.31 0.009 0.000 16.60 7.3.30 0.004 0.004 16.73 7.3.29 0.000 0.007 16.68 7.3.28 0.006 0.016 16.65 7.3.26 0.013 0.009 16.81 7.3.24 0.007 0.011 16.83 7.3.23 0.006 0.011 16.78 7.3.21 0.009 0.012 17.03 7.3.20 0.017 0.000 16.94 7.3.19 0.012 0.012 17.03 7.3.18 0.007 0.010 16.78 7.3.17 0.011 0.014 16.80 7.3.16 0.013 0.003 16.97 7.2.33 0.011 0.008 17.05 7.2.32 0.010 0.010 16.99 7.2.31 0.008 0.011 17.07 7.2.30 0.009 0.009 17.13 7.2.29 0.007 0.011 16.98
preferences:dark mode live preview
58.46 ms | 401 KiB | 5 Q