Newsgroups: php.internals
Path: news.php.net
Xref: news.php.net php.internals:122718
X-Original-To: internals@lists.php.net
Delivered-To: internals@lists.php.net
Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5])
by qa.php.net (Postfix) with ESMTPS id 3DF601A009D
for ; Thu, 21 Mar 2024 20:36:35 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail;
t=1711053416; bh=6L32gY25+Ycsc5OC3pNLLZjUjqG95X/F8YUFovzwbF0=;
h=Date:Subject:To:References:From:In-Reply-To:From;
b=DNt+h9tyh1/OmpN4V3b5JSPjOTUpSa4g17zp8x4aOFvW+QRm6XqhAthgD0jYUwOFb
SuueaFyEjFkHPVoj4T72B0maDAhXk7xsEQoCBuA0jgPEP1TD155j6Mdto69X+gzlHO
ZNonAQkBTVuyEJtWFfTYCFPmM9Gbgas8Oq0wQNY2LTlAqbY6jfd772uem6d11qieZe
hugiGvCjmrZ57gOU7TdcZZVZBNljJD45s+JIB9Gz/N0/Djq8e69JY1+DX87D7cxJCK
Tucz9Pf4GRkDLzsUb27LbOEF16A0c5CLaz/4Otg6dQLBXlQKYTRUKXmzC+MdVOL8Qq
DXa0OFDnLtG5A==
Received: from php-smtp4.php.net (localhost [127.0.0.1])
by php-smtp4.php.net (Postfix) with ESMTP id 44ED0180549
for ; Thu, 21 Mar 2024 20:36:52 +0000 (UTC)
X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net
X-Spam-Level:
X-Spam-Status: No, score=-0.1 required=5.0 tests=BAYES_50,DKIM_SIGNED,
DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE,
RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE
autolearn=no autolearn_force=no version=4.0.0
X-Spam-Virus: No
X-Envelope-From:
Received: from fhigh8-smtp.messagingengine.com (fhigh8-smtp.messagingengine.com [103.168.172.159])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256)
(No client certificate requested)
by php-smtp4.php.net (Postfix) with ESMTPS
for ; Thu, 21 Mar 2024 20:36:50 +0000 (UTC)
Received: from compute6.internal (compute6.nyi.internal [10.202.2.47])
by mailfhigh.nyi.internal (Postfix) with ESMTP id D9754114005D
for ; Thu, 21 Mar 2024 16:36:27 -0400 (EDT)
Received: from mailfrontend2 ([10.202.2.163])
by compute6.internal (MEProxy); Thu, 21 Mar 2024 16:36:27 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rwec.co.uk; h=cc
:content-type:content-type:date:date:from:from:in-reply-to
:in-reply-to:message-id:mime-version:references:reply-to:subject
:subject:to:to; s=fm2; t=1711053387; x=1711139787; bh=7dVuTAuqDG
v1/yWWVxkzWPjesRUDYRD4/EQvzIWO9e4=; b=ZRnDudb+P+ILv0sGNmUAEWHsI1
Dm810iZhqvZCLDoIXWGtJ2vI4UL51/ITNmlcxvisBG+P8viGGAZsuRPEm6o5yKoI
34UTHoOavr7uXwLJW0e/iHTqJYDR4MItVPTq6EJOve/wpCUZal96ySZJ7CdbzyeO
tRs+iHTEvOr7r6+vfKHlW0ok4No8OPIFsg23AlO1f2KPvsy7q636C1nRlBrC4nTz
msCvugNIsgdrHq8nCgt/Aodv9pQ9+4LvLYDpZ/bE5Qp65vVGHkttoHvBbXPbXnPP
aopPbhU/kv0s1PlXmLpGni2Hklo5yc6W+S6OxuLmn1WO04JLhl195s1YZXNg==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
messagingengine.com; h=cc:content-type:content-type:date:date
:feedback-id:feedback-id:from:from:in-reply-to:in-reply-to
:message-id:mime-version:references:reply-to:subject:subject:to
:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=
fm2; t=1711053387; x=1711139787; bh=7dVuTAuqDGv1/yWWVxkzWPjesRUD
YRD4/EQvzIWO9e4=; b=D4hz0DTklaPbJch0jtI+YoOv0ZgSsBZONopHWDb4Ry9T
6JR7frUttLPVpwz5xiM2t459D8DmUDEPgh/E+6SxQMoYyANxcv2vl9ST1+0NmD8C
IViXIR6kMvj6y3XpCly/CtntsbGlxMUw6J4VkqjSjwpnBArHC9Y5Vn5q9FgCJinB
sRKC0RXB1Wm/r4LErecbVWJXUYWIVMsX1Tiv0L+8sBiQgUBJNAGhykAsayLkUJqn
QGmrtpW+ylmdUOo6GbyYNNQKrP2wwsNINTqbEc65oc2JAhVO5SYb7PuZnToM/wCi
b2DHo7Nypoe/o8lS68AfxZQyJ8bae/buRIEi2sHm7g==
X-ME-Sender:
X-ME-Received:
X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrleejgdejkecutefuodetggdotefrodftvf
curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu
uegrihhlohhuthemuceftddtnecunecujfgurheptgfkffggfgfuvfhfhfgjsegrtderre
dtvdejnecuhfhrohhmpedftfhofigrnhcuvfhomhhmihhnshculgfkoffuohfrngdfuceo
ihhmshhophdrphhhphesrhifvggtrdgtohdruhhkqeenucggtffrrghtthgvrhhnpeehte
elieeigfeuudeiueeiffdvveehudeufeekjeeugffffedtiedtgeettdelteenucevlhhu
shhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehimhhsohhprdhphh
hpsehrfigvtgdrtghordhukh
X-ME-Proxy:
Feedback-ID: id5114917:Fastmail
Received: by mail.messagingengine.com (Postfix) with ESMTPA for
; Thu, 21 Mar 2024 16:36:27 -0400 (EDT)
Content-Type: multipart/alternative;
boundary="------------s0G8oWXfn8281z09TBLHBJWn"
Message-ID:
Date: Thu, 21 Mar 2024 20:36:24 +0000
Precedence: bulk
list-help:
list-post:
List-Id: internals.lists.php.net
MIME-Version: 1.0
User-Agent: Mozilla Thunderbird
Subject: Re: [PHP-DEV] Proposal: AS assertions
To: internals@lists.php.net
References:
<3F78A125-1946-42E2-A4F5-A2B282BE2107@rwec.co.uk>
<2d7ec203-6e80-445c-94f4-d29ef58743b1@rwec.co.uk>
<40d5c22f-5c06-403d-afc2-84c202277a29@rwec.co.uk>
Content-Language: en-GB
In-Reply-To:
From: imsop.php@rwec.co.uk ("Rowan Tommins [IMSoP]")
This is a multi-part message in MIME format.
--------------s0G8oWXfn8281z09TBLHBJWn
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
On 21/03/2024 19:03, Robert Landers wrote:
> I suppose we are taking this from different viewpoints, yours appears
> to be more of a philosophical one, whereas mine is more of a practical
> one.
My main concern is consistency; which is partly philosophical, but does
have practical impact - the same syntax meaning the same thing in
different contexts leads to less user confusion and fewer bugs.
But I also think there are real use cases for "error on anything other
than either Foo or null" separate from "give me a null for anything
other than Foo".
> $x = $a as null;
>
> (or any other value, such as true|false) appears to have no practical
> purpose in this particular case.
There's plenty of possible pieces of code that have no practical
purpose, but that on its own isn't a good reason to make them do
something different.
"null" as a standalone type (rather than part of a union) is pretty much
always pointless, and was forbidden until PHP 8.2. It's now allowed,
partly because there are scenarios involving inheritance where it does
actually make sense (e.g. narrowing a return type from Foo|null to
null); and probably also because it's easier to allow it than forbid it.
That's not really what we're talking about anyway, though; we're talking
about nullable types, or null in a union type, which are much more
frequently used.
> Further, reading "$x =
> $a as null", as a native English speaker, appears to be the same as
> "$x = null".
Well, that's a potential problem with the choice of syntax: "$x = $a as
int" could easily be mistaken for "cast $a as int", rather than "assert
that $a is int".
If you spell out "assert that $a is null", or "assert that $a is
int|null", it becomes very surprising for 'hello' to do anything other
than fail the assertion.
> As I mentioned in the beginning, I see this mostly being used when
> dealing with mixed types from built-in/library functions, where you
> have no idea what the actual type is, but when you write the code, you
> have a reasonable expectation of a set of types and you want to throw
> if it is unexpected.
My argument is that you might have a set of expected types which
includes null, *and* want to throw for other, unexpected, values. If
"|null" is special-cased to mean "default to null", there's no way to do
that.
> Right now, the best way to do that is to simply
> set a function signature and pass the mixed type to the function to
> have the engine do it for you
And if you do that, then a value of 'hello' passed to a parameter of
type int|null, will throw a TypeError, not give you a null.
As I illustrated in my last e-mail, you can even (since PHP 8.2) have a
parameter of type null, and get a TypeError for any other value. That
may not be useful, but it's entirely logical.
> It makes more sense, from a practical programming
> point-of-view, to simply return the value given if none of the types
> match.
This perhaps is a key part of our difference: when I see
"int|bool|null", I don't see any "value given", just three built-in
types: int, which has a range of values from PHP_INT_MIN to PHP_INT_MAX;
bool, which has two possible values "true" and "false"; and null, which
has a single possible value "null".
So there are 2**64 + 2 + 1 possible values that meet the constraint, and
nothing to specify that one of those is my preferred default if given
something unexpected.
Regards,
--
Rowan Tommins
[IMSoP]
--------------s0G8oWXfn8281z09TBLHBJWn
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 7bit
On 21/03/2024 19:03, Robert Landers
wrote:
I suppose we are taking this from different viewpoints, yours appears
to be more of a philosophical one, whereas mine is more of a practical
one.
My main concern is consistency; which is partly philosophical,
but does have practical impact - the same syntax meaning the same
thing in different contexts leads to less user confusion and fewer
bugs.
But I also think there are real use cases for "error on anything
other than either Foo or null" separate from "give me a null for
anything other than Foo".
$x = $a as null;
(or any other value, such as true|false) appears to have no practical
purpose in this particular case.
There's plenty of possible pieces of code that have no practical
purpose, but that on its own isn't a good reason to make them do
something different.
"null" as a standalone type (rather than part of a union) is
pretty much always pointless, and was forbidden until PHP 8.2.
It's now allowed, partly because there are scenarios involving
inheritance where it does actually make sense (e.g. narrowing a
return type from Foo|null to null); and probably also because it's
easier to allow it than forbid it.
That's not really what we're talking about anyway, though; we're
talking about nullable types, or null in a union type, which are
much more frequently used.
Further, reading "$x =
$a as null", as a native English speaker, appears to be the same as
"$x = null".
Well, that's a potential problem with the choice of syntax: "$x =
$a as int" could easily be mistaken for "cast $a as int", rather
than "assert that $a is int".
If you spell out "assert that $a is null", or "assert that $a is
int|null", it becomes very surprising for 'hello' to do anything
other than fail the assertion.
As I mentioned in the beginning, I see this mostly being used when
dealing with mixed types from built-in/library functions, where you
have no idea what the actual type is, but when you write the code, you
have a reasonable expectation of a set of types and you want to throw
if it is unexpected.
My argument is that you might have a set of expected types which
includes null, *and* want to throw for other, unexpected, values.
If "|null" is special-cased to mean "default to null", there's no
way to do that.
Right now, the best way to do that is to simply
set a function signature and pass the mixed type to the function to
have the engine do it for you
And if you do that, then a value of 'hello' passed to a parameter
of type int|null, will throw a TypeError, not give you a null.
As I illustrated in my last e-mail, you can even (since PHP 8.2)
have a parameter of type null, and get a TypeError for any other
value. That may not be useful, but it's entirely logical.
It makes more sense, from a practical programming
point-of-view, to simply return the value given if none of the types
match.
This perhaps is a key part of our difference: when I see
"int|bool|null", I don't see any "value given", just three
built-in types: int, which has a range of values from PHP_INT_MIN
to PHP_INT_MAX; bool, which has two possible values "true" and
"false"; and null, which has a single possible value "null".
So there are 2**64 + 2 + 1 possible values that meet the
constraint, and nothing to specify that one of those is my
preferred default if given something unexpected.
Regards,
--
Rowan Tommins
[IMSoP]
--------------s0G8oWXfn8281z09TBLHBJWn--