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

Reply via email to