On 10/11/2023 11:29, Craig Francis wrote:
strict_types=1 enables strict type checking
While it's not exactly false, this statement is misleading in a really
important way. That's not your fault, it's just that "strict_types" is,
in hindsight, a really terrible name.
If I had a time machine (and a lot of patience to wade back into the
debate), I would advocate naming the modes as follows:
* declare(scalar_params=coerce)
* declare(scalar_params=assert)
This would have made several things clearer.
1) Although asserting a type is in a sense "more strict" than coercing
it, the "coerce" mode actually rejects more inputs than an explicit cast
would.
2) The settings were never intended as a change to "the type system";
they don't change the behaviour of anything other than certain arguments
passed into functions.
3) They only change the behaviour of a small number of new type keywords
added to the language at that time: "int", "float", "string", and
"bool". It governs the way these types interact with each other, and not
anything about any other type.
Most relevantly for this discussion, that list does not include "null".
At the time, the language already had type declarations on parameters
for "array" and class/interface names, and those already disallowed null
values. Note that this isn't a given, as many languages treat "null" as
a valid value for any object type; recent developments in C# suggest PHP
got it right for once by disallowing that from the start.
I never understood why NULL was considered a complex value like a
class/callable/array, when it's more like a simple bool/int/float/string
I think you are misreading the quoted passage. It's not saying that null
is similar to the complex types, it's saying that the handling of null
values should be consistent between parameters marked with those
keywords, and parameters marked with the new keywords "int", "float",
"string", and "bool".
In actual fact, we could probably have narrowed the scope of the setting
even further, because there are two cases that most people care about:
* coercing int to and from float (which is allowed in both modes anyway)
* coercing string to and from int or float (e.g. getting an ID or a
price from a URL or API response)
So maybe we could have had:
* declare(numeric_params=coerce)
* declare(numeric_params=assert)
That would make it even clearer that the question of whether trim(null)
is a meaningful operation is a completely separate debate than anything
that the declare() covers.
Wherever it is used, "null" is a confusing and often controversial
concept. In different contexts, it is used for different things, and has
different ideal behaviours. It's a whole debate on its own, and bringing
in other types of coercion just confuses the conversation.
Regards,
--
Rowan Tommins
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php