kphp icon indicating copy to clipboard operation
kphp copied to clipboard

Universal `cast<T>` function

Open vkaverin opened this issue 2 years ago • 0 comments

Depends on #764.

Problem

Given there are two ways to cast a variable to some type:

  • For primitive types there's (T)$v, where T is a primitive type.
  • For class instances there's instance_cast($o, T::class).

Here we can see that instance-way is fully compatible with generics (you can use class-string type for T::class), but primitives are not, since you can't do ($t)$v (where $t is of type class-string<T>).

Solution

Function cast($v, $t), where $t is known at compile-time and can be

  • Class::class
  • class-string<T>
  • Primitive type string like 'int', 'string', etc.

Use cases

Given mixed[]. Wanted to cast it to int[], float[], string[] or any other more specific type. Currently it's necessary to make own function for each type:

  • array_force_int($array): int[]
  • array_force_float($array): float[]
  • array_force_string($array): string[]
  • ...

All these functions have the same code, only casted type is different:

foreach ($array as $k => $v) {
  $typed_array[$k] = (T)$v; // T is int/float/string/etc.
  // OR
  $typed_array[$k] = instance_cast($v, T); // T is class-string
}

With the cast function it could be just one function array_force($array, $type):

/**
  * @kphp-generic In, Out
  * @param In[] $array
  * @param class-string<Out> $type
  */
function array_force(array $array, $type): array {
  foreach ($array as $k => $v) {
    $typed_array[$k] = cast($v, $type);
  }
}

vkaverin avatar Mar 05 '23 15:03 vkaverin