Skip to content

Instantly share code, notes, and snippets.

@thekid
Last active August 29, 2015 14:18
Show Gist options
  • Select an option

  • Save thekid/ee6f46112dd0976aa63a to your computer and use it in GitHub Desktop.

Select an option

Save thekid/ee6f46112dd0976aa63a to your computer and use it in GitHub Desktop.
Iteration trait with extensions
<?php
use util\data\Sequence;
use lang\Error;
trait Iteration {
public static $extensions= [];
public function __call($name, $args) {
if (isset(Iteration::$extensions[$name])) {
return Iteration::$extensions[$name]($this, ...$args);
}
throw new Error('Call to non-existant '.nameof($this).'::'.$name.'()');
}
}
class Walls implements IteratorAggregate {
use Iteration;
private $list;
public function __construct(...$walls) {
$this->list= $walls;
}
public function getIterator() {
foreach ($this->list as $wall) {
yield $wall;
}
}
}
// Inside a module e.g.
Iteration::$extensions['sequence']= function($self) { return Sequence::of($self); };
// Then
(new Walls(new Wall('My Team', Types::$CLOSED), new Wall('Developers', Types::$OPEN)))
->sequence()
->each([Console::class, 'writeLine'])
;
<?php
use util\data\Sequence;
use lang\Error;
trait Extensions {
public static $methods= [];
protected abstract function extend();
public function __call($name, $args) {
$method= $this->extend().'::'.$name;
if (isset(Extensions::$methods[$method])) {
return Extensions::$methods[$method]($this, ...$args);
}
throw new Error('Call to non-existant '.nameof($this).'::'.$name.'()');
}
}
class Walls implements IteratorAggregate {
use Extensions;
private $list;
protected function extend() { return 'iterable'; }
public function __construct(...$walls) {
$this->list= $walls;
}
public function getIterator() {
foreach ($this->list as $wall) {
yield $wall;
}
}
}
// Inside a module e.g.
Extensions::$methods['iterable::sequence']= function($self) { return Sequence::of($self); };
// Then
(new Walls(new Wall('My Team', Types::$CLOSED), new Wall('Developers', Types::$OPEN)))
->sequence()
->each([Console::class, 'writeLine'])
;
<?php
// Classes.class.php in xp/extend7
namespace lang\extend;
class Classes {
public static $extensions= [];
public static function extend($type, $methods) {
$prefix= strtr($type, '.', '\\').'::';
foreach ($methods as $name => $closure) {
self::$extensions[$prefix.$name]= $closure;
}
}
}
// Extensions.class.php in xp/extend7
namespace lang\extend;
use lang\Error;
trait Extensions {
public function __call($name, $args) {
foreach (class_implements($this) + class_parents($this) as $type) {
$key= $type.'::'.$name;
if (isset(Classes::$extensions[$key])) {
return Classes::$extensions[$key]($this, ...$args);
}
}
throw new Error('Call to non-existant '.nameof($this).'::'.$name.'()');
}
}
// module.xp in xp-forhge/sequence
namespace util\data;
use lang\extend\Classes;
module xp-forge/sequence {
/**
* Registers extension method `sequence()` for traversable types.
*/
public function initialize() {
Classes::extend(\Traversable::class, [
'sequence' => function($self) { return Sequence::of($self); }
]);
}
}
// Walls.class.php in my/project
class Walls implements IteratorAggregate {
use Extensions;
private $list;
public function __construct(...$walls) {
$this->list= $walls;
}
public function getIterator() {
foreach ($this->list as $wall) {
yield $wall;
}
}
}
// Test.class.php in my/project
class Test {
public static function main($args) {
(new Walls(new Wall('My Team', Types::$CLOSED), new Wall('Developers', Types::$OPEN)))
->sequence()
->each([Console::class, 'writeLine'])
;
}
}
@thekid
Copy link
Author

thekid commented Mar 31, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment