Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125030 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 167B31A00BD for ; Sat, 17 Aug 2024 20:28:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1723926593; bh=pPED9A09xcgfnBzEz0RFatqJzVXL0w8AKfY+Lv3iIXY=; h=Date:From:To:Cc:In-Reply-To:References:Subject:From; b=Dhx7zzBHX8FeNm4WDnT5xl5BoV4aBWGklMgN9xEj5/n0ldnhmgxdGobzYRXEc77E6 92/5aL51nTtgvFjrJNR/36jY/SXcn2BOaw/VStJou0dMCBUJ5nquVzX2pksiNO2Xk+ R3iUVaJwIOiXFyvIdtRwkK7jbZj2NYbitNM6vIJe3vGtQYSK3z142mp1+YCUUIt83X 0p0OGdTX+ow/AbMYkY52L5e2MWZL8jjV+4WPenzaNfcaJ25SmkNh64j3vTfFDqOf8e WqcrHosCNh1E15xoYfk1+qCtbj+tzbH8wIiQb7qn2dsStphVzNJcZm3jP1B1OtedIp XWhVgDS2BWZ7Q== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 8E3C0180059 for ; Sat, 17 Aug 2024 20:29: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=4.1 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DMARC_MISSING,HEADER_FROM_DIFFERENT_DOMAINS,HTML_MESSAGE, RCVD_IN_MSPIKE_H2,RCVD_IN_SBL_CSS,SPF_HELO_NONE,SPF_NONE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-yw1-f181.google.com (mail-yw1-f181.google.com [209.85.128.181]) (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 ; Sat, 17 Aug 2024 20:29:51 +0000 (UTC) Received: by mail-yw1-f181.google.com with SMTP id 00721157ae682-691c85525ebso28412627b3.0 for ; Sat, 17 Aug 2024 13:28:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=coggenterprises-com.20230601.gappssmtp.com; s=20230601; t=1723926483; x=1724531283; darn=lists.php.net; h=mime-version:subject:references:in-reply-to:message-id:cc:to:from :date:from:to:cc:subject:date:message-id:reply-to; bh=pPED9A09xcgfnBzEz0RFatqJzVXL0w8AKfY+Lv3iIXY=; b=xhBNvQ3Hhqpfj8s6In7Hxm89L9rR2UAmyp09RVplNGCJoig3/So5mE5IB7j0UuNvLc BI1VqO0VN4oU/bITU1C5+8BUtv/5r4+9Qc8UDzEkMcF5Vpke29GJwhQ3dt6v0XLgV+EK XZfi5RwBxnkLjVo5C09CSpQb5hGeiZ0jxjfOrK+2X8fVOGdQqYTXT33YFc5El880aqvJ 3sIxKX5986NCsivKTqMFzQJRiwTJEviChFSxgiR7WF3ghwJS/fV+BO88O9KMtxHrwDab CgZurUUkNZ16D+TZ0aa9jNIB6IsIMtUPa1C1fTSJewYFmsZ+pthHZdL/94GMWTtDa9Zm XZug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723926483; x=1724531283; h=mime-version:subject:references:in-reply-to:message-id:cc:to:from :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=pPED9A09xcgfnBzEz0RFatqJzVXL0w8AKfY+Lv3iIXY=; b=pD8/aKtL5wMQfSf2IhOcuLhty/xUIs2pwoGO4sYw5x9pKt+zeBEj/GsN9XIaQhsYOd 6PdpSk1zxjg2CYoDzrD8ArB31T590EuBPV60XBYq6CY67kX7GCK4hNHYIWI3iaRcnC/i kO5blgBUOM8yHuQ4SNCW35cQ3cJsszfb7I4pzabqZWJXrHUeWXZLUicchy0htjEGNaNo zlMABlrSmkrHYP47z5255sUNfItP6Tjmi4pPxUNPyuvj+/C21khef2YBp8yAz82rmnxO w/ZN5INtuCMPPFaZICUzwXfJiVN/ULYjcGuoyV8+0LK2qrTuz5Ym956A6dvJOWapTM6T 3woQ== X-Gm-Message-State: AOJu0YwXZEUJ04mmUrESI9iksILVkaSWBm4kVnqCdZ7TMatFq39W4Dk/ evVV9pZCtVl9gzI0rRYRSttvFJUdwcSb0oFLoHkvn/EVvrVUkVSGPvhAJqan+g+OyuzXS7VDPf9 r X-Google-Smtp-Source: AGHT+IGJnYhdPxFGWsbqNwee6AXj3XhvpnJQwUIMwjlTV7b2JyaWOsJVqGpxMt/55kbXGHmKwdANgg== X-Received: by 2002:a05:690c:45c8:b0:6b2:1b65:4c05 with SMTP id 00721157ae682-6b21b654e6bmr72474687b3.17.1723926483084; Sat, 17 Aug 2024 13:28:03 -0700 (PDT) Received: from Johns-MacBook-Pro-2.local ([207.213.210.67]) by smtp.gmail.com with ESMTPSA id 00721157ae682-6af9da160f9sm10935887b3.113.2024.08.17.13.28.01 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 17 Aug 2024 13:28:02 -0700 (PDT) Date: Sat, 17 Aug 2024 16:27:59 -0400 To: =?utf-8?Q?Rowan_Tommins_=5BIMSoP=5D?= Cc: "=?utf-8?Q?internals=40lists.php.net?=" Message-ID: <428B8247-59F1-4987-B9F7-0EE7F5F70717@getmailspring.com> In-Reply-To: <7082DD61-A257-4B3D-A49E-9CB32A560CDA@rwec.co.uk> References: <7082DD61-A257-4B3D-A49E-9CB32A560CDA@rwec.co.uk> Subject: Re: [PHP-DEV] String enums & __toString() X-Mailer: Mailspring Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="66c107cf_74b0dc51_17d67" From: john@coggeshall.org (John Coggeshall) --66c107cf_74b0dc51_17d67 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline > Just to show the range of viewpoints on this, I'd like to mention my opinion that Stringable is a horrible feature, with an implementation that's completely inconsistent with the rest of the language, and no clear semantic purpose. If your contract is "the input must be usable as a string", then the obvious type to require is "string". > I'm not saying my opinion is objectively right, or even held by a majority, I just wanted to provide a counterbalance of sorts. I don't think it's without purpose... what it should be for is to allow developers to make flexible APIs where they can type-hint string|Stringable and the user of the API doesn't have to worry about it. There are examples where complex data types (object, enums) can be intelligently and reasonably cast to a string for more than simply "output" purposes (e.g. print statements, log files and the like). Since we have __toString() it makes sense to me to have an interface I can type against to know that method is valid to call instead of hunting around for it with method_exists() or other some such thing. See below for an example I pulled off the top of my head with an ORM. > >function fooThatWantsString(string|Stringable|UnitEnum $bar) > I would have thought the more common use case would be the opposite: you want the function to be limited to a particular enum, but allow strings for backward compatibility, and have this: > function fooThatTakesAnOption(FooOptionEnum|string $opt) { > if ( is_string($opt) ) { > $opt = FooOptionEnum::from($opt); > } > ... > } I think there's pretty meaningful evidence based on the engagement in the PR (and the number of likes in that PR regarding specifically at least allowing __toString() to be implemented) that your version of the mock API above and my version don't have to be mutually exclusive things -- nor is one vs. the other better or worse from a generic perspective. A composer package you pull into your project won't know the Enum type you want to pass in, but it shouldn't be hard for you to pass in a string enum if the API requires a string. There are plenty of APIs out there in the wild right now buried in various composer packages that expect a string but a string-backed enum might make sense.... I haven't tested this directly but just as an offhand example consider something like Laravel's Eloquent ORM: $model->query()->where('enumColumn', '=', MyEnum::MYVALUE)->get(); It's possible that Laravel has already been smart enough to add the necessary logic to look for UnitEnum here and resolve that to MyEnum::MYVALUE->value , but my argument is that it shouldn't have to try that hard. Nor should I have to write MyEnum::MYVALUE->value in my query -- nor should any developer ever have to think/worry about that for a string enum with a string parameter. As a library developer when I write a method to be used by others in an entirely unknown context, if my method takes a string input then I should be able to hint string|Stringable and know I've given users of my library maximum flexibility with basically no real effort on my part (other than a redundant $foo = (string)$foo line. The fact this works 99% of the time (except, strangely, string-backed enums) is the inconsistency I want to repair here. As it seems to me there isn't a particularly strong argument for why we don't allow __toString() , would anyone have a strong objection to getting an RFC going to get this voted on? I didn't look closely at the original PR from the "auto implement __toString()" for string-backed enums, but I think this might literally be a one-liner just to enable enums to implement __toString() and the rest can be tossed. John --66c107cf_74b0dc51_17d67 Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline
Just to show the range of viewpoints on this, I= 'd like to mention my opinion that Stringable is a horrible feature, with= an implementation that's completely inconsistent with the rest of the la= nguage, and no clear semantic purpose. If your contract is =22the input m= ust be usable as a string=22, then the obvious type to require is =22stri= ng=22.

I'm not saying my opinion is objectively right, or e= ven held by a majority, I just wanted to provide a counterbalance of sort= s.


I don't think it's without p= urpose... what it should  be for is to allow developers to = make flexible APIs where they can type-hint string=7CStringable  and the user of the API doesn't have to worry about it.
There are examples where complex data types (object, enums) can be= intelligently and reasonably cast to a string for more than simply =22ou= tput=22 purposes (e.g. print statements, log files and the like). Since w= e have =5F=5FtoString()  it makes sense to me to have a= n interface I can type against to know that method is valid to call inste= ad of hunting around for it with method=5Fexists()  or = other some such thing. See below for an example I pulled off the top of m= y head with an ORM.

>function fooThatWantsString(= string=7CStringable=7CUnitEnum =24bar)
I would have thought the more common use case would be the= opposite: you want the function to be limited to a particular enum, but = allow strings for backward compatibility, and have this:
function fooThatTakesAnOption(=46ooOptio= nEnum=7Cstring =24opt) =7B
if ( is=5Fstring(=24op= t) ) =7B
=24opt =3D =46ooOptionEnum::from(=24opt)= ;
=7D
...
=7D
I think there's pretty meaningful evide= nce based on the engagement in the PR (and the number of likes in that PR= regarding specifically at least allowing =5F=5FtoString()&n= bsp; to be implemented) that your version of the mock API above and my ve= rsion don't have to be mutually exclusive things -- nor is one vs. the ot= her better or worse from a generic perspective. A composer package you pu= ll into your project won't know the Enum type you want to pass in, but it= shouldn't be hard for you to pass in a string enum if the API requires a= string.  There are plenty of APIs out there in the wild right now b= uried in various composer packages that expect a string = ; but a string-backed enum might make sense.... I haven't tested this dir= ectly but just as an offhand example consider something like Laravel's El= oquent ORM:

=24model->query()->where('enumColum= n', '=3D', MyEnum::MYVALUE)->get(); 

It's po= ssible that Laravel has already been smart enough to add the necessary lo= gic to look for UnitEnum  here and resolve that to MyEnum::MYVALUE->value , but my argument is that it shou= ldn't have to try that hard. Nor should I have to write MyEnum::MYV= ALUE->value  in my query -- nor should any developer ever = have to think/worry about that for a string enum with a string parameter.= As a library developer when I write a method to be used by others in an = entirely unknown context, if my method takes a string input then I should= be able to hint string=7CStringable  and know I've giv= en users of my library maximum flexibility with basically no real effort = on my part (other than a redundant =24foo =3D (string)=24foo=   line. The fact this works 99% of the time (except, strangely, stri= ng-backed enums) is the inconsistency I want to repair here.

As it seems to me there isn't a particularly strong argument for why we= don't allow =5F=5FtoString() , would anyone have a str= ong objection to getting an R=46C going to get this voted on=3F I didn't = look closely at the original PR from the =22auto implement =5F=5FtoString= ()=22 for string-backed enums, but I think this might literally be a one-= liner just to enable enums to implement =5F=5FtoString()&nbs= p; and the rest can be tossed.

John
--66c107cf_74b0dc51_17d67--