PHPGenerics / php-generics-rfc

Mirror of https://wiki.php.net/rfc/generics for easier collaboration
186 stars 1 forks source link

Reified type-arguments #37

Open mindplay-dk opened 6 years ago

mindplay-dk commented 6 years ago

This isn't so much an issue for discussion, so much as just trying to give you guys an idea of how I imagined generics would work in PHP. You can read/ponder/comment if you like, and then we can simply close this - I just wanted to make sure you've seen and understood this idea.

I've been updating my knowledge of Dart a bit, experimenting with a small DI container.

I'd like you to see something that surprised me.

In Dart, types are actually values of the type Type - and therefore type-arguments are also values.

Look at this example - or this simplified example:

String nameOf<T>() {
  return T.toString();
}

class Foo {}

print(nameOf(Foo)); // prints "Foo"

So Foo is not only a type, but also a variable of type Type - which seems really rational and natural to me, considering the fact that Dart (like PHP) is dynamic and reified.

In other words, the main difference at run-time between a regular argument and a type-argument is the syntax - the type-argument itself works just like any other variable when referenced in the body of a function.

Now, syntactically this wouldn't work well in PHP, since variables and types occupy different "namespaces", e.g. with all variable-names having an enforced $ prefix by way of syntax, so I'm not suggesting we'd be able to do that.

But it demonstrates an interesting run-time approach - something that might inspire the implementation of generics in PHP.

Here's another small example demonstrating a couple of interesting effects:

void main() {
  var foo = Foo<Bar>();

  ok(foo is Foo, "checks the base type");
  ok(foo is Foo<Bar>, "checks the base type and type-argument");
  ok(foo.getType() == Bar, "returns the type-argument");
}

class Foo<T> {
  Type getType() {
    return T;
  }
}

class Bar {}
class Baz {}

void ok(bool result, String description) {
  print('${ result ? "OK" : "FAIL" }: ${description}');
}

Note that there's Type, and then there's a separate dart:mirrors API - I wonder why the full reflection isn't just built into the Type type... if everything is reified anyway, it can be reflected, so I don't know what's won by having a separate reflection API.

I guess it'll be similar in PHP though, where our basic "type type" is a string (which isn't great, but..) and then the Reflection API provides models reflecting the internals of those types.

Anyhow, if you don't know Dart, maybe this gives you some idea why I've been looking closely at it while writing the initial proposal - I don't know of another language that is both reified and reflected in this manner, and it seems analogous to how I imagine it would work (or works) internally in PHP.

orolyn commented 6 years ago

.NET is the same https://docs.microsoft.com/en-us/dotnet/api/system.type.generictypearguments?redirectedfrom=MSDN&view=netframework-4.7.2#System_Type_GenericTypeArguments

I don't know though if types are genuinely objects though, i suspect there is a bit of boxing involved when inspection takes place.