> Hello Larry and Ilija,
> 
> I maintain a production PHP application that rejects a model’s JSON reply 
> unless every field is present and of an exact type. Pattern matching is the 
> language feature that would replace those checks. Two outcomes in the current 
> draft would make that replacement accept replies we currently reject. Both 
> are constraints on the rules you already wrote, not requests for new syntax.
> 
> The RFC’s array-pattern equivalents use array_key_exists() before comparing 
> the value. A missing key therefore fails the pattern. The implementation note 
> on https://github.com/php/php-src/pull/20574 says the draft reads a missing 
> element as null, so this is true:
> 
>     ['a' => 42] is ['b' => null]
> 
> Please keep the RFC text. For this parser, a missing key and an explicit null 
> are different successful results, and a value of any other type is a failure:
> 
>     function partQuote(array $p): ?array {
>         if (!is_string($p['part'] ?? null)) {
>             return null;
>         }
>         if (array_key_exists('quote', $p) && $p['quote'] !== null && 
> !is_string($p['quote'])) {
>             return null;
>         }
>         $out = ['part' => $p['part']];
>         if (array_key_exists('quote', $p)) {
>             $out['quote'] = $p['quote']; // null is kept; the key was present
>         }
>         return $out;
>     }
> 
>     partQuote(['part' => 'A']);                    // ['part' => 'A']
>     partQuote(['part' => 'A', 'quote' => null]);   // ['part' => 'A', 'quote' 
> => null]
>     partQuote(['part' => 'A', 'quote' => 1]);      // null
> 
> If ['quote' => null] matched a missing quote, the first two calls would 
> become the same pattern and the stored shape would be wrong.
> 
> The same parser requires a real int for a score-like field, in 0..100 
> inclusive. is_int() is the type check; the range is applied only after that. 
> These all fail:
> 
>     ['strength' => '80']
>     ['strength' => 80.0]
>     ['strength' => 101]
>     ['relevant' => 1]       // is_bool(), same rule: no coercion
>     ['relevant' => 'true']
> 
> and ['strength' => 80] with ['relevant' => true] passes. An int pattern 
> therefore has to reject a numeric string and a float. A range pattern such as 
> >=0 & <=100 has to do the same when it is standing in for that field; "80" 
> and 80.0 are inside the numeric range and are still the wrong type.
> 
> I am not asking for a change to the feature set. The written array patterns 
> already say array_key_exists(), and an int pattern that follows is_int() is 
> what this code can adopt.
> 
> Kevin Lopez

Reply via email to