Skip to content

Instantly share code, notes, and snippets.

@IMSoP
Created March 17, 2024 16:27
Show Gist options
  • Save IMSoP/fbd60c5379ccefcab6c5af25eacc259b to your computer and use it in GitHub Desktop.
Save IMSoP/fbd60c5379ccefcab6c5af25eacc259b to your computer and use it in GitHub Desktop.
<?php
class DefaultDict implements DimensionFetchable, DimensionWritable, FetchAppendable, DimensionUnsettable
{
private array $backingDict = [];
/**
* @param callable $factory Callback to provide a default value on read
*/
public function __construct(
private $factory
) {}
public function offsetGet(mixed $offset): mixed
{
if ( ! array_key_exists(array: $this->backingDict, key: $offset) ) {
// Calculate the default, but don't save it
return ($this->factory)($offset);
}
return $this->backingDict[$offset];
}
public function &offsetFetch(mixed $offset): mixed
{
if ( ! array_key_exists(array: $this->backingDict, key: $offset) ) {
// Populate the default value and return it by reference
$this->backingDict[$offset] = ($this->factory)($offset);
}
return $this->backingDict[$offset];
}
public function offsetExists(mixed $offset): bool
{
return array_key_exists(array: $this->backingDict, key: $offset);
}
public function offsetSet(mixed $offset, mixed $value): void
{
$this->backingDict[$offset] = $value;
}
public function offsetUnset(mixed $offset): void
{
unset($this->backingDict[$offset]);
}
public function append(mixed $value): void
{
$this->backingDict[] = $value;
}
public function &fetchAppend(): mixed
{
// First, get an append-reference on the actual array
$newItem =& $this->backingDict[];
// Next, generate a default value for it
$newItem = ($this->factory)(null);
// Finally, return it, and let the engine decide if it's a useful value for the operation
return $newItem;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment