Skip to content

Instantly share code, notes, and snippets.

@kaja47
Created May 3, 2012 17:31
Show Gist options
  • Save kaja47/2587452 to your computer and use it in GitHub Desktop.
Save kaja47/2587452 to your computer and use it in GitHub Desktop.
Object oriented system made only from functions
<?php
// If you want to make an object oriented system from scratch, you must first create the universe.
// Only things you need are functions
function cons($h, $t) {
return function($what) use($h, $t) {
return ($what[0] === 'h') ? $h : $t;
};
}
$__nilFunction = function() { return null; };
function nil() {
global $__nilFunction;
return $__nilFunction;
}
function makeList() {
return array_reduce(array_reverse(func_get_args()), function ($res, $arg) { return cons($arg, $res); }, nil());
}
function head($l) { return $l === nil() ? null : $l('head'); }
function tail($l) { return $l === nil() ? nil() : $l('tail'); }
function find($l, $f) {
if ($l === nil()) return null;
else {
$h = head($l);
$t = tail($l);
if ($f($h)) return $h;
else return find($t, $f);
}
}
function concat($prefix, $suffix) {
if ($suffix === nil()) return $prefix;
else if ($prefix === nil()) return $suffix;
else {
$x = function ($l) use(&$x, $suffix) {
if ($l !== nil()) {
$h = head($l);
$t = tail($l);
return cons($h, $x($t));
} else {
return $suffix;
}
};
return $x($prefix);
}
}
function deleg($childMethods, $parentMethods) {
return concat($childMethods, $parentMethods);
}
function call($object, $method) {
$m = find($object, function ($x) use($method) { return head($x) === $method; });
$m = tail($m);
return $m($object);
}
// you can call methods on prettyfied objects by passing arguments to this object
// $obj('method') insted od call($obj, 'method')
function prettify($methods) { return function ($method) use($methods) { return call($methods, $method); }; }
function property($val) { return function () use($val) { return $val; }; }
// objects are nothing more than collections of methods
$parent = makeList(
cons("x", function ($self) { return 'parent.x'; }),
cons("y", function ($self) { return 'parent.y -> ' . call($self, 'x'); })
);
$childMethods = makeList(
cons("x", function ($self) { return 'child.x'; })
);
$child = deleg($childMethods, $parent);
var_dump( call($parent, 'x') === 'parent.x' );
var_dump( call($parent, 'y') === 'parent.y -> parent.x');
var_dump( call($child, 'x') === 'child.x' );
var_dump( call($child, 'y') === 'parent.y -> child.x'); // look ma, virtual call and open recursion
$makePerson = function ($name, $mail) {
return makeList(
cons('name', property($name)),
cons('mail', property($mail)),
cons('contact', function ($self) { return 'name: ' . call($self, 'name') . ' mail: ' . call($self, 'mail'); })
);
};
$person = $makePerson('kaja47', '[email protected]');
$person2 = deleg(makeList(cons('name', property('Anonymous'))), $person);
var_dump(call($person, 'contact') === "name: kaja47 mail: [email protected]");
var_dump(call($person2, 'contact') === "name: Anonymous mail: [email protected]");
$pp = prettify($person);
var_dump($pp('contact') === "name: kaja47 mail: [email protected]");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment