Skip to content

Instantly share code, notes, and snippets.

@jcartledge
Last active August 9, 2020 18:25
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jcartledge/5963823 to your computer and use it in GitHub Desktop.
Save jcartledge/5963823 to your computer and use it in GitHub Desktop.
PHP immutable set
<?php
function set() {
return new Set(func_get_args());
}
class Set implements Countable, Iterator {
private $data = array();
function __construct($data) {
$this->data = $this->unique_array($data);
}
/** Countable implementation **/
function count () { return count($this->data); }
/** End Countable implementation **/
/** Iterator implementation **/
function current() { return current($this->data); }
function key () { return $this->hash(current($this->data)); }
function next () { next($this->data); return $this; }
function rewind () { reset($this->data); return $this; }
function valid () { return TRUE; }
/** End Iterator implementation **/
/** "Mutation" operations return a new Set **/
function map($fn) {
return new Set(array_map($fn, $this->data));
}
function filter($fn) {
return new Set(array_filter($this->data, $fn));
}
function append($value) {
return new Set(array_merge($this->data, func_get_args()));
}
function remove($value) {
$args = func_get_args();
return $this->filter(function($x) use ($args) {
return !in_array($x, $args);
});
}
function concat(Set $that) {
return new Set(array_merge($this->data), $that->as_array());
}
/** End "Mutation" operations **/
/** Boolean existence test **/
function contains($value) {
return isset($this->data[$this->hash($value)]);
}
/** Native array **/
function as_array() {
return array_values($this->data);
}
/** String for prettyprint **/
function __toString() {
return sprintf('Set(%s)', implode(', ',
array_map(array($this, 'inspect'), $this->data)
));
}
/** Key is hash of serialized value **/
private function hash($data) {
return sha1(serialize($data));
}
/** If we allow data to be passed in by reference (e.g nested arrays) **/
/** Then there is a risk it will get modified from outside. **/
private function copy($data) {
return unserialize(serialize($data));
}
/** Convert an arbitrary array into one with unique values keyed on hash **/
private function unique_array($arr) {
return array_combine(
array_map(array($this, 'hash'), $arr),
array_map(array($this, 'copy'), $arr)
);
}
/** Output variable type and value for prettyprint **/
private function inspect($var) {
ob_start();
var_dump($var);
return trim(ob_get_clean());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment