Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-24 Thread Michał Brzuchalski
wt., 23 kwi 2019 o 11:17 Nikita Popov  napisał(a):

> ...
> Without commenting on the rest of the proposal: It's not possible to use
> (ClassName) as a cast syntax, because it is ambiguous. For example (Foo)
> [$x] is already valid syntax (fetch constant Foo and take index $x), or
> (Foo) +$bar, etc.
>

Wouldn't that be possible to differentiate consts with class names if we
merge symbol tables and allow only one symbol with the same name?

I know this is huge BC break but AFAIK in the past, there was a discussion
about merging symbol tables.

-- 
regards / pozdrawiam,
--
Michał Brzuchalski
about.me/brzuchal
brzuchalski.com


Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Stephen Reay


> On 23 Apr 2019, at 21:54, Benjamin Morel  wrote:
> 
> @Stephen Reay 
> 
>> In languages without type hinting (e.g. JavaScript) - the “boiler plate”
> you’re trying to remove is also common, e.g. using `typeof` in JavaScript.
> 
> It's also very common to *not* check types in JavaScript... I assume the
> absence of type hints is partly responsible for this, and a reason why
> quite a lot of JS developers turn to typed preprocessors, such as
> TypeScript.
> 
>> Assigning a variable to itself, because you want to check its type is the
> weirdest concept I’ve heard in a long time.
> 
> I assume you're speaking of the foreach() example; sure, used this way, it
> looks like a self-assignment, but in most cases it's not, it's an inline,
> checked type-hint:
> 
>// (assuming the 'as' syntax, now that the cast syntax has been buried)
>$foo = $entityManager->find(User::class, 123) as User;
> 
> You're effectively adding, **inline and with just a few chars**, an
> additional type-hint and runtime check to the value. I wouldn't call this a
> no-op.
> 
>> You want to add more capability to enforce type checking - I get that,
> and I share that goal. But when we already have pretty common, intuitive
> syntax to do so in one situation, I don’t see why you wouldn’t adopt the
> same syntax elsewhere.
> 
> While I don't agree with you on many points, I appreciate that we share the
> same goal somehow, and hope that we can find common grounds. I would
> personally not be against variables typed on declaration, but even though
> this probably does not make sense, I'm somehow more comfortable with:
> 
>function test(string $name) {
>$name = 123;
>}
> 
> than:
> 
>string $name = 'Ben';
>$name = 123;
> 
> I guess that I could be more comfortable with this approach if we had a
> switch, such as `declare(locked_types=1)`, that would enforce the type of
> the variable throughout its lifetime. This may come at a huge runtime cost,
> though.
> 
> - Ben

Hi Ben,

I realise type checking in JS is not really common, my intention was to 
indicate that the suggested `$foo = $bar->foo() as Foo` is basically unheard of 
in any language besides Hack. As has been suggested and refuted many times - 
less code is not necessarily more readable. In this case, I still feel `$foo 
instanceof Foo || throwTypeError()` or even a 3-liner `if` to do the throw 
inline, is more readable and more obvious than the proposed syntax.

Yes - because of the syntax you’re proposing, this feature could never 
realistically be added to `foreach` statements without making them hard to read 
at best, and possibly (I don’t know, I’m not familiar with the C internals) 
impossible.

Given that type hinting the members of an iterable is something that has been 
discussed and rejected before, the ability to hint types of an iterable is a 
no-brainer to me. It’s also one of the two examples Larry came up with.


As I understand it, you find `Foo $obj = $bar->getFoo();` to imply a fixed type 
for the variable $obj?

I’ll just recap one more time, and then I’m not going to repeat this, because 
it’s surely getting boring for everyone else on the list.

There is (as of 7.4) precedent for a typed “variable” that *is* locked to the 
type it’s declared with (class properties^), and for typed variables (function 
parameters) that are *not* locked to the type they're declared with. If this 
feature were added, it surely will follow the behaviour of one of those two: 
either they are or are not a fixed type, and one of the three cases will become 
the ‘exception’ developers need to remember when using typed 
variables/properties.

^: Yes I know class properties aren’t really the same as local variables, but 
they’re presented very similarly in syntax and behave mostly the same pre-7.4


I *assume* implementation wise it’s not even realistic to make local variables 
behave as 7.4+ typed class properties do (i.e. fixed type), but my point is 
that from a “do people want this” point of view, I believe the people who are 
actually likely to declare types on local variables, are *probably* quite 
unlikely to re-declare variables to a different type like that in most cases 
anyway.


I’d also suggest that just adding local variable type hinting “now” (i.e. in 
8.0 if an RFC passed) in a manner consistent with function parameter type 
hints, would mean that a later discussion/RFC could approach the concept of 
fixed-type variables (e.g using a `declare` option as you mentioned).


Cheers

Stephen




--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Benjamin Morel
@Stephen Reay 

> In languages without type hinting (e.g. JavaScript) - the “boiler plate”
you’re trying to remove is also common, e.g. using `typeof` in JavaScript.

It's also very common to *not* check types in JavaScript... I assume the
absence of type hints is partly responsible for this, and a reason why
quite a lot of JS developers turn to typed preprocessors, such as
TypeScript.

> Assigning a variable to itself, because you want to check its type is the
weirdest concept I’ve heard in a long time.

I assume you're speaking of the foreach() example; sure, used this way, it
looks like a self-assignment, but in most cases it's not, it's an inline,
checked type-hint:

// (assuming the 'as' syntax, now that the cast syntax has been buried)
$foo = $entityManager->find(User::class, 123) as User;

You're effectively adding, **inline and with just a few chars**, an
additional type-hint and runtime check to the value. I wouldn't call this a
no-op.

> You want to add more capability to enforce type checking - I get that,
and I share that goal. But when we already have pretty common, intuitive
syntax to do so in one situation, I don’t see why you wouldn’t adopt the
same syntax elsewhere.

While I don't agree with you on many points, I appreciate that we share the
same goal somehow, and hope that we can find common grounds. I would
personally not be against variables typed on declaration, but even though
this probably does not make sense, I'm somehow more comfortable with:

function test(string $name) {
$name = 123;
}

than:

string $name = 'Ben';
$name = 123;

I guess that I could be more comfortable with this approach if we had a
switch, such as `declare(locked_types=1)`, that would enforce the type of
the variable throughout its lifetime. This may come at a huge runtime cost,
though.

- Ben


Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Stephen Reay


> On 23 Apr 2019, at 21:02, Benjamin Morel  wrote:
> 
> It's exactly the purpose of the proposal: avoid this boilerplate. For the 
> same reason you probably write:
> 

Replacing 1 line of “boiler plate” with a *different* line of less-obvious 
“boiler plate” is not an improvement IMO.

> The current proposal is to fill the gap of type checking / type hinting 
> **inline**, when getting data from an losely typed source.

Parameter type hints use syntax that is clear, concise and reasonably common in 
other languages.

Similarly, defining the type of a variable when it’s declared is clear and 
concise reasonably common in other languages.

In languages without type hinting (e.g. JavaScript) - the “boiler plate” you’re 
trying to remove is also common, e.g. using `typeof` in JavaScript.

Assigning a variable to itself, because you want to check its type is the 
weirdest concept I’ve heard in a long time.



You want to add more capability to enforce type checking - I get that, and I 
share that goal. But when we already have pretty common, intuitive syntax to do 
so in one situation, I don’t see why you wouldn’t adopt the same syntax 
elsewhere.


The typed properties RFC adopted the same syntax as parameter hints, even 
though they have some different implementation details (e.g. you can redeclare 
a function parameter to another type, you can’t with a typed class property). I 
can see that there would be pros and cons to either approach for typed local 
variables - but IMO *that* is the discussion to have.

The initial RFC doesn’t even need to cover every possible scenario - it could 
literally just cover plain variable declarations. A later one could cover 
adding type hints to for example, foreach.

By using syntax that’s already in-use, *and* doesn’t conflict with other 
*potential* points of implementation, we can hopefully end up with more options 
for type support in the language.


Cheers


Stephen


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Benjamin Morel
@Stephen Reay 

> And as I said before, I can’t understand how that is supposed to be
better than just doing what works now, using instanceof to check the type
inside the block:
> if (! $foo instanceof Foo) { throw new TypeError(…); }
> At least with the above, it’s obvious what is happening.

It's exactly the purpose of the proposal: avoid this boilerplate. For the
same reason you probably write:

function test(Foo $foo, string $bar) {}

and not:

function test($foo, $bar) {
if (! $foo instanceof Foo) throw new TypeError();
if (! is_string($bar)) throw new TypeError();
}

We could have argued a few years ago that adding type-hints to PHP was
unnecessary, for the same reason: if was possible to do these checks in
userland.
It's just much more readable and concise to let the engine perform the
checks.

The current proposal is to fill the gap of type checking / type hinting
**inline**, when getting data from an losely typed source.

- Ben


Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Mark Randall

On 23/04/2019 14:39, Mark Randall wrote:
It keeps coming back to the feature we've all been praying to the PHP 
Gods for... generics.


Replying to myself (sorry).

I just wanted to point out that the same syntax would also solve your 
other issue from the nullable casts thread:


function ncast($value) ?T {
   if ($value === null) {
 return null;
   }

   if (settype($value, T) === false) {
  throw new InvalidArgumentException('Cannot convert to ' . T);
   }

   return $value;
}

ncast(null);
ncast(12345);

ncast(null);
ncast('abcdef');

--
Mark Randall

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Stephen Reay


> On 23 Apr 2019, at 19:32, Benjamin Morel  wrote:
> 
> I'm sorry, I still don't understand what the issue with foreach is? As I said 
> before, the proposed syntax does not aim to be used inside the foreach () 
> parentheses, but rather as an explicit declaration inside the foreach {} 
> block.
> 

And as I said before, I can’t understand how that is supposed to be better than 
just doing what works now, using instanceof to check the type inside the block:

if (! $foo instanceof Foo) { throw new TypeError(…); }

At least with the above, it’s obvious what is happening.




--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Benjamin Morel
@Mark Randall 

> It keeps coming back to the feature we've all been praying to the PHP
> Gods for... generics.
> $x = cast($obj);

I did not think about using generics for this, but indeed this could work.
It's only reasonably verbose, easily implemented in userland, and should be
usable both by static analysis tooling, and potentially by the VM and JIT
for future optimizations.
It just costs an extra function call vs. a single opcode, but overall I
could be OK with this approach.

I'm not sure why generics haven't yet gained traction though, so unless
there's a hope to see them implemented soon, I'll keep focusing on this
standalone feature for now!

- Ben


Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Mark Randall

On 23/04/2019 13:32, Benjamin Morel wrote:

Aw. I did not think about a possible conflict here, thanks for bringing
this up!


It keeps coming back to the feature we've all been praying to the PHP 
Gods for... generics.


function cast(object $obj): T {
  if ($obj instanceof T) {
return $obj;
  }

  throw new InvalidArgumentException('Cast expected ' . T);
}

$x = cast($obj);

--
Mark Randall

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Benjamin Morel
@Nikita Popov 

>  It's not possible to use (ClassName) as a cast syntax, because it is
ambiguous.

Aw. I did not think about a possible conflict here, thanks for bringing
this up!

@Stephen Reay 

> My objection to `as` is that it specifically prevents (or makes very
confusing) the `foreach` use I mentioned. There’s no variables involved in
imports/traits, and neither of those relates to foreach.

I'm sorry, I still don't understand what the issue with foreach is? As I
said before, the proposed syntax does not aim to be used inside the foreach
() parentheses, but rather as an explicit declaration inside the foreach {}
block.

> As for the `string $foo = $bar->getFoo();` ‘looking strongly typed’ and
wondering if it will allow re-declaration - do you think the same when you
see `function (string $foo) { $foo = explode(‘ ‘, $foo); }` ? Functions
have allowed type hints since 5.0 - nearly 15 years ago, and nobody seems
to be confused if those variables can be redeclared. Whether you *should*
redeclare them to a different value is something you need to decide for
yourself.

You have a point. I can't say why, but outside of the function declaration,
it looks more like a static typing to me (and someone else had the same gut
reaction earlier in this thread). I may just be plain wrong.

> As for limiting this to class/interface names - why would you do that? It
took YEARS to get scalar type hints for function parameters, why would you
not include them from the start on anything new that pertains to
essentially the same functionality?

I'm definitely not against supporting other types, it's just that the
original syntax I had in mind was using () casting, which was already
covered for other types.
Now if people like Hack's `as` syntax, it would probably make sense to
generalize it indeed.

@Dan Ackroyd 

> Similar to the nullable casting idea, you're taking a problem caused
> by your own code/framework, and then thinking it should be solved in
> core, when a simple solution is available in user-land.
> ...
> btw I'm sure you're already aware of it, but this is using a
> 'dependency injector' as a service locator. If your current DI library
> isn't powerful enough for you, rather than abusing it like this,

I think that the sudden focus on the specific case of DI container /
service locator reveals a misunderstanding here. The example I chose is
obviously responsible for that and this choice was perhaps infortunate: it
didn't help convey the true meaning of the proposal.

As I said earlier, I'm a heavy user of Dependency Injection AND Inversion
of Control; my framework does not suffer from any such limitation: my
controllers' and services' dependencies are explicitly declared and
injected automatically, and no such code relies on fetching dependencies
from the container directly. These classes are not even aware of the
existence of the container, and not tied to the DI framework in any way.
Also, my repositories are full blown, and encapsulate the ORM to return
specific entities.

YET, I also do some quick prototypes or CLI scripts that would not benefit
from too much boilerplate, and may use the DI container or the ORM's entity
manager directly. I also get objects from various losely typed data sources
(functions returning mixed types, arrays, iterators of all sorts, etc.)
that I expect to be of a given type, and that would benefit from the
added *readability,
type checking and static analysis capabilities* the current proposal offers.

@Andrey Hristov 

> this is easily solvable with the following (considering strict_types is
enabled)
> function tostr(string $in) : string { return $in; }

This solves it for a single type, but you have to write a function for
every class you want to enforce:

function toEmailService(EmailService $service) : EmailService { return
$service; }
function toUser(User $user) : User { return $user; }

As you can see, this gets ugly real quick. Your IDE and/or static analysis
tool will also probably warn about "Expecting Foo, got mixed", whereas with
an explicit cast/enforced-type-hint, the tooling would know that you're
explicitly stating that this unknown typed value is an instance of Foo.

- Ben



On Tue, 23 Apr 2019 at 12:52, Andrey Hristov  wrote:

>   Hi,
> On 23.04.19 г. 13:44 ч., azjezz wrote:
> > Hello Dan,
> >
> > I don' think this a problem relating to just one use case, some PHP
> builtin functions have weird union return types, where static analysis
> tools would warn you about the return type being `string|bool`, when you
> are expecting `string`.
> >
> > using type constrain :
> > ```
> > $foo = substr($foo, 1, 3) as string;
> > // there's no need to check if `$foo` is false here.
> > ```
>
> this is easily solvable with the following (considering strict_types is
> enabled)
>
> function tostr(string $in) : string { return $in; }
>
> $foo = tostr($foo);
>
> Put it in a convenience namespace and that's it.
>
> Cheers,
> Andrey
>
> >
> >
> > Cheers,
> >
> > - Saif
> >
> >
> > 

Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread azjezz
Hello Andery.

yes that's possible, but would need a function for each type, or we can do : 
https://3v4l.org/6B3hA

but this is still not type-safe, as we won't be able to type hint it correctly 
without using generics + `typename` type that exists in Hack.


using generics + `typename` : `function check(mixed $var, typename 
$type): T`


Cheers,

- Saif

Sent with ProtonMail Secure Email.

‐‐‐ Original Message ‐‐‐
On Tuesday, April 23, 2019 11:51 AM, Andrey Hristov  wrote:

> Hi,
> On 23.04.19 г. 13:44 ч., azjezz wrote:
>
> > Hello Dan,
> > I don' think this a problem relating to just one use case, some PHP builtin 
> > functions have weird union return types, where static analysis tools would 
> > warn you about the return type being `string|bool`, when you are expecting 
> > `string`.
> > using type constrain :
> >
> > $foo = substr($foo, 1, 3) as string;
> > // there's no need to check if `$foo` is false here.
> >
>
> this is easily solvable with the following (considering strict_types is
> enabled)
>
> function tostr(string $in) : string { return $in; }
>
> $foo = tostr($foo);
>
> Put it in a convenience namespace and that's it.
>
> Cheers,
> Andrey
>
> > Cheers,
> >
> > -   Saif
> >
> > Sent with ProtonMail Secure Email.
> > ‐‐‐ Original Message ‐‐‐
> > On Tuesday, April 23, 2019 11:33 AM, Dan Ackroyd dan...@basereality.com 
> > wrote:
> >
> > > HI Benjamin,
> > > Similar to the nullable casting idea, you're taking a problem caused
> > > by your own code/framework, and then thinking it should be solved in
> > > core, when a simple solution is available in user-land.
> > > If you changed what you currently have:
> > > $service = $diContainer->get('email.service');
> > > to also take the expected class:
> > > $service = $diContainer->get('email.service', EmailService::class);
> > > And then check inside your 'DI container' whether the expected type is
> > > returned, this solves the problem without needing new syntax.
> > > btw I'm sure you're already aware of it, but this is using a
> > > 'dependency injector' as a service locator. If your current DI library
> > > isn't powerful enough for you, rather than abusing it like this, I'd
> > > recommend looking at a different one, like
> > > https://github.com/rdlowrey/Auryn
> > > Also, similar:
> > >
> > > > By the way, this RFC is a special case of something that could be far
> > > > more generic. If it was possible to register callbacks to be used when
> > > > casting, ...
> > >
> > > Apparently this might not be possible as it's ambiguouswhich is a 
> > > shame.
> > > cheers
> > > Dan
> > > Ack
> > > On Mon, 22 Apr 2019 at 22:47, Benjamin Morel benjamin.mo...@gmail.com 
> > > wrote:
> > >
> > > > Hi internals,
> > > > I'd like to revive an old discussion https://externals.io/message/67131 
> > > > about
> > > > object type casting.
> > > > The idea would be to allow (ClassName) casting:
> > > >
> > > >  $service = (EmailService) $diContainer->get('email.service');
> > > >
> > > >
> > > > The above code would throw a TypeError if the value is not an instance 
> > > > of
> > > > the given class. I see the following advantages:
> > > >
> > > > -   Type safety: we can be sure that the value is of the correct type 
> > > > or that
> > > > we'll get an Error. This syntax allows to fail early if the variable
> > > > happens to not be of the expected type, and avoids much more 
> > > > verbose checks;
> > > >
> > > > -   Static analysis: IDEs and static code analysis tools can now 
> > > > understand
> > > > the type of the variable, without having to resort to `@var` 
> > > > annotations.
> > > >
> > > >
> > > > These combine into a third advantage: readability. Today's equivalent of
> > > > the above one-liner could be:
> > > >
> > > >  /** @var EmailService $service */
> > > >  $service = $diContainer->get('email.service');
> > > >  if (! $service instanceof EmailService) {
> > > >  throw new TypeError('Expected instance of EmailService, ...');
> > > >  }
> > > >
> > > >
> > > > Which is a lot of boilerplate code that could be easily avoided by
> > > > introducing this new syntax.
> > > > Before moving forward and working on a formal RFC, I'd like to hear your
> > > > thoughts: what's your early feeling about this? Did I miss other
> > > > discussions around this subject? Are there any technical issues that 
> > > > come
> > > > to mind? Could this feature help the upcoming JIT compiler produce more
> > > > efficient machine code by knowing the type of the variable at compile 
> > > > time?
> > > > etc.
> > > > Note: "casting" might not be the perfect name here as what we're really
> > > > doing is a type check, but this reuses the type casting syntax and
> > > > resembles Java's object casting.
> > > > Thank you,
> > > > Ben
> > >
> > > --
> > > PHP Internals - PHP Runtime Development Mailing List
> > > To unsubscribe, visit: http://www.php.net/unsub.php



--
PHP Internals - PHP Runtime 

Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Andrey Hristov

 Hi,
On 23.04.19 г. 13:44 ч., azjezz wrote:

Hello Dan,

I don' think this a problem relating to just one use case, some PHP builtin 
functions have weird union return types, where static analysis tools would warn 
you about the return type being `string|bool`, when you are expecting `string`.

using type constrain :
```
$foo = substr($foo, 1, 3) as string;
// there's no need to check if `$foo` is false here.
```


this is easily solvable with the following (considering strict_types is 
enabled)


function tostr(string $in) : string { return $in; }

$foo = tostr($foo);

Put it in a convenience namespace and that's it.

Cheers,
Andrey




Cheers,

- Saif


Sent with ProtonMail Secure Email.

‐‐‐ Original Message ‐‐‐
On Tuesday, April 23, 2019 11:33 AM, Dan Ackroyd  wrote:


HI Benjamin,

Similar to the nullable casting idea, you're taking a problem caused
by your own code/framework, and then thinking it should be solved in
core, when a simple solution is available in user-land.

If you changed what you currently have:

$service = $diContainer->get('email.service');

to also take the expected class:

$service = $diContainer->get('email.service', EmailService::class);

And then check inside your 'DI container' whether the expected type is
returned, this solves the problem without needing new syntax.

btw I'm sure you're already aware of it, but this is using a
'dependency injector' as a service locator. If your current DI library
isn't powerful enough for you, rather than abusing it like this, I'd
recommend looking at a different one, like
https://github.com/rdlowrey/Auryn

Also, similar:


By the way, this RFC is a special case of something that could be far
more generic. If it was possible to register callbacks to be used when
casting, ...


Apparently this might not be possible as it's ambiguouswhich is a shame.

cheers
Dan
Ack

On Mon, 22 Apr 2019 at 22:47, Benjamin Morel benjamin.mo...@gmail.com wrote:


Hi internals,
I'd like to revive an old discussion https://externals.io/message/67131 about
object type casting.
The idea would be to allow (ClassName) casting:

 $service = (EmailService) $diContainer->get('email.service');


The above code would throw a TypeError if the value is not an instance of
the given class. I see the following advantages:

-   Type safety: we can be sure that the value is of the correct type or that
 we'll get an Error. This syntax allows to fail early if the variable
 happens to not be of the expected type, and avoids much more verbose 
checks;

-   Static analysis: IDEs and static code analysis tools can now understand
 the type of the variable, without having to resort to `@var` annotations.


These combine into a third advantage: readability. Today's equivalent of
the above one-liner could be:

 /** @var EmailService $service */
 $service = $diContainer->get('email.service');
 if (! $service instanceof EmailService) {
 throw new TypeError('Expected instance of EmailService, ...');
 }


Which is a lot of boilerplate code that could be easily avoided by
introducing this new syntax.
Before moving forward and working on a formal RFC, I'd like to hear your
thoughts: what's your early feeling about this? Did I miss other
discussions around this subject? Are there any technical issues that come
to mind? Could this feature help the upcoming JIT compiler produce more
efficient machine code by knowing the type of the variable at compile time?
etc.
Note: "casting" might not be the perfect name here as what we're really
doing is a type check, but this reuses the type casting syntax and
resembles Java's object casting.
Thank you,
Ben


--

PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php







--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread azjezz
Hello Dan,

I don' think this a problem relating to just one use case, some PHP builtin 
functions have weird union return types, where static analysis tools would warn 
you about the return type being `string|bool`, when you are expecting `string`.

using type constrain :
```
$foo = substr($foo, 1, 3) as string;
// there's no need to check if `$foo` is false here.
```



Cheers,

- Saif


Sent with ProtonMail Secure Email.

‐‐‐ Original Message ‐‐‐
On Tuesday, April 23, 2019 11:33 AM, Dan Ackroyd  wrote:

> HI Benjamin,
>
> Similar to the nullable casting idea, you're taking a problem caused
> by your own code/framework, and then thinking it should be solved in
> core, when a simple solution is available in user-land.
>
> If you changed what you currently have:
>
> $service = $diContainer->get('email.service');
>
> to also take the expected class:
>
> $service = $diContainer->get('email.service', EmailService::class);
>
> And then check inside your 'DI container' whether the expected type is
> returned, this solves the problem without needing new syntax.
>
> btw I'm sure you're already aware of it, but this is using a
> 'dependency injector' as a service locator. If your current DI library
> isn't powerful enough for you, rather than abusing it like this, I'd
> recommend looking at a different one, like
> https://github.com/rdlowrey/Auryn
>
> Also, similar:
>
> > By the way, this RFC is a special case of something that could be far
> > more generic. If it was possible to register callbacks to be used when
> > casting, ...
>
> Apparently this might not be possible as it's ambiguouswhich is a shame.
>
> cheers
> Dan
> Ack
>
> On Mon, 22 Apr 2019 at 22:47, Benjamin Morel benjamin.mo...@gmail.com wrote:
>
> > Hi internals,
> > I'd like to revive an old discussion https://externals.io/message/67131 
> > about
> > object type casting.
> > The idea would be to allow (ClassName) casting:
> >
> > $service = (EmailService) $diContainer->get('email.service');
> >
> >
> > The above code would throw a TypeError if the value is not an instance of
> > the given class. I see the following advantages:
> >
> > -   Type safety: we can be sure that the value is of the correct type or 
> > that
> > we'll get an Error. This syntax allows to fail early if the variable
> > happens to not be of the expected type, and avoids much more verbose 
> > checks;
> >
> > -   Static analysis: IDEs and static code analysis tools can now understand
> > the type of the variable, without having to resort to `@var` 
> > annotations.
> >
> >
> > These combine into a third advantage: readability. Today's equivalent of
> > the above one-liner could be:
> >
> > /** @var EmailService $service */
> > $service = $diContainer->get('email.service');
> > if (! $service instanceof EmailService) {
> > throw new TypeError('Expected instance of EmailService, ...');
> > }
> >
> >
> > Which is a lot of boilerplate code that could be easily avoided by
> > introducing this new syntax.
> > Before moving forward and working on a formal RFC, I'd like to hear your
> > thoughts: what's your early feeling about this? Did I miss other
> > discussions around this subject? Are there any technical issues that come
> > to mind? Could this feature help the upcoming JIT compiler produce more
> > efficient machine code by knowing the type of the variable at compile time?
> > etc.
> > Note: "casting" might not be the perfect name here as what we're really
> > doing is a type check, but this reuses the type casting syntax and
> > resembles Java's object casting.
> > Thank you,
> > Ben
>
> --
>
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Dan Ackroyd
HI Benjamin,

Similar to the nullable casting idea, you're taking a problem caused
by your own code/framework, and then thinking it should be solved in
core, when a simple solution is available in user-land.

If you changed what you currently have:

$service = $diContainer->get('email.service');

to also take the expected class:

$service = $diContainer->get('email.service', EmailService::class);

And then check inside your 'DI container' whether the expected type is
returned, this solves the problem without needing new syntax.

btw I'm sure you're already aware of it, but this is using a
'dependency injector' as a service locator. If your current DI library
isn't powerful enough for you, rather than abusing it like this, I'd
recommend looking at a different one, like
https://github.com/rdlowrey/Auryn

Also, similar:
>
> By the way, this RFC is a special case of something that could be far
> more generic. If it was possible to register callbacks to be used when
> casting, ...

Apparently this might not be possible as it's ambiguouswhich is a shame.

cheers
Dan
Ack

On Mon, 22 Apr 2019 at 22:47, Benjamin Morel  wrote:
>
> Hi internals,
>
> I'd like to revive an old discussion  
> about
> object type casting.
>
> The idea would be to allow (ClassName) casting:
>
> $service = (EmailService) $diContainer->get('email.service');
>
> The above code would throw a TypeError if the value is not an instance of
> the given class. I see the following advantages:
>
> - Type safety: we can be sure that the value is of the correct type or that
> we'll get an Error. This syntax allows to fail early if the variable
> happens to not be of the expected type, and avoids much more verbose checks;
> - Static analysis: IDEs and static code analysis tools can now understand
> the type of the variable, without having to resort to `@var` annotations.
>
> These combine into a third advantage: readability. Today's equivalent of
> the above one-liner could be:
>
> /** @var EmailService $service */
> $service = $diContainer->get('email.service');
> if (! $service instanceof EmailService) {
> throw new TypeError('Expected instance of EmailService, ...');
> }
>
> Which is a lot of boilerplate code that could be easily avoided by
> introducing this new syntax.
>
> Before moving forward and working on a formal RFC, I'd like to hear your
> thoughts: what's your early feeling about this? Did I miss other
> discussions around this subject? Are there any technical issues that come
> to mind? Could this feature help the upcoming JIT compiler produce more
> efficient machine code by knowing the type of the variable at compile time?
> etc.
>
> Note: "casting" might not be the perfect name here as what we're really
> doing is a type check, but this reuses the type casting syntax and
> resembles Java's object casting.
>
> Thank you,
> Ben

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread azjezz
Hello Nikita,

I would love to hear your opinion on the `as` syntax from Hack, and whether it 
can be used in PHP the same way or would it be an issue.

Cheers,

- Saif

Sent with ProtonMail Secure Email.

‐‐‐ Original Message ‐‐‐
On Tuesday, April 23, 2019 10:16 AM, Nikita Popov  wrote:

> On Mon, Apr 22, 2019 at 11:48 PM Benjamin Morel benjamin.mo...@gmail.com
> wrote:
>
> > Hi internals,
> > I'd like to revive an old discussion https://externals.io/message/67131
> > about
> > object type casting.
> > The idea would be to allow (ClassName) casting:
> >
> > $service = (EmailService) $diContainer->get('email.service');
> >
> >
> > The above code would throw a TypeError if the value is not an instance of
> > the given class. I see the following advantages:
> >
> > -   Type safety: we can be sure that the value is of the correct type or 
> > that
> > we'll get an Error. This syntax allows to fail early if the variable
> > happens to not be of the expected type, and avoids much more verbose
> > checks;
> >
> > -   Static analysis: IDEs and static code analysis tools can now understand
> > the type of the variable, without having to resort to `@var` 
> > annotations.
> >
> >
> > These combine into a third advantage: readability. Today's equivalent of
> > the above one-liner could be:
> >
> > /** @var EmailService $service */
> > $service = $diContainer->get('email.service');
> > if (! $service instanceof EmailService) {
> > throw new TypeError('Expected instance of EmailService, ...');
> > }
> >
> >
> > Which is a lot of boilerplate code that could be easily avoided by
> > introducing this new syntax.
> > Before moving forward and working on a formal RFC, I'd like to hear your
> > thoughts: what's your early feeling about this? Did I miss other
> > discussions around this subject? Are there any technical issues that come
> > to mind? Could this feature help the upcoming JIT compiler produce more
> > efficient machine code by knowing the type of the variable at compile time?
> > etc.
> > Note: "casting" might not be the perfect name here as what we're really
> > doing is a type check, but this reuses the type casting syntax and
> > resembles Java's object casting.
> > Thank you,
> > Ben
>
> Without commenting on the rest of the proposal: It's not possible to use
> (ClassName) as a cast syntax, because it is ambiguous. For example (Foo)
> [$x] is already valid syntax (fetch constant Foo and take index $x), or
> (Foo) +$bar, etc.
>
> The only reason why (int) etc are okay is because we treat the whole (int)
> as a single token, something we can't do in general (because it would break
> foo(Foo)).
>
> Nikita



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Andrey Hristov

 Hi,
maybe with short closures this will be pretty easy to implement by 
injecting a short closure that expects the return type to be of the type 
to be casted and to return it.


Something in the like of :

$service = (fn(EmailService $s):EmailService => $s 
;)($diContainer->get('email.service'));


Not that I support pulling services from a container most often being an 
anti-pattern.


Cheers,
Andrey

On 23.04.19 г. 0:47 ч., Benjamin Morel wrote:

Hi internals,

I'd like to revive an old discussion  about
object type casting.

The idea would be to allow (ClassName) casting:

 $service = (EmailService) $diContainer->get('email.service');

The above code would throw a TypeError if the value is not an instance of
the given class. I see the following advantages:

- Type safety: we can be sure that the value is of the correct type or that
we'll get an Error. This syntax allows to fail early if the variable
happens to not be of the expected type, and avoids much more verbose checks;
- Static analysis: IDEs and static code analysis tools can now understand
the type of the variable, without having to resort to `@var` annotations.

These combine into a third advantage: readability. Today's equivalent of
the above one-liner could be:

 /** @var EmailService $service */
 $service = $diContainer->get('email.service');
 if (! $service instanceof EmailService) {
 throw new TypeError('Expected instance of EmailService, ...');
 }

Which is a lot of boilerplate code that could be easily avoided by
introducing this new syntax.

Before moving forward and working on a formal RFC, I'd like to hear your
thoughts: what's your early feeling about this? Did I miss other
discussions around this subject? Are there any technical issues that come
to mind? Could this feature help the upcoming JIT compiler produce more
efficient machine code by knowing the type of the variable at compile time?
etc.

Note: "casting" might not be the perfect name here as what we're really
doing is a type check, but this reuses the type casting syntax and
resembles Java's object casting.

Thank you,
Ben




--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Stephen Reay
> On 23 Apr 2019, at 16:03, Benjamin Morel  wrote:
> 
> >  I like the idea but I find the syntax (both suggestions) less than great, 
> > given that there’s already “ensure a type” syntax, and both suggestions are 
> > already used for other things (casting and foreach)
> 
> Note that we already use `as` in other contexts than foreach: in imports 
> (`use Foo as Bar`) and in traits (`use SomeTrait { foo as bar; }`) , so I 
> think that reusing the keyword for yet another use case is OK, as long as it 
> does not conflict.
> 
> > Is there some reason (eg ambiguities) a type can’t just be placed before a 
> > variable to ensure a type, similar to a function parameter or typed 
> > property? 
> > string $foo = 'bar';
> > ...
> > I’m talking about exactly the same functionality that exists with method 
> > parameters - constraining the type it must conform to when it is declared. 
> > Nothing more nothing less.
> 
> I would personnally read this as "this variable is now strongly typed, 
> INCLUDING later assignments" (which would belong to another feature / 
> discussion), but as you have later clarified that this is not what you had in 
> mind, I think that this syntax is then even more confusing than the other 
> proposals:
> 
> Foo $foo = new Foo();
> $foo = 123; // this would work?
> 
> > Using `as` means trying to add type constraints to an iterable in the 
> > foreach would be ridiculously confusing:
> > foreach ( $foo as $K as int => $v as string) {...}
> 
> Please note that my proposal is specific to class/interface names, not other 
> types for now (I could consider broadening it if people are interested in the 
> suggested "as" syntax from Hack).
> Anyway with the two syntaxes suggested so far, you would not inline it in the 
> foreach, but explicitly write:
> 
> foreach ($foos as $foo) {
> $foo = (Foo) $foo;
> // or
> $foo = $foo as Foo;
> }
> 
> 

Hi Ben,

My objection to `as` is that it specifically prevents (or makes very confusing) 
the `foreach` use I mentioned. There’s no variables involved in imports/traits, 
and neither of those relates to foreach.

As for the `string $foo = $bar->getFoo();` ‘looking strongly typed’ and 
wondering if it will allow re-declaration - do you think the same when you see 
`function (string $foo) { $foo = explode(‘ ‘, $foo); }` ? Functions have 
allowed type hints since 5.0 - nearly 15 years ago, and nobody seems to be 
confused if those variables can be redeclared. Whether you *should* redeclare 
them to a different value is something you need to decide for yourself.


As for limiting this to class/interface names - why would you do that? It took 
YEARS to get scalar type hints for function parameters, why would you not 
include them from the start on anything new that pertains to essentially the 
same functionality?


I can’t even begin to comprehend how re-assigning a variable to itself (even if 
it is a no-op internally, it *appears* to re-assign) to do a type check seems 
like a good option.


Cheers

Stephen
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Nikita Popov
On Mon, Apr 22, 2019 at 11:48 PM Benjamin Morel 
wrote:

> Hi internals,
>
> I'd like to revive an old discussion 
> about
> object type casting.
>
> The idea would be to allow (ClassName) casting:
>
> $service = (EmailService) $diContainer->get('email.service');
>
> The above code would throw a TypeError if the value is not an instance of
> the given class. I see the following advantages:
>
> - Type safety: we can be sure that the value is of the correct type or that
> we'll get an Error. This syntax allows to fail early if the variable
> happens to not be of the expected type, and avoids much more verbose
> checks;
> - Static analysis: IDEs and static code analysis tools can now understand
> the type of the variable, without having to resort to `@var` annotations.
>
> These combine into a third advantage: readability. Today's equivalent of
> the above one-liner could be:
>
> /** @var EmailService $service */
> $service = $diContainer->get('email.service');
> if (! $service instanceof EmailService) {
> throw new TypeError('Expected instance of EmailService, ...');
> }
>
> Which is a lot of boilerplate code that could be easily avoided by
> introducing this new syntax.
>
> Before moving forward and working on a formal RFC, I'd like to hear your
> thoughts: what's your early feeling about this? Did I miss other
> discussions around this subject? Are there any technical issues that come
> to mind? Could this feature help the upcoming JIT compiler produce more
> efficient machine code by knowing the type of the variable at compile time?
> etc.
>
> Note: "casting" might not be the perfect name here as what we're really
> doing is a type check, but this reuses the type casting syntax and
> resembles Java's object casting.
>
> Thank you,
> Ben
>

Without commenting on the rest of the proposal: It's not possible to use
(ClassName) as a cast syntax, because it is ambiguous. For example (Foo)
[$x] is already valid syntax (fetch constant Foo and take index $x), or
(Foo) +$bar, etc.

The only reason why (int) etc are okay is because we treat the whole (int)
as a single token, something we can't do in general (because it would break
foo(Foo)).

Nikita


Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-23 Thread Benjamin Morel
Hi all, thanks for the valuable feedback!

@Stephen Reay:

>  I like the idea but I find the syntax (both suggestions) less than
great, given that there’s already “ensure a type” syntax, and both
suggestions are already used for other things (casting and foreach)

Note that we already use `as` in other contexts than foreach: in imports
(`use Foo as Bar`) and in traits (`use SomeTrait { foo as bar; }`) , so I
think that reusing the keyword for yet another use case is OK, as long as
it does not conflict.

> Is there some reason (eg ambiguities) a type can’t just be placed before
a variable to ensure a type, similar to a function parameter or typed
property?
> string $foo = 'bar';
> ...
> I’m talking about exactly the same functionality that exists with method
parameters - constraining the type it must conform to when it is declared.
Nothing more nothing less.

I would personnally read this as "this variable is now strongly typed,
INCLUDING later assignments" (which would belong to another feature /
discussion), but as you have later clarified that this is not what you had
in mind, I think that this syntax is then even more confusing than the
other proposals:

Foo $foo = new Foo();
$foo = 123; // this would work?

> Using `as` means trying to add type constraints to an iterable in the
foreach would be ridiculously confusing:
> foreach ( $foo as $K as int => $v as string) {...}

Please note that my proposal is specific to class/interface names, not
other types for now (I could consider broadening it if people are
interested in the suggested "as" syntax from Hack).
Anyway with the two syntaxes suggested so far, you would not inline it in
the foreach, but explicitly write:

foreach ($foos as $foo) {
$foo = (Foo) $foo;
// or
$foo = $foo as Foo;
}

@Andreas Hennings:

> If I remember correctly, an object pointer (object variable) in Java has
a type independent of the object it points to. The pointer type restricts
the range of object types that can be pointed to from the variable.
> You can cast the pointer type (variable type) to let a variable of
different object pointer type store the same object, as long as the type is
compatible.
> In PHP, variables have no type on language level, so casting would indeed
be a misleading concept. Unless we want to change this.

You have a point for sure, but as I said above, I don't feel like this
makes it incompatible with casting semantics.

In Java, casting to a class/interface name:

1. ensures that the variable holds an instance of this class/interface
2. changes the pointer type, which affects later usage of the object

In PHP, you'd just scratch point #2 which is irrelevant. Is this a good
enough reason to stop using the casting syntax? I'm not sure.

@Sebastian Bergmann:

> Today's equivalent is, at least for me, is this one-liner:
> assert($service instanceof EmailService);

Let's be picky: this is actually a two-liner, a second line after the
variable declaration ;-)

> This way the IDE knows what type $service is supposed to be and there
will
> be an exception at runtime (given the appropriate configuration) when
this
> is not the case.

That's a fair point regarding the IDE. The exception at runtime however,
becomes strongly dependent on PHP configuration.
We're also losing the advantage of an explicit language construct, that I
suspect could be later used by the JIT compiler to generate more efficient
machine code by knowing the type of the variable at this point at compile
time (I'd love to get feedback on this point from Dmitry).

> Personally, I prefer hand-written factories that have an explicit
> createEmailService() method with a :EmailService return type declaration,
> for example, over the implicitness of a dependency injection container as
> the latter disguises and obscures dependencies.

We're entering the realm of patterns here; I'm a big fan of IoC myself and
even though I use it a lot in my apps, I still find myself calling
`$diContainer->get()` more often than not, for example in quick prototypes
or CLI scripts. Same thing for ORMs: you may have a full-blown repository
for each entity with a strongly typed `find() : ClassName` method, but you
may also need to call `$entityManager->find()` directly from time to time.
There are also plenty of other use cases in PHP, where you get a variable
from a losely typed source (array or whatever), but somehow know that it
should be of a given type.

- Ben


On Tue, 23 Apr 2019 at 07:58, M. W. Moe  wrote:

> Hello,
>
> Sebastian yes; interface or abstract have been somehow created for that
> purpose; even if I find people abusing of those constructs; now if your
> container is generalized and represents dynamic data; for instance like a
> Message class
> it could hold dynamic data types;
>
> let say:
> // abstract public offsetGet
>  ( mixed
> <
> 

Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread M. W. Moe
Hello,

Sebastian yes; interface or abstract have been somehow created for that
purpose; even if I find people abusing of those constructs; now if your
container is generalized and represents dynamic data; for instance like a
Message class
it could hold dynamic data types;

let say:
// abstract public offsetGet
 ( mixed

 $offset ) : mixed

$service = $diContainer['email.service'] of ?EmailService; // else throw
TypeError(this type instead of null or EmailService)


On Mon, Apr 22, 2019 at 10:07 PM Sebastian Bergmann 
wrote:

> Am 22.04.2019 um 23:47 schrieb Benjamin Morel:
> > These combine into a third advantage: readability. Today's equivalent of
> > the above one-liner could be:
> >
> >  /** @var EmailService $service */
> >  $service = $diContainer->get('email.service');
> >  if (! $service instanceof EmailService) {
> >  throw new TypeError('Expected instance of EmailService, ...');
> >  }
>
> Today's equivalent is, at least for me, is this one-liner:
>
>  assert($service instanceof EmailService);
>
> This way the IDE knows what type $service is supposed to be and there will
> be an exception at runtime (given the appropriate configuration) when this
> is not the case.
>
> Personally, I prefer hand-written factories that have an explicit
> createEmailService() method with a :EmailService return type declaration,
> for example, over the implicitness of a dependency injection container as
> the latter disguises and obscures dependencies.
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread Sebastian Bergmann

Am 22.04.2019 um 23:47 schrieb Benjamin Morel:

These combine into a third advantage: readability. Today's equivalent of
the above one-liner could be:

 /** @var EmailService $service */
 $service = $diContainer->get('email.service');
 if (! $service instanceof EmailService) {
 throw new TypeError('Expected instance of EmailService, ...');
 }


Today's equivalent is, at least for me, is this one-liner:

assert($service instanceof EmailService);

This way the IDE knows what type $service is supposed to be and there will 
be an exception at runtime (given the appropriate configuration) when this 
is not the case.


Personally, I prefer hand-written factories that have an explicit 
createEmailService() method with a :EmailService return type declaration, 
for example, over the implicitness of a dependency injection container as 
the latter disguises and obscures dependencies.


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread Stephen Reay



> On 23 Apr 2019, at 07:50, azjezz  wrote:
> 
> I think we would be talking about typed variables at that point.
> 
> 
> ( something you can do with PHP 7.4 http://github.com/azjezz/typed )
> 
> even though `as` is used with `foreach`, i don't think it would be an issue 
> to use it for something else, but i think i will leave that to someone who's 
> more familiar with the PHP parser than me.
> 
> 
> Cheers.
> 
> Sent with ProtonMail Secure Email.
> 
> ‐‐‐ Original Message ‐‐‐
> On Tuesday, April 23, 2019 1:43 AM, Stephen Reay  
> wrote:
> 
>>> On 23 Apr 2019, at 06:30, azjezz azj...@protonmail.com wrote:
>>> Hello Ben.
>>> yes, i have made a gist with a simple example to show the `as` operator 
>>> usage in hack + HHVM ( 4.1.0 ) output.
>>> see : https://gist.github.com/azjezz/03955ff2b009f1ced22ce68c9a862847
>>> Sent with ProtonMail Secure Email.
>>> ‐‐‐ Original Message ‐‐‐
>>> 
 On Monday, April 22, 2019 11:50 PM, Benjamin Morel 
 benjamin.mo...@gmail.com wrote:
 Hi Azjezz, thanks for jumping in!
 
> I have been using HackLang for quite a while now and i believe they have 
> a better solution for this, and it would awesome to see it in PHP, the 
> `as` operator.
 
 If I understand correctly, `as` is an operator that performs type checks 
 but never casts like () does.
 This looks like a serious candidate for an alternative syntax to the one I 
 proposed!
 
 -   Ben
>> 
>> I like the idea but I find the syntax (both suggestions) less than great, 
>> given that there’s already “ensure a type” syntax, and both suggestions are 
>> already used for other things (casting and foreach)
>> 
>> Is there some reason (eg ambiguities) a type can’t just be placed before a 
>> variable to ensure a type, similar to a function parameter or typed property?
>> 
>> Eg
>> 
>> string $foo = 'bar';
>> array $bar = getBar();
>> foreach($bar as int $k => string $v) {...}
>> 
>> Cheers
>> 
>> Stephen
> 
> 

I’m talking about exactly the same functionality that exists with method 
parameters - constraining the type it must conform to when it is declared. 
Nothing more nothing less.

Using `as` means trying to add type constraints to an iterable in the foreach 
would be ridiculously confusing:

foreach ( $foo as $K as int => $v as string) {...}

And the cast syntax re-use means you’d not be able to use the object pseudotype 
(or you’d have to remove casting to object) 

 Cheers

Stephen

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread azjezz
I think we would be talking about typed variables at that point.


( something you can do with PHP 7.4 http://github.com/azjezz/typed )

even though `as` is used with `foreach`, i don't think it would be an issue to 
use it for something else, but i think i will leave that to someone who's more 
familiar with the PHP parser than me.


Cheers.

Sent with ProtonMail Secure Email.

‐‐‐ Original Message ‐‐‐
On Tuesday, April 23, 2019 1:43 AM, Stephen Reay  
wrote:

> > On 23 Apr 2019, at 06:30, azjezz azj...@protonmail.com wrote:
> > Hello Ben.
> > yes, i have made a gist with a simple example to show the `as` operator 
> > usage in hack + HHVM ( 4.1.0 ) output.
> > see : https://gist.github.com/azjezz/03955ff2b009f1ced22ce68c9a862847
> > Sent with ProtonMail Secure Email.
> > ‐‐‐ Original Message ‐‐‐
> >
> > > On Monday, April 22, 2019 11:50 PM, Benjamin Morel 
> > > benjamin.mo...@gmail.com wrote:
> > > Hi Azjezz, thanks for jumping in!
> > >
> > > > I have been using HackLang for quite a while now and i believe they 
> > > > have a better solution for this, and it would awesome to see it in PHP, 
> > > > the `as` operator.
> > >
> > > If I understand correctly, `as` is an operator that performs type checks 
> > > but never casts like () does.
> > > This looks like a serious candidate for an alternative syntax to the one 
> > > I proposed!
> > >
> > > -   Ben
>
> I like the idea but I find the syntax (both suggestions) less than great, 
> given that there’s already “ensure a type” syntax, and both suggestions are 
> already used for other things (casting and foreach)
>
> Is there some reason (eg ambiguities) a type can’t just be placed before a 
> variable to ensure a type, similar to a function parameter or typed property?
>
> Eg
>
> string $foo = 'bar';
> array $bar = getBar();
> foreach($bar as int $k => string $v) {...}
>
> Cheers
>
> Stephen



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread Marcos Passos
Such a feature would be very helpful to ensure type safety! A big +1!

On Mon, Apr 22, 2019 at 19:51 Benjamin Morel 
wrote:

> Hi Azjezz, thanks for jumping in!
>
> > I have been using HackLang for quite a while now and i believe they have
> a better solution for this, and it would awesome to see it in PHP, the `as`
> operator.
>
> If I understand correctly, `as` is an operator that performs type checks
> but never casts like () does.
> This looks like a serious candidate for an alternative syntax to the one I
> proposed!
>
> - Ben
>


Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread Stephen Reay



> On 23 Apr 2019, at 06:30, azjezz  wrote:
> 
> Hello Ben.
> 
> yes, i have made a gist with a simple example to show the `as` operator usage 
> in hack + HHVM ( 4.1.0 ) output.
> 
> see : https://gist.github.com/azjezz/03955ff2b009f1ced22ce68c9a862847
> 
> Sent with [ProtonMail](https://protonmail.com) Secure Email.
> 
> ‐‐‐ Original Message ‐‐‐
>> On Monday, April 22, 2019 11:50 PM, Benjamin Morel 
>>  wrote:
>> 
>> Hi Azjezz, thanks for jumping in!
>> 
>>> I have been using HackLang for quite a while now and i believe they have a 
>>> better solution for this, and it would awesome to see it in PHP, the `as` 
>>> operator.
>> 
>> If I understand correctly, `as` is an operator that performs type checks but 
>> never casts like () does.
>> This looks like a serious candidate for an alternative syntax to the one I 
>> proposed!
>> 
>> - Ben

I like the idea but I find the syntax (both suggestions) less than great, given 
that there’s already “ensure a type” syntax, and both suggestions are already 
used for other things (casting and foreach)

Is there some reason (eg ambiguities) a type can’t just be placed before a 
variable to ensure a type, similar to a function parameter or typed property?

Eg 

string $foo = 'bar';
array $bar = getBar();
foreach($bar as int $k => string $v) {...}


Cheers


Stephen

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread azjezz
Hello Ben.

yes, i have made a gist with a simple example to show the `as` operator usage 
in hack + HHVM ( 4.1.0 ) output.

see : https://gist.github.com/azjezz/03955ff2b009f1ced22ce68c9a862847

Sent with [ProtonMail](https://protonmail.com) Secure Email.

‐‐‐ Original Message ‐‐‐
On Monday, April 22, 2019 11:50 PM, Benjamin Morel  
wrote:

> Hi Azjezz, thanks for jumping in!
>
>> I have been using HackLang for quite a while now and i believe they have a 
>> better solution for this, and it would awesome to see it in PHP, the `as` 
>> operator.
>
> If I understand correctly, `as` is an operator that performs type checks but 
> never casts like () does.
> This looks like a serious candidate for an alternative syntax to the one I 
> proposed!
>
> - Ben

Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread Benjamin Morel
Hi Azjezz, thanks for jumping in!

> I have been using HackLang for quite a while now and i believe they have
a better solution for this, and it would awesome to see it in PHP, the `as`
operator.

If I understand correctly, `as` is an operator that performs type checks
but never casts like () does.
This looks like a serious candidate for an alternative syntax to the one I
proposed!

- Ben


Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread Benjamin Morel
Hi Larry, thanks for the early feedback!

> First thought: I'm all for easy ways to be more type-explicit, so yay on
the concept.

Glad to hear that!

> Second thought: (...) how many use cases for that are there other than
function boundaries, which we already have covered?

I chose an example where function boundaries are typically not covered:
dependency injection containers, which have some generic `get()` method
that can return any type.
Another one is ORMs: Doctrine's EntityManager::find(), for example, returns
a generic `object`.

> The second I can see being easily handled by this syntax.  The former,
how would that look?

I guess it could be used this way:

foreach ($arrayOfFoo as $foo) {
((Foo) $foo)->bar();
}

Although this use case is not the primary motivation for this feature,
which is not meant to replace all object type hints.

> Third thought: Casting is the wrong name here, and feels also misleading
as a syntax.

I suspected this would come up, hence the final note; I'm open to
suggestions for alternatives. Please note that Java's object casting uses
the same syntax, and follows the same semantics of
throw-if-not-instance-of. The difference, if I'm not mistaken, is that you
can type-hint an object to more generic interface or parent class, or, on
the contrary, type-hint it to a more specific sub-class or concrete class
to make its members accessible; this part is obviously not needed in PHP as
the VM does not care what the type is before attempting to access one of
its members. But I'm not sure if the fact that we miss the "conversion"
part is enough to justify a change in naming or syntax compared to the Java
equivalent?

- Ben


On Tue, 23 Apr 2019 at 00:03, Larry Garfield  wrote:

> On Mon, Apr 22, 2019, at 4:47 PM, Benjamin Morel wrote:
> > Hi internals,
> >
> > I'd like to revive an old discussion 
> about
> > object type casting.
> >
> > The idea would be to allow (ClassName) casting:
> >
> > $service = (EmailService) $diContainer->get('email.service');
> >
> > The above code would throw a TypeError if the value is not an instance of
> > the given class. I see the following advantages:
> >
> > - Type safety: we can be sure that the value is of the correct type or
> that
> > we'll get an Error. This syntax allows to fail early if the variable
> > happens to not be of the expected type, and avoids much more verbose
> checks;
> > - Static analysis: IDEs and static code analysis tools can now understand
> > the type of the variable, without having to resort to `@var` annotations.
> >
> > These combine into a third advantage: readability. Today's equivalent of
> > the above one-liner could be:
> >
> > /** @var EmailService $service */
> > $service = $diContainer->get('email.service');
> > if (! $service instanceof EmailService) {
> > throw new TypeError('Expected instance of EmailService, ...');
> > }
> >
> > Which is a lot of boilerplate code that could be easily avoided by
> > introducing this new syntax.
> >
> > Before moving forward and working on a formal RFC, I'd like to hear your
> > thoughts: what's your early feeling about this? Did I miss other
> > discussions around this subject? Are there any technical issues that come
> > to mind? Could this feature help the upcoming JIT compiler produce more
> > efficient machine code by knowing the type of the variable at compile
> time?
> > etc.
> >
> > Note: "casting" might not be the perfect name here as what we're really
> > doing is a type check, but this reuses the type casting syntax and
> > resembles Java's object casting.
> >
> > Thank you,
> > Ben
>
> Hi Ben.
>
> First thought: I'm all for easy ways to be more type-explicit, so yay on
> the concept.
>
> Second thought: That said, how many use cases for that are there other
> than function boundaries, which we already have covered?
>
> I can think of two:  foreach() loops and returns where you know the return
> type with more specificity than the method you're calling.  Example:
>
> /** @var Foo $foo *//
> foreach ($arrayOfFoo as $foo) {
>   $foo->bar();
> }
>
> Example from PSR-14, in which you know the object you're getting back MUST
> be the same one that's passed in but dispatch() has no return type:
>
> /** @var Foo $event **/
> $event = $dispatcher->dispatch(new Foo());
>
> The second I can see being easily handled by this syntax.  The former, how
> would that look?
>
> Third thought: Casting is the wrong name here, and feels also misleading
> as a syntax.  (float)$anInt means "type coerce this thing into a float",
> which cannot error.  You're suggesting (Foo)$bar to mean "if this isn't
> already a Foo, throw."  That's a very different behavior semantic for the
> same syntax.  Is that a land mine?  I would expect (Foo)$bar to mean
> "recast $bar into an instance of Foo if possible, and error if not".
> Which... I suppose "is it already" is a subcase of that, but it's still not
> the behavior 

Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread azjezz
Hello, Internals.

I have been using HackLang for quite a while now and i believe they have a 
better solution for this, and it would awesome to see it in PHP, the `as` 
operator.

see : https://docs.hhvm.com/hack/expressions-and-operators/as

---

when i see :

```
$foo = (Foo) $object;
```
i think that `$object` is going to be converted to an instance of `Foo`, not 
ensure that its an instance of `Foo`.

Hack `as` operator
```
$foo = $object as Foo;
// or
$object as Foo;
// use `$object` now, known that its an instance of `Foo`

```

> a `TypeAssertionException` expect would be throw if `$object` is not `Foo`.






Sent with ProtonMail Secure Email.

‐‐‐ Original Message ‐‐‐
On Monday, April 22, 2019 11:03 PM, Larry Garfield  
wrote:

> On Mon, Apr 22, 2019, at 4:47 PM, Benjamin Morel wrote:
>
> > Hi internals,
> > I'd like to revive an old discussion https://externals.io/message/67131 
> > about
> > object type casting.
> > The idea would be to allow (ClassName) casting:
> >
> > $service = (EmailService) $diContainer->get('email.service');
> >
> >
> > The above code would throw a TypeError if the value is not an instance of
> > the given class. I see the following advantages:
> >
> > -   Type safety: we can be sure that the value is of the correct type or 
> > that
> > we'll get an Error. This syntax allows to fail early if the variable
> > happens to not be of the expected type, and avoids much more verbose 
> > checks;
> >
> > -   Static analysis: IDEs and static code analysis tools can now understand
> > the type of the variable, without having to resort to `@var` 
> > annotations.
> >
> >
> > These combine into a third advantage: readability. Today's equivalent of
> > the above one-liner could be:
> >
> > /** @var EmailService $service */
> > $service = $diContainer->get('email.service');
> > if (! $service instanceof EmailService) {
> > throw new TypeError('Expected instance of EmailService, ...');
> > }
> >
> >
> > Which is a lot of boilerplate code that could be easily avoided by
> > introducing this new syntax.
> > Before moving forward and working on a formal RFC, I'd like to hear your
> > thoughts: what's your early feeling about this? Did I miss other
> > discussions around this subject? Are there any technical issues that come
> > to mind? Could this feature help the upcoming JIT compiler produce more
> > efficient machine code by knowing the type of the variable at compile time?
> > etc.
> > Note: "casting" might not be the perfect name here as what we're really
> > doing is a type check, but this reuses the type casting syntax and
> > resembles Java's object casting.
> > Thank you,
> > Ben
>
> Hi Ben.
>
> First thought: I'm all for easy ways to be more type-explicit, so yay on the 
> concept.
>
> Second thought: That said, how many use cases for that are there other than 
> function boundaries, which we already have covered?
>
> I can think of two: foreach() loops and returns where you know the return 
> type with more specificity than the method you're calling. Example:
>
> /** @var Foo $foo *//
> foreach ($arrayOfFoo as $foo) {
> $foo->bar();
> }
>
> Example from PSR-14, in which you know the object you're getting back MUST be 
> the same one that's passed in but dispatch() has no return type:
>
> /** @var Foo $event **/
> $event = $dispatcher->dispatch(new Foo());
>
> The second I can see being easily handled by this syntax. The former, how 
> would that look?
>
> Third thought: Casting is the wrong name here, and feels also misleading as a 
> syntax. (float)$anInt means "type coerce this thing into a float", which 
> cannot error. You're suggesting (Foo)$bar to mean "if this isn't already a 
> Foo, throw." That's a very different behavior semantic for the same syntax. 
> Is that a land mine? I would expect (Foo)$bar to mean "recast $bar into an 
> instance of Foo if possible, and error if not". Which... I suppose "is it 
> already" is a subcase of that, but it's still not the behavior I'd expect 
> from that syntax.
>
> --Larry Garfield
>
> ---
>
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread Larry Garfield
On Mon, Apr 22, 2019, at 4:47 PM, Benjamin Morel wrote:
> Hi internals,
> 
> I'd like to revive an old discussion  
> about
> object type casting.
> 
> The idea would be to allow (ClassName) casting:
> 
> $service = (EmailService) $diContainer->get('email.service');
> 
> The above code would throw a TypeError if the value is not an instance of
> the given class. I see the following advantages:
> 
> - Type safety: we can be sure that the value is of the correct type or that
> we'll get an Error. This syntax allows to fail early if the variable
> happens to not be of the expected type, and avoids much more verbose checks;
> - Static analysis: IDEs and static code analysis tools can now understand
> the type of the variable, without having to resort to `@var` annotations.
> 
> These combine into a third advantage: readability. Today's equivalent of
> the above one-liner could be:
> 
> /** @var EmailService $service */
> $service = $diContainer->get('email.service');
> if (! $service instanceof EmailService) {
> throw new TypeError('Expected instance of EmailService, ...');
> }
> 
> Which is a lot of boilerplate code that could be easily avoided by
> introducing this new syntax.
> 
> Before moving forward and working on a formal RFC, I'd like to hear your
> thoughts: what's your early feeling about this? Did I miss other
> discussions around this subject? Are there any technical issues that come
> to mind? Could this feature help the upcoming JIT compiler produce more
> efficient machine code by knowing the type of the variable at compile time?
> etc.
> 
> Note: "casting" might not be the perfect name here as what we're really
> doing is a type check, but this reuses the type casting syntax and
> resembles Java's object casting.
> 
> Thank you,
> Ben

Hi Ben.

First thought: I'm all for easy ways to be more type-explicit, so yay on the 
concept.

Second thought: That said, how many use cases for that are there other than 
function boundaries, which we already have covered?

I can think of two:  foreach() loops and returns where you know the return type 
with more specificity than the method you're calling.  Example:

/** @var Foo $foo *//
foreach ($arrayOfFoo as $foo) {
  $foo->bar();
}

Example from PSR-14, in which you know the object you're getting back MUST be 
the same one that's passed in but dispatch() has no return type:

/** @var Foo $event **/
$event = $dispatcher->dispatch(new Foo());

The second I can see being easily handled by this syntax.  The former, how 
would that look?

Third thought: Casting is the wrong name here, and feels also misleading as a 
syntax.  (float)$anInt means "type coerce this thing into a float", which 
cannot error.  You're suggesting (Foo)$bar to mean "if this isn't already a 
Foo, throw."  That's a very different behavior semantic for the same syntax.  
Is that a land mine?  I would expect (Foo)$bar to mean "recast $bar into an 
instance of Foo if possible, and error if not".  Which... I suppose "is it 
already" is a subcase of that, but it's still not the behavior I'd expect from 
that syntax.

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Object Type Casting Reloaded

2019-04-22 Thread Benjamin Morel
Hi internals,

I'd like to revive an old discussion  about
object type casting.

The idea would be to allow (ClassName) casting:

$service = (EmailService) $diContainer->get('email.service');

The above code would throw a TypeError if the value is not an instance of
the given class. I see the following advantages:

- Type safety: we can be sure that the value is of the correct type or that
we'll get an Error. This syntax allows to fail early if the variable
happens to not be of the expected type, and avoids much more verbose checks;
- Static analysis: IDEs and static code analysis tools can now understand
the type of the variable, without having to resort to `@var` annotations.

These combine into a third advantage: readability. Today's equivalent of
the above one-liner could be:

/** @var EmailService $service */
$service = $diContainer->get('email.service');
if (! $service instanceof EmailService) {
throw new TypeError('Expected instance of EmailService, ...');
}

Which is a lot of boilerplate code that could be easily avoided by
introducing this new syntax.

Before moving forward and working on a formal RFC, I'd like to hear your
thoughts: what's your early feeling about this? Did I miss other
discussions around this subject? Are there any technical issues that come
to mind? Could this feature help the upcoming JIT compiler produce more
efficient machine code by knowing the type of the variable at compile time?
etc.

Note: "casting" might not be the perfect name here as what we're really
doing is a type check, but this reuses the type casting syntax and
resembles Java's object casting.

Thank you,
Ben