On Fri, 22 Mar 2024, at 12:58, Robert Landers wrote: > >> $optionalExpiryDateTime = $expiry as ?DateTimeInterface else new >> DateTimeImmutable($expiry); > I'm not sure I can grok what this does... > > $optionalExpiryDateTime = ($expiry === null || $expiry instanceof > DateTimeInterface) ? $expiry : new DateTimeImmutable($expiry)
Trying to write it as a one-liner is going to make for ugly code - that's why I'd love to have a new way to write it! But yes, that's the right logic. With the "is" operator from the Pattern Matching draft, it would be: $optionalExpiryDateTime = ($expiry is ?DateTimeInterface) ? $expiry : new DateTimeImmutable($expiry); But with a clearer assertion that the variable will end up with the right type in all cases: $optionalExpiryDateTime = $expiry as ?DateTimeInterface else some_other_function($expiry); assert($optionalExpiryDateTime is ?DateTimeInterface); // cannot fail, already asserted by the "as" > Maybe? What would be the usefulness of this in real life code? I've > never written anything like it in my life. I already explained the scenario: the parameter is optional, so you want to preserve nulls; but if it *is* present, you want to make sure it's the correct type before proceeding. Another example: // some library function that only supports strings and nulls function bar(?string $name) { if ( $string !== null ) ... else ... } // a function you're writing that supports various alternative formats function foo(string|Stringable|int|null $name = null) { // we don't want to do anything special with nulls here, just pass them along // but we do want to convert other types to string, so that bar() doesn't reject them bar($name as ?string else (string)$name); } To put it another way, it's no different from any other union type: at some point, you will probably want to handle the different types separately, but at this point in the program, either type is fine. In this case, the types that are fine are DateTimeInterface and null; or in the example above, string and null. > $optionalExpiryDateTime = $expiry == null ? $expiry : $expiry as > DateTimeInterface ?? new DateTimeImmutable($expiry as string ?? "now") If you think that's "readable" then we might as well end the conversation here. If that was presented to me in a code review, I'd probably just write "WTF?!" I have no idea looking at that what type I can assume for $optionalExpiryDateTime after that line, which was surely the whole point of using "as" in the first place? Regards, -- Rowan Tommins [IMSoP]