PHP code example of lisachenko / userland-php-generics

1. Go to this page and download the library: Download lisachenko/userland-php-generics library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

lisachenko / userland-php-generics example snippets


use Lisachenko\Generics\Attribute\TemplateParameter;
use Lisachenko\Generics\{GenericObject, GenericTemplate};

/**
 * @template T
 */
#[TemplateParameter('T')]
final class Box implements GenericObject
{
    use GenericTemplate;

    private ?T $value = null;

    public function set(T $value): void
    {
        $this->value = $value;
    }

    public function get(): ?T
    {
        return $this->value;
    }
}

$intBox = new (Box::of('int'))();

$intBox->set(42);        // fine
$intBox->set('nope');    // TypeError: Box<int>::set(): Argument #1 ($value) must be of type int

get_class($intBox);      // "Box<int>"  — a real, registered, instantiable class

Generic::registry()->bindingFor($intBox::class)?->typeArguments;   // ['int']

Generic::warmUp([
    [Box::class, ['int']],
    [Box::class, [User::class]],
]);

$factory = new GenericFactory(mangler: new IdentifierSafeNameMangler());

use Lisachenko\Generics\Runtime\GenericAutoloader;

GenericAutoloader::register($factory);   // never installed for you

class_exists('App\Generic\Box_int');     // true - minted on the spot

spl_autoload_register(fn ($name) => print $name);
class_exists('App\Box<int>');            // prints nothing whatsoever

use Lisachenko\Generics\Generic;

Generic::bootstrap();   // optional: boots Z-Engine now instead of on first specialization

private ?T $value = null;

public function set(T $value): void {}

#[Of('T')]
private mixed $value = null;

#[TemplateParameter('T', of: Countable::class)]

interface BoxInterface extends GenericObject {}

/** @template T @implements BoxInterface<T> */
#[TemplateParameter('T')]
final class Box implements BoxInterface { use GenericTemplate; }

function consume(BoxInterface $box): void {}   // works for every Box<X>

$box = new (Box::of('int'))();          // inferred as Box<int>
Box::of('int');                          // class-string<Box<int>>
Box::of($runtime);                       // class-string<Box> - not narrowed, and not wrong

use Lisachenko\Generics\Native\NativeVector;

$samples = new (NativeVector::of('int'))($blobFromTheWire);

echo $samples[0];          // a zend_long read straight out of the block
$samples[1] = -20;         // written straight back into it
$samples->append(50);      // the block grows by eight bytes
$samples->append(1.5);     // TypeError, from the engine

$bytes = $samples->toBinary();  // back to a PHP string, byte for byte
neon
parameters:
    stubFiles:
        - var/generics-stubs/box-stub.php
    scanFiles:
        - var/generics-stubs/placeholders.php
bash
php -d ffi.enable=1 -d opcache.jit=off examples/collection.php
php -d ffi.enable=1 -d opcache.jit=off examples/native-vector.php