On Sat, Dec 30, 2017 at 5:37 AM, Lester Caine <les...@lsces.co.uk> wrote:

>
> Not being able to vote, many of us have no option to complain about the
> way things are going. Currently there seems to be several styles of PHP
> form the nice and simple untyped version I moved to from very strictly
> typed hard compiled code I'd been using up until then, through to
> current code which is reliant on third party things like PSR and
> Composer and expects only strictly typed PHP.
>
>

This is born of the fact that while ignoring datatype makes learning PHP
easier, it makes using it harder - especially when testing.

Mark me as against union types. First, it places the burden of getting the
type right on the calling programmer. Stock PHP code doesn't do this and if
popular 3rd party libraries start doing this too much it makes the language
harder to learn.

Second it blocks this proposal, which is a way to give people who want to
control types the ability to do so in their own code without creating BC
breaks in PHP or interoperability problems with other libraries. Doing this
requires declaring variable types as an OPTION.  The default type of a
variable will be scalar.

Under what I propose putting what is now a type hint on the function line
will become a type declaration, and a casting operation will result if the
wrong type is passed in. So

function foo( int $a ) {}

Obviously this path becomes unavailable to us with union types - and by
comparison union types is an ineffective band-aid. The above is a shorthand
for this

function foo ( $arg ) {
  var int $a = $arg;
}

When a variable is declared this way it will autocast any assignment to the
declared type. The only way to get around this is redeclare the type.

Now some might be wondering, why not use this shorter statement:

int $a = 3;

The reason is this - I propose that syntax will lock the type down, but it
won't autocast assignments - it iwll instead throw a TypeError if the
assignment type doesn't match.

Anyway, there is one BC break - see it?

function foo( int $a ) {
  $a = 'hi';
}

Currently $a becomes a string of 'hi'. Under this proposal $a remains an it
and it is assigned the cast result of 'hi', which I believe is 0. Since the
format is relatively new - PHP 7 - changing it in 8 won't be as disruptive
as something that's been around a long time. Also, changing a var type
deliberately after declaring it is a bad practice, further reducing the
scope of code affected, but it's certainly not 0, so this is PHP 8.0
minimum.

Now next, class instance creation.

SomeClass $a = new SomeClass();

Doing this locks $a to SomeClass, and trying to assign it to something else
will trip a type error.

var SomeClass $a = new SomeClass();

Since there's no way to cast arbitrary arguments to SomeClass I'm not sure
how this should be handled.

Within classes..

class SomeClass {

  public $a = null; // Creates a scalar.

  public var int $b = 3; // Creates an autocasting int

  protected int $c = 5; // Creates an int. Errors will pitch on bad assign.

  protected OtherClass $b;

}

This syntax locks down, or *really* locks down types, but it's entirely
opt-in. If we're going to go down the road of sticter types this has to be
done.  It's also an example of why pasting in functionality without an
over-arching plan is a bad idea.  If Union types is included part of this
solution will be forever lost since it's likely incompatible with union
types (or at least union types with scalars - union types with objects
wouldn't be affected).

Reply via email to