Skip to content

Latest commit

 

History

History
139 lines (100 loc) · 3.9 KB

isomorphisms.md

File metadata and controls

139 lines (100 loc) · 3.9 KB

🔄 Isomorphic Magic

Seamlessly navigate between different data representations with our Isomorphisms. Experience the enchantment of transforming your data effortlessly, as if conducting a symphony of bits and bytes.

Isos visualized

An isomorphism, in the world of optics, is like a universal translator for your data. It's the secret sauce that allows you to seamlessly switch between different representations of information without losing any meaning. Imagine effortlessly translating a complex concept from one language to another, each version capturing the essence perfectly. Isomorphisms do just that for your data, providing a smooth and reversible way to navigate between various structures, ensuring that your information remains intact and coherent, regardless of its form.

Let's dive into a small example:

Iso

use VeeWee\Reflecta\Iso\Iso;

$base64 = new Iso(
    to: base64_encode(...),
    from: base64_decode(...),
);

$data = 'hello world';
$encoded = $base64->to($data);
// > "aGVsbG8gd29ybGQ="
$actual = $base64->from($encoded);
// > "hello world"

assert($actual === $data);

This example provides an isomorphism for encoding a value to base64 or decoding from a base64 value. The result of the to() method will always be revertable by using the from() method.

Composability

You can compose many ISOs into one bigger ISO:

use VeeWee\Reflecta\Iso\Iso;

$base64 = new Iso(
    base64_encode(...),
    base64_decode(...),
);

$commaSeparated = new Iso(
    static fn (array $keywords): string => join(',', $keywords),
    static fn (string $keywords): array => explode(',', $keywords)
);

$commaSeparatedBase64 = $commaSeparated->compose($base64);

$data = ['hello' ,'world'];
$encoded = $commaSeparatedBase64->to($data);
// > ["hello", "world"] -> "hello,world" -> aGVsbG8sd29ybGQ=
$actual = $commaSeparatedBase64->from($encoded);
// > aGVsbG8sd29ybGQ= -> "hello,world", ["hello", "world"]

assert($actual === $data);

Functions

compose

This function is able to compose multiple isomorphisms into a new one. Check the chapter composability for more information. A psalm plugin is available that validates if the types of the ISOs are composable.

use function VeeWee\Reflecta\Iso\compose;

$commaSeparatedBase64 = compose(
    $commaSeparated,
    $base64,
    // ...others
);

object_data

This function will create an Iso that can access object data.

  • To will transform an array<string, mixed> and use this array to fill a new instance of the provided named object.
  • From will transform an instance of the provided named object into a array<string, mixed> that contains a full list of all properties with their values.
use function VeeWee\Reflecta\Iso\object_data;

class Item {
    public string $value;
}

$itemData = object_data(Item::class);

$data = [
    'value' => 'hello'
];
$itemInstance = $itemData->from($data);
$actualData = $itemData->to($item);

assert($data === $actualData);

Additionally, you can provide a custom Lens to the object_data function which will be used to read and write the data. This makes it possible to check property visibility or alternatively use getters and setters to access the data.

use VeeWee\Reflecta\Reflect\Type\Visibility;
use function VeeWee\Reflecta\Iso\object_data;
use function VeeWee\Reflecta\Lens\properties;
use function VeeWee\Reflecta\Reflect\Predicate\property_visibility;

class Item {
    public string $value = 'value';
    private string $hidden = 'hidden';
}

$itemData = object_data(Item::class, properties(property_visibility(Visibility::Public)));

$data = [
    'value' => 'hello',
    'hidden' => 'ignored',
];

$itemInstance = $itemData->from($data);
// > Item { value: "hello", hidden: "hidden" }
$actualData = $itemData->to($item);
// > ['value' => 'hello']

assert($data === $actualData);