Skip to content

Instantly share code, notes, and snippets.

@bwoebi
Last active August 29, 2015 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bwoebi/77759ace18b63a4ccdf2 to your computer and use it in GitHub Desktop.
Save bwoebi/77759ace18b63a4ccdf2 to your computer and use it in GitHub Desktop.
Generic typehints (Generator)
<?php
class Fetched {
# dummy class
}
class Fetcher {
private $promises;
private $stream;
private $watcher;
public function __construct(Stream $stream) {
$this->stream = $stream;
}
public function fetch(int $param): Promise<Fetched> {
# write some things to the $this->stream related to $param
$promise = new Promise; // is a Promise<Fetched>, because that's what's returned
$this->promises[] = $promise;
$this->watcher = $this->stream->enableWatcher([$this, "onReadable"]);
return $promise;
}
public function onReadable(string $streamInput) {
# work on $streamInput
# if we have all information ... (else return and wait in loop)
$this->stream->disableWatcher($this->watcher);
$promise = array_unshift($promises); # we can infer it was a Promise<Fetched> in the array, because that's the only thing ever pushed on it
$promise->resolve(new Fetched);
}
}
class Promise<T> {
protected $resolved = false;
protected $value;
private $resolver;
public function resolved(): bool {
return $this->resolved;
}
public function resolve(T $value): null {
$this->resolved = true;
$this->value = $value;
if (!$resolver) throw new Exception; # ...
($this->resolver)($value);
}
public function setResolver((T $value) $resolver): null {
$this->resolver = $resolver;
}
public function getValue() : T {
return $this->value;
}
}
class Success<T> extends Promise<T> {
public function __construct(T $success) {
$this->resolved = true;
$this->value = $success;
}
}
function getNumber(): Promise<int> {
return new Success(4);
}
function gen(Fetcher $fetcher): Generator<null, T, Promise<T>, Fetched> {
# Note that you may want to yield other Promises which are not of type Promise<Fetched> here... like e.g. Promise<int>
$number = yield getNumber();
$fetched = yield $fetcher->fetch($number);
return $fetched;
}
# ... in generics mark types I'm not interested in, which I don't want to specify
function advanceGenerator(Generator<..., T, Promise<T>, ...> $generator): null {
$advance = function () use (&$send, $generator) {
while ($generator->valid()) {
$promise = $generator->current();
if (!$promise->resolved()) {
$promise->setResolver($send);
return;
}
$generator->send($promise->getValue());
}
}
$send = function (T $value) use ($advance, $generator) {
$generator->send($value);
$advance();
}
$advance();
}
# get $stream from somewhere here… doesn't matter for the example
$gen = gen(new Fetcher($stream));
advanceGenerator();
if ($gen->valid()) {
startEventLoop();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment