Last active
August 29, 2015 14:18
-
-
Save thekid/ee6f46112dd0976aa63a to your computer and use it in GitHub Desktop.
Iteration trait with extensions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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']) | |
| ; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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']) | |
| ; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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']) | |
| ; | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See xp-framework/rfc#297