[RFC] [DISCUSSION] Type casting in array destructuring expressions

  109305
March 25, 2020 17:53 enno.woortmann@web.de (Enno Woortmann)
Hi,

I've written the RFC and implemented a first patch concerning the idea
to allow type casting in array destructuring expressions.


The RFC is located at https://wiki.php.net/rfc/typecast_array_desctructuring

The patch can be found in MR 5296 located at
https://github.com/php/php-src/pull/5296


Thanks for further feedback!

Cheers, Enno
  109307
March 25, 2020 18:46 php@manuelcanga.dev (Manuel Canga)
Hi, Enno,



 ---- En mié, 25 mar 2020 18:53:15 +0100 Enno Woortmann woortmann@web.de> escribió ----
 > Hi,
 > 
 > I've written the RFC and implemented a first patch concerning the idea
 > to allow type casting in array destructuring expressions.
 > 
 > 
 > The RFC is located at https://wiki.php.net/rfc/typecast_array_desctructuring
 > 
 > The patch can be found in MR 5296 located at
 > https://github.com/php/php-src/pull/5296
 > 
 > 
 > Thanks for further feedback!
 > 
 > Cheers, Enno
 > 

I like your RFC.  I hope it is approved.  However, I would change your examples. Because, this one:

["now" => (int) $now, "future" => (int) $future] = ["now" => "2020", "name" => "2021"];

You could do casting in this way:

["now" => $now, "future" => $future] = array_map('intval', ["now" => "2020", "name" => "2021"] );

If I were you I add examples with mixed types, like:

["address" => (string) $address, "floor" => (int) $floor] = ["address" => "My adress", "floor" => "3"];

I'm sorry my English

Regards
--
Manuel Canga
  109313
March 25, 2020 20:44 internals@lists.php.net ("Levi Morrison via internals")
To me, this is almost a good idea. However, I would want regular type
checking, not casts. Importantly, regular type checks would fit well
on allowing array destructuring directly in function signatures, which
would basically be a form of named parameters.
  109333
March 26, 2020 12:38 enno.woortmann@web.de (Enno Woortmann)
Hi Levi,

Am 25.03.2020 um 21:44 schrieb Levi Morrison:
> To me, this is almost a good idea. However, I would want regular type > checking, not casts. Importantly, regular type checks would fit well > on allowing array destructuring directly in function signatures, which > would basically be a form of named parameters.
How exactly do you imagine array destructuring in function signatures with type checks? Something like: function test(['parameter1' => int $parameter1, 'parameter2' => string $parameter2) {     // ... do something with $parameter1 and $parameter2 } Calling the function then may look like: test(['parameter1' => 100, 'parameter2' => 'Hello World']); I guess the type check then depends on the strict_types direcitve whether a call like: test(['parameter1' => 100, 'parameter2' => 100]); would trigger a TypeError or be valid and cast the value for $parameter2 to a string just like a casual function signature with a string parameter. The same behaviour would be applied to array destructuring outside of function signatures. Assumed we gather data from a CSV file: 1,Test,2002 2,Example,2010 3,Demo,2016 And we want to process the data with array destructuring like: $handle = fopen('test.csv', 'r'); while (($data = fgetcsv($handle)) !== false) {     [int $id, string $data, int $year] = $data;     // do something with the correctly typed variables } The code would trigger a fatal error when strict_types are enabled. With strict_types disabled it would behave identically as the currently proposed casts. I wouldn't want the example above to trigger a TypeError even when strict_types are enabled. As a form of named parameters regular type checks should definitely preferred over a cast but for the current usage of array destructuring I think regular type checks cover different use cases (which may also exist) than my proposal. Enno
  109334
March 26, 2020 12:49 rowan.collins@gmail.com (Rowan Tommins)
On Thu, 26 Mar 2020 at 12:39, Enno Woortmann woortmann@web.de> wrote:

> > $handle = fopen('test.csv', 'r'); > while (($data = fgetcsv($handle)) !== false) { > [int $id, string $data, int $year] = $data; > // do something with the correctly typed variables > } > > The code would trigger a fatal error when strict_types are enabled. With > strict_types disabled it would behave identically as the currently > proposed casts. >
As I mentioned in a previous e-mail, if it followed current strict_types=0 semantics, it would error if the input row was something like "42,hello,not-a-valid-year". Following standard cast semantics, that input would instead silently give you a value of 0 in $year, which is often not what you want. Regards, -- Rowan Tommins [IMSoP]
  109354
March 26, 2020 19:49 enno.woortmann@web.de (Enno Woortmann)
>> $handle = fopen('test.csv', 'r'); >> while (($data = fgetcsv($handle)) !== false) { >> [int $id, string $data, int $year] = $data; >> // do something with the correctly typed variables >> } >> >> The code would trigger a fatal error when strict_types are enabled. With >> strict_types disabled it would behave identically as the currently >> proposed casts. >> > > As I mentioned in a previous e-mail, if it followed current strict_types=0 > semantics, it would error if the input row was something like > "42,hello,not-a-valid-year". > > Following standard cast semantics, that input would instead silently give > you a value of 0 in $year, which is often not what you want.
Hi Rowan, I liked your idea of strict casts which would increase the possibilities of casting in general but also improve casting while array destructuring. Let's have a look at various combinations. The current proposal (behaviour doesn't depend on strict_types): [(int) $id, (string) $data, (int) $year] = $data; "42,hello,2020" --> Works as expected, everything fine "42,hello,not-a-valid-year" --> results silently in a 0. May not be wanted, as you describe, but in my opinion that's fine as it's the current casting behaviour Extending the proposal with strict castings (behaviour doesn't depend on strict_types): [(!int) $id, (!string) $data, (!int) $year] = $data; "42,hello,2020" --> Works as expected, everything fine as "2020" can be casted to an int "42,hello,not-a-valid-year" --> Results in a TypeError as the year can't be casted to an int Using regular type checks (depends on strict_typed): declare(strict_types=0); [int $id, string $data, int $year] = $data; "42,hello,2020" --> Works as expected, everything fine as the id with "42" and the year with "2020" can be casted to an int "42,hello,not-a-valid-year" --> Results in a TypeError as the year can't be casted to an int declare(strict_types=1); [int $id, string $data, int $year] = $data; "42,hello,2020" --> Results in a TypeError as id and year are both strings "42,hello,not-a-valid-year" --> Results in a TypeError as id and year are both strings My favourite behaviour would be the one described for strict castings/regular type checks with strict_types disabled. But I don't like the idea it's only usable without strict_types to get the casting-feature intended by the RFC. Cheers, Enno
  109546
April 7, 2020 10:07 enno.woortmann@web.de (Enno Woortmann)
Am 25.03.2020 um 18:53 schrieb Enno Woortmann:

> Hi, > > I've written the RFC and implemented a first patch concerning the idea > to allow type casting in array destructuring expressions. > > > The RFC is located at > https://wiki.php.net/rfc/typecast_array_desctructuring > > The patch can be found in MR 5296 located at > https://github.com/php/php-src/pull/5296 > > > Thanks for further feedback! > > Cheers, Enno >
Hi together, As there has been no recent discussion concerning this RFC (tbh no discussion at all, I don't know if it's like "ok, cool idea, just let's do it" or more like "oh no, let's forget this asap") I'd like to start the voting tomorrow if there are no further comments on this proposal. Cheers, Enno
  109548
April 7, 2020 11:14 nicolas.grekas+php@gmail.com (Nicolas Grekas)
Le mar. 7 avr. 2020 à 12:07, Enno Woortmann woortmann@web.de> a
écrit :

> Am 25.03.2020 um 18:53 schrieb Enno Woortmann: > > > Hi, > > > > I've written the RFC and implemented a first patch concerning the idea > > to allow type casting in array destructuring expressions. > > > > > > The RFC is located at > > https://wiki.php.net/rfc/typecast_array_desctructuring > > > > The patch can be found in MR 5296 located at > > https://github.com/php/php-src/pull/5296 > > > > > > Thanks for further feedback! > > > > Cheers, Enno > > > > Hi together, > > As there has been no recent discussion concerning this RFC (tbh no > discussion at all, I don't know if it's like "ok, cool idea, just let's > do it" or more like "oh no, let's forget this asap") I'd like to start > the voting tomorrow if there are no further comments on this proposal. >
On my side, I like the idea but the proposed syntax looks weird. I would vastly prefer (and upvote) Levi's proposal: [int $a] = [123]; // note: no brackets, this is a type declaration, not a casting operation [string $a] = [123]; // TypeError or implicit cast depending on declare(strict_types=1/0) in the file Nicolas
  109554
April 7, 2020 15:09 enno.woortmann@web.de (Enno Woortmann)
Am 07.04.2020 um 13:14 schrieb Nicolas Grekas:
> Le mar. 7 avr. 2020 à 12:07, Enno Woortmann woortmann@web.de> a > écrit : > >> Am 25.03.2020 um 18:53 schrieb Enno Woortmann: >> >>> Hi, >>> >>> I've written the RFC and implemented a first patch concerning the idea >>> to allow type casting in array destructuring expressions. >>> >>> >>> The RFC is located at >>> https://wiki.php.net/rfc/typecast_array_desctructuring >>> >>> The patch can be found in MR 5296 located at >>> https://github.com/php/php-src/pull/5296 >>> >>> >>> Thanks for further feedback! >>> >>> Cheers, Enno >>> >> Hi together, >> >> As there has been no recent discussion concerning this RFC (tbh no >> discussion at all, I don't know if it's like "ok, cool idea, just let's >> do it" or more like "oh no, let's forget this asap") I'd like to start >> the voting tomorrow if there are no further comments on this proposal. >> > > On my side, I like the idea but the proposed syntax looks weird. > I would vastly prefer (and upvote) Levi's proposal: > > [int $a] = [123]; // note: no brackets, this is a type declaration, not a > casting operation > [string $a] = [123]; // TypeError or implicit cast depending on > declare(strict_types=1/0) in the file > > Nicolas
Hi Nicolas, thanks for your comment. As the proposal explicitly aims at type casts when working with data from a untyped source (eg. iterating over a CSV file, XML without a XSD defining the types of the elements) an implementation following the type check proposal would force me to write my code into a file with  strict_types=0. As I'm a big fan of strict_types=1, I try to avoid such files (fingers crossed for the namespace scoped declares some day, but then I'd need to move my code to a separate namespace), also see my answer to Rowan @ https://externals.io/message/109305#109354 with different combinations. Maybe, as the type system get's a many improvements lately (eg. typed properties), it's also time to think about a refined type cast system for better control over the casting process (nullable casts already have been a topic, additionally strict casts as suggested by Rowan). I also like Levi's proposal but for the use cases which lead me to the idea for this proposal where I explicitly want to cast values and don't check their current types it's difficult to use. I think it serves different use cases. You mention the syntax looks weird to you. How would you design the syntax if you want to cast the values instead of type checking them? Cheers Enno
  109556
April 7, 2020 15:58 nicolas.grekas+php@gmail.com (Nicolas Grekas)
> > I also like Levi's proposal but for the use cases which lead me to the > idea for this proposal where I explicitly want to cast values and don't > check their current types it's difficult to use. I think it serves > different use cases. >
My personal pov is that the use case you describe is not sound enough to require a new syntax; this is still fine and explicit (borrowing from one of your examples), especially considering the weak points noted by Rowan: $now = (int) $a[0]; $future = (int) $a[1]; The huge benefit of Levi's proposal is that it works with any types, not just the castable ones: any class/interface would fit there. This means this new syntax would provide another "type barrier" that could help the engine or any type analyzer get a better understanding of the variables at hand.
> You mention the syntax looks weird to you. How would you design the > syntax if you want to cast the values instead of type checking them? >
I would abstain from trying to answer then. I now understand you had this different use case in mind, so I would totally understand that in turn, you'd be not interested in working towards Levi's proposal. On the other hand, I would so much like you'd be :) Cheers, Nicolas
  109557
April 7, 2020 17:24 claude.pache@gmail.com (Claude Pache)
> Le 7 avr. 2020 à 17:09, Enno Woortmann woortmann@web.de> a écrit : > > As the proposal explicitly aims at type casts > when working with data from a untyped source (eg. iterating over a CSV > file, XML without a XSD defining the types of the elements)
I feel that the RFC lacks a section named “Motivation”... That said, the larger question is: How many ad-hoc features do we want to add to array destructuring? For type-casting is one specific kind of transformation you may want to apply to your data. —Claude
  109561
April 8, 2020 09:51 enno.woortmann@web.de (Enno Woortmann)
Am 07.04.2020 um 19:24 schrieb Claude Pache:
> >> Le 7 avr. 2020 à 17:09, Enno Woortmann woortmann@web.de> a écrit : >> >> As the proposal explicitly aims at type casts >> when working with data from a untyped source (eg. iterating over a CSV >> file, XML without a XSD defining the types of the elements) > I feel that the RFC lacks a section named “Motivation”.... > > That said, the larger question is: How many ad-hoc features do we want to add to array destructuring? For type-casting is one specific kind of transformation you may want to apply to your data. > > —Claude
I've added a motivation section to the RFC describing the target of the proposal, added a discussion section describing the difference between the proposal and type checks while array destructuring and extended the patch section to include a description of the change. Enno