Re: [RFC][Discussion] Objects can be declared falsifiable

From: Date: Wed, 15 Jul 2020 19:16:36 +0000
Subject: Re: [RFC][Discussion] Objects can be declared falsifiable
References: 1 2 3 4  Groups: php.internals 
Request: Send a blank email to internals+get-111030@lists.php.net to get a copy of this message
On Wed, Jul 15, 2020 at 10:43 AM Marco Pivetta <ocramius@gmail.com> wrote: > > Hey Larry, > > On Wed, Jul 15, 2020 at 5:32 PM Larry Garfield <larry@garfieldtech.com> > wrote: > > > 1) return null, which is a non-type, and thus you need to make the return > > type ?User or User|null, which means the caller *must* always check it's > > nullness. > > > > Allowing an object to falsify itself is a 4th, more type-safe option. It > > lets you return an object that both fails a boolean check (like null) but > > also has default values in it for the base case. A user object likely > > wouldn't use that, but a value object like an Address very well could. > > > > Until we can support for-reals monads (which would require enums and > > generics to do properly; the former is possible the latter is very hard), > > it's the best option we have for more type-safe returns. > > > > Adding a "falsey" state for code that expects `is_object($foo) === (bool) > $foo` seems to be a massive BC break to me, and reduces type safety of > boolean operators (and checks) by expanding the object type and > all > operators and expressions that can interact with it. > > In general, ?T is very much equivalent to Maybe > T > > Where instance Monad Maybe is implemented in type-safe langs as > (quoting > > https://en.wikibooks.org/wiki/Haskell/Understanding_monads/Maybe - I > omitted return because the lifting bit is not really used in > PHP): > > ```hs > (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b > (>>=) m g = case m of > Nothing -> Nothing > Just x -> g x > ``` > > ?T is very much the same in PHP (pseudo-code, since nullability > is not > represented the same way in Haskell): > > ```hs > (>>=) :: ?T -> (T -> Maybe T2) -> ?T2 > (>>=) m g = case m of > null -> null > x -> g x > ``` > > Let's not confuse Java nullable issues with PHP nullability, which is quite > healthy :-) > > I see adding a "falsey" evaluation to something that has been assumed (for > a looooooong time) as universally "truthy" is a very major issue. > > We need code examples where this is a clear advantage over previous logic: > as it stands, I don't see why I would ever prefer (bool) > $object over > $object !== null, or > $object->valid() (which I believe to be an > anti-pattern) In my opinion, it seems reasonable to be able to swap out an array for an object that implements Traversable, ArrayAccess, Countable, etc in common situations. However, this is not possible in at least two common situations: if ($array) { // ... foreach ($array as $key => $value) { // ... } // ... } if (!empty($array)) { // ... foreach ($array as $key => $value) { // ... } // ... } You could swap !empty() for count > 0 , but I can imagine objects where we can know that we aren't empty without knowing the full count. For example, a database result using a cursor or something; we'll know on the first response if we have even 1 result, but we won't know the final count ahead of time. Of course, there are cases where we can't do this swap because of array_* specific functions anyway, but my point is rather that from a language perspective it seems like a reasonable goal to pursue.

« previous php.internals (#111030) next »