Skip to content

Instantly share code, notes, and snippets.

@deathlyfrantic
Last active September 24, 2021 12:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save deathlyfrantic/d6cb7e95e83a83cf111bef5876d5630d to your computer and use it in GitHub Desktop.
Save deathlyfrantic/d6cb7e95e83a83cf111bef5876d5630d to your computer and use it in GitHub Desktop.
php object implementation of a standard list (not hashtable)
<?php
function vector($arg = null): Vector {
return new Vector($arg);
}
function is_vector($obj): bool {
return $obj instanceof Vector;
}
class AttributeError extends Exception {}
class Vector implements Countable, ArrayAccess, Iterator {
protected $items = [];
protected $cursor = 0;
public function __construct(...$args) {
$this->items = $args;
}
public function __get($name) {
switch ($name) {
case "__items__":
return $this->items;
case "length":
return $this->count();
default:
throw new AttributeError("Vector has no attribute called $name.");
}
}
protected function decrementCursor() {
if ($this->cursor > 0) {
$cursor--;
}
}
public function current() {
return $this->items[$this->cursor];
}
public function key(): int {
return $this->cursor;
}
public function next() {
$this->cursor++;
}
public function rewind() {
$this->cursor = 0;
}
public function valid(): bool {
return $this->offsetExists($this->cursor);
}
public function offsetExists($idx): bool {
if (!is_int($idx)) {
throw new AttributeError("Vector keys must be integers.");
}
return $idx < ($this->count() - 1);
}
protected function ensureIndexInRange($idx) {
if (!$this->offsetExists($idx)) {
throw new AttributeError("$idx is outside the range [{$this->count()}] of this vector.");
}
}
public function offsetGet($idx) {
$this->ensureIndexInRange($idx);
return $this->items[$idx];
}
public function offsetSet($idx, $val) {
$this->ensureIndexInRange($idx);
$this->items[$idx] = $val;
}
public function offsetUnset($idx) {
$this->ensureIndexInRange($idx);
$this->splice($idx, 1);
if ($this->cursor === $idx) {
$this->decrementCursor();
}
}
public function count(): int {
return count($this->items);
}
public function push(...$args) {
return array_push($this->items, ...$args);
}
public function pop() {
if ($this->cursor === $this->count() - 1) {
$this->decrementCursor();
}
return array_pop($this->items);
}
public function shift() {
if ($this->cursor !== 0) {
$this->decrementCursor();
}
return array_shift($this->items);
}
public function unshift(...$args) {
return array_unshift($this->items, ...$args);
}
public function slice(int $offset, $length = null): self {
return new self(array_slice($this->items, $offset, $length));
}
public function splice(int $offset, int $length = null, $replacement = []): self {
if (is_null($length)) {
$length = $this->count();
}
return new self(array_splice($this->items, $offset, $length, $replacement));
}
public function map(callable $cb): self {
return new self(array_map($cb, $this->items));
}
public function forEach(callable $cb) {
array_walk($this->items, $cb);
}
public function filter(callable $cb): self {
return new self(array_filter($this->items, $cb));
}
public function some(callable $cb): bool {
foreach ($this->items as $item) {
if ($cb($item)) {
return true;
}
}
return false;
}
public function every(callable $cb): bool {
foreach ($this->items as $item) {
if (!$cb($item)) {
return false;
}
}
return true;
}
public function includes($val): bool {
return in_array($val, $this->items);
}
public function join($glue = " "): string {
return implode($glue, $this->items);
}
public function reduce(callable $cb, $initial = null) {
return array_reduce($this->items, $cb, $initial);
}
public function sort(callable $cb = null): self {
if (is_null($cb)) {
sort($this->items);
} else {
usort($this->items, $cb);
}
return $this;
}
public function reverse(): self {
$this->items = array_reverse($this->items);
return $this;
}
public function indexOf($val): int {
$loc = array_search($val, $this->items);
return ($loc !== false) ? $loc : -1;
}
public function unique(): self {
return new self(array_unique($this->items));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment