Re: "TryX" idom for Enumerations
| From: | Ben Ramsey | Date: | Mon, 11 Jan 2021 20:27:54 +0000 |
| Subject: | Re: "TryX" idom for Enumerations | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-112843@lists.php.net to get a copy of this message | ||
> On Jan 10, 2021, at 20:09, Larry Garfield <larry@garfieldtech.com> wrote:
>
> On Sun, Jan 10, 2021, at 4:40 PM, Mark Randall wrote:
>> On 10/01/2021 21:27, Larry Garfield wrote:
>>> The "a method that begins with try is nullable, so watch out" idiom is
>>> present in C# and Rust, but to my knowledge has never existed in PHP. That doesn't make it
>>> bad; it actually combines quite well with the null coalesce operator to allow for default values,
>>> making a valueOrDefault() method unnecessary.
>>
>> I get the advantages of returning null, in particular WRT the null
>> coalescing operator.
>>
>> However, when I see 'try' I instictively think 'exceptions' i.e.
>> try/catch when the reality is it's the opposite and it would be the
>> non-try functions which throw.
>>
>> But it makes sense for those to throw.
>
> That was my initial response as well, and my main concern. To a PHP developer, the terminology
> seems backwards. But it's not like we haven't adopted idioms and syntax from other
> languages before.
>
>> However if you will permit me a tangent...
>>
>> There is an alternative, of sorts. Something I tried investigating when
>> I first started looking into PHP-SRC, but lack the skill and knowledge
>> to implement myself.
>>
>> A shorthand try / catch of something like the form:
>>
>> <tryname>(<expr, ExceptionType => ResultExpr, ...)
>>
>> At which point tryFrom becomes:
>>
>> $order = attempt(SortOrder::tryFrom($input), ValueError => SortOrder::Asc);
>>
>> Which would be the equivilent of:
>>
>> function attempt(callable $try, array $map): mixed {
>> try {
>> return $try();
>> }
>> catch ($e) {
>> foreach ($map as $class => $expr) {
>> if (is_subclass_of($e, $class, true)) {
>> return $expr();
>> }
>> }
>>
>> throw $e;
>> }
>> }
>>
>> Or just allow a mixed value to be given without a mapping for catching
>> Throwable.
>>
>> If added as a language construct, except each expr and $try itself would
>> be parsed closure at language construct level to avoid needing to fn()
>> them all e.g.
>>
>> $foo = attempt(fn() => SortOrder::tryFrom($input), [ ValueError => fn()
>> => null ]);
>>
>> Just a thought, perhaps a cleaner solution to a wider problem. A try /
>> catch combined with a match.
>>
>> It avoids the need for two methods, just provide the one that throws and
>> use shorthand to assign a null if it throws.
>>
>> Mark Randall
>
> The main issue I see is that creating an exception is quite expensive. (Or it was the last
> time I bothered benchmarking it, which admittedly has been a while.) So even if you had some built
> in "catch and match" pseudo-function, you're still paying the cost of the exception,
> which is not cheap.
>
> catch-and-match is an interesting idiom, but as you say it's somewhat tangential to the
> question at hand.
>
> --Larry Garfield
I have no problem introducing this idiom (or similar). In fact, I welcome it.
In userland, the same concept is often achieved with methods like
Attachment: [application/pgp-signature] Message signed with OpenPGP signature.asc
fromOrNull(), and as
Mark points out, the word “try” makes me think the method should throw an exception if it fails.
I’m not advocating for xOrNull(), though, since I think that smacks of Hungarian
notation, but maybe we can come up with something that is a more PHP-ish name. ;-)
“There are two hard things in computer science: cache invalidation, naming things, and off-by-one
errors.” --Phil Karlton
Cheers,
Ben
Attachment: [application/pgp-signature] Message signed with OpenPGP signature.asc