# [RFC] Nullable Return Type Declaration

- Thread: https://externals.io/message/92303
- Original archive: https://news-web.php.net/php.internals/92303
- Started by Tom Worster on 2016-04-14T15:39:00+00:00
- Messages: 28
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/92303.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #92303 — Tom Worster — 2016-04-14T15:39:00+00:00

URL: https://externals.io/message/92303#92303

I would like to introduce for discussion an RFC proposing and arguing for
Nullable Return Type Declaration in 7.1 and deferring for now more general
relaxations of 7.0 type as proposed in Levi's two RFCs.

  https://wiki.php.net/rfc/nullable_returns

If anyone would like to collaborate on the RFC, I have a repo you may fork:
https://gist.github.com/tom--/e95a10fbe4d34f8a72c9 (although guthub's
formatting isn't lovely). I'm looking for help with implementation.

Tom

---

## #92305 — Levi Morrison — 2016-04-14T16:35:44+00:00

URL: https://externals.io/message/92303#92305 · In reply to: #92303

> I would like to introduce for discussion an RFC proposing and arguing for
> Nullable Return Type Declaration in 7.1 and deferring for now more general
> relaxations of 7.0 type as proposed in Levi's two RFCs.
>
>   https://wiki.php.net/rfc/nullable_returns
>
> If anyone would like to collaborate on the RFC, I have a repo you may fork:
> https://gist.github.com/tom--/e95a10fbe4d34f8a72c9 (although guthub's
> formatting isn't lovely). I'm looking for help with implementation.
>
> Tom
>
>
>

I can appreciate that you want only the restricted union with null.
However, I do not see the point of disallowing it for parameter types
while allowing it for return types:

    function setLeft(Node $n = null) {
        $this->left = $n;
        $this->updateHeight();
    }

Why disallow the explicit union with null here instead of the default
parameter which does not exactly capture the desired semantics?
Calling `$node->setLeft()` is just odd, almost as if it was a mistake.
I would much prefer `$node->setLeft(null)` here. Basically, if we have
a feature for return types that exactly matches the semantics that we
occasionally want for the parameter types why forbid it?

Additionally, on occasion I'll see functions like this:

    function foo(Bar $b = null, $not_optional_param);

Why not allow nullable types on parameters to avoid that wonkiness
caused by default values of null?

    function foo(Bar | Null $b, $not_optional_param);

This is much better.

---

## #92307 — Fleshgrinder — 2016-04-14T17:33:23+00:00

URL: https://externals.io/message/92303#92307 · In reply to: #92305

> 
> > […]
> 
> I can appreciate that you want only the restricted union with null.
> However, I do not see the point of disallowing it for parameter types
> while allowing it for return types:
> 
>     function setLeft(Node $n = null) {
>         $this->left = $n;
>         $this->updateHeight();
>     }
> 
> Why disallow the explicit union with null here instead of the default
> parameter which does not exactly capture the desired semantics?
> Calling `$node->setLeft()` is just odd, almost as if it was a mistake.
> I would much prefer `$node->setLeft(null)` here. Basically, if we have
> a feature for return types that exactly matches the semantics that we
> occasionally want for the parameter types why forbid it?
> 
> Additionally, on occasion I'll see functions like this:
> 
>     function foo(Bar $b = null, $not_optional_param);
> 
> Why not allow nullable types on parameters to avoid that wonkiness
> caused by default values of null?
> 
>     function foo(Bar | Null $b, $not_optional_param);
> 
> This is much better.
> 

My guess is that this RFC only wants to get it for return because it
might be an easier vote?

I do not like the fact that only the long version of union types is
supported and prefer the question mark approach as a short hand. Can
this RFC be either extended to include that as well or removed so it
does not get in the way of the other two RFCs?

-- 
Richard "Fleshgrinder" Fussenegger

---

## #92318 — Tom Worster — 2016-04-14T21:19:51+00:00

URL: https://externals.io/message/92303#92318 · In reply to: #92305

On 4/14/16, 12:35 PM, "Levi Morrison" <morrison.levi@gmail.com on behalf
of levim@php.net> wrote:

>I can appreciate that you want only the restricted union with null.
>However, I do not see the point of disallowing it for parameter types
>while allowing it for return types:
>
>    function setLeft(Node $n = null) {
>        $this->left = $n;
>        $this->updateHeight();
>    }
>
>Why disallow the explicit union with null here instead of the default
>parameter which does not exactly capture the desired semantics?
>Calling `$node->setLeft()` is just odd, almost as if it was a mistake.
>I would much prefer `$node->setLeft(null)` here. Basically, if we have
>a feature for return types that exactly matches the semantics that we
>occasionally want for the parameter types why forbid it?

I agree that `$node->setLeft()` is weird but I find `$node->setLeft(null)`
still a bit weird. Perhaps something like `$node->resetLeft()` would work?
Was that the idea?


>Additionally, on occasion I'll see functions like this:
>
>    function foo(Bar $b = null, $not_optional_param);

The only thing we can know for sure from this is that the programmer
urgently needs reeducation :)


>Why not allow nullable types on parameters to avoid that wonkiness
>caused by default values of null?
>
>    function foo(Bar | Null $b, $not_optional_param);
>
>This is much better.

Yes but still a code smell to me. I'd need to know more about the
programmer's intent for `foo(null, "value")`. It might be better to swap
order, or change the method name, or add another method... Who knows? Need
to take each case individually.

This kind of asking questions about intent in code review is good for code
quality. That's why I like how PHP doesn't allow this. It encourages the
question asking. Every case is different, of course, so you can surely
find counter examples. But on balance I'd say it's better to disallow it.


Does this help you understand my preference? I think the restriction
encourages a healthy discipline.

Otoh, I think nullable return is a pressing need.

Tom

---

## #92319 — Tom Worster — 2016-04-14T21:46:22+00:00

URL: https://externals.io/message/92303#92319 · In reply to: #92307

>
> > […]
>My guess is that this RFC only wants to get it for return because it
>might be an easier vote?

Hi Richard,

That wasn't really my intent. I tried to set out my argument contra
nullable param type in the RFC and elaborate it in my answer to Levi,
which I hope you read.

My attitude to programming reversed since 10 years ago. I used to prefer
to have all the options and be allowed to exercise my judgement. But over
those years I had to remain responsible for most of my code, which led to
a blinding conversion. Now I am so acutely aware of how likely I am to
write bugs that I more often than not want the language to get smaller.

My sense is that nullable params won't turn out to be one of the good
parts, in the Crockford sense. Something|null return, otoh, is so
established as a convention I can't imagine getting away from it.


I'm aware that some people won't understand my point of view. If that's
still the case, ask again and I'll try a different answer.

Tom

---

## #92320 — Levi Morrison — 2016-04-14T21:46:56+00:00

URL: https://externals.io/message/92303#92320 · In reply to: #92318

> > […]
>
> Yes but still a code smell to me. I'd need to know more about the
> programmer's intent for `foo(null, "value")`. It might be better to swap
> order, or change the method name, or add another method... Who knows? Need
> to take each case individually.

Having a separate method instead of `foo(null, "value")` makes it
difficult to use for the result of a function. Assume `bar()` returns
`Bar | Null`; this would no longer work if they were separated:

    foo(bar(), "value")

Functions are often composed so if something is the output of one
function it will likely be the input to another. Thus if returning
optionally null values is important to you so should optionally null
parameters.

---

## #92323 — Tom Worster — 2016-04-15T00:33:41+00:00

URL: https://externals.io/message/92303#92323 · In reply to: #92320

On 4/14/16, 5:46 PM, "Levi Morrison" <morrison.levi@gmail.com on behalf of
levim@php.net> wrote:

>Having a separate method instead of `foo(null, "value")` makes it
>difficult to use for the result of a function.

I suspect that might be a good thing:) I don't know for sure but the
possibility exists.


>Assume `bar()` returns
>`Bar | Null`; this would no longer work if they were separated:
>
>    foo(bar(), "value")
>
>Functions are often composed so if something is the output of one
>function it will likely be the input to another. Thus if returning
>optionally null values is important to you so should optionally null
>parameters.

This was a chin-scratcher for me. On one hand, I see what you mean. On the
other I couldn't think of an example from my experience (which I admit is
very narrow -- I live a sheltered life) of such a bar() that I would feed
straight foo().

The semantic convention for Something or null return, as I see it, is when
bar() returns null, it is saying "I got nothing". What kind of foo() does
the same thing to nothing at all as it does to a Something object? This is
where I got stuck.

Say I was doing the composition instead via chaining.
Something::bar()->foo("value") is nonsense if bar() could return null.
This suggests to me that the other composition might not be wise.

*Either* bar() should not be returning Something or null (maybe it should
instead return some other type that can represent all the possible
returns) *or* we shouldn't try to compose like this and should test for
the Somethingness of bar()'s return before apply ->foo("value") or foo(…,
"value") to it. Or maybe this API needs an even more fundamental redesign.

So, from my perspective, this might be an example of the limitation
nudging us to think harder about the design.

Tom

---

## #92324 — Larry Garfield — 2016-04-15T00:48:06+00:00

URL: https://externals.io/message/92303#92324 · In reply to: #92323

> On 4/14/16, 5:46 PM, "Levi Morrison" <morrison.levi@gmail.com on behalf of
> levim@php.net> wrote:
>
> > […]
> I suspect that might be a good thing:) I don't know for sure but the
> possibility exists.
>
>
> > […]
> This was a chin-scratcher for me. On one hand, I see what you mean. On the
> other I couldn't think of an example from my experience (which I admit is
> very narrow -- I live a sheltered life) of such a bar() that I would feed
> straight foo().
>
> The semantic convention for Something or null return, as I see it, is when
> bar() returns null, it is saying "I got nothing". What kind of foo() does
> the same thing to nothing at all as it does to a Something object? This is
> where I got stuck.
>
> Say I was doing the composition instead via chaining.
> Something::bar()->foo("value") is nonsense if bar() could return null.
> This suggests to me that the other composition might not be wise.
>
> *Either* bar() should not be returning Something or null (maybe it should
> instead return some other type that can represent all the possible
> returns) *or* we shouldn't try to compose like this and should test for
> the Somethingness of bar()'s return before apply ->foo("value") or foo(…,
> "value") to it. Or maybe this API needs an even more fundamental redesign.
>
> So, from my perspective, this might be an example of the limitation
> nudging us to think harder about the design.
>
> Tom

I have to agree with Tom.  if foo(bar(), $val) could die because bar() 
may return NULL, that's not an indication that foo() needs to accept 
NULL.  It's a sign that bar() should not be returning it in the first 
place. :-)

I am highly, highly sceptical about nullable parameters or returns, and 
frankly would rather they were not included in the language.  By nature 
they undermine type safety.  At best, they indicate to all callers 
"*every* time you call this function, you MUST put `is_null()` around it 
or your program may fail randomly."  While that's better to know 
explicitly than not (which is the case for any untyped return, aka any 
PHP code pre-7.0), it would be better still to, well, not have to worry 
about that billion dollar mistake[1] cropping up in my code.

In a sense, if we really must allow for value-or-null (which I consider 
a code smell in the 98% case) I'd prefer if it was ONLY available via 
union types: That is, Something|null.  That's longer and clumsier to 
type, and harder to read.  Which it should be. (Static casts in C++ have 
a fugly syntax, which has been defended by the language designers on the 
grounds that static casts are fugly, so the syntax for them should be as 
well to remind you to stop doing it. There is a fair amount of validity 
to that argument on affordance grounds, at least within C++.)  Using an 
easy short hand notation for something that is inherently a code smell 
when you're already typing your code only serves to encourage something 
we should be training people out of in the first place.

Unless you like having `is_null()` scattered around your code in a hundred 
places...  I don't. :-)

[1] https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions

--Larry Garfield

---

## #92325 — Levi Morrison — 2016-04-15T04:22:37+00:00

URL: https://externals.io/message/92303#92325 · In reply to: #92324

> 
> > […]
>
>
> I have to agree with Tom.  if foo(bar(), $val) could die because bar() may
> return NULL, that's not an indication that foo() needs to accept NULL.  It's
> a sign that bar() should not be returning it in the first place. :-)
>
> I am highly, highly sceptical about nullable parameters or returns, and
> frankly would rather they were not included in the language.  By nature they
> undermine type safety.  At best, they indicate to all callers "*every* time
> you call this function, you MUST put `is_null()` around it or your program may
> fail randomly."  While that's better to know explicitly than not (which is
> the case for any untyped return, aka any PHP code pre-7.0), it would be
> better still to, well, not have to worry about that billion dollar
> mistake[1] cropping up in my code.
>
> In a sense, if we really must allow for value-or-null (which I consider a
> code smell in the 98% case) I'd prefer if it was ONLY available via union
> types: That is, Something|null.  That's longer and clumsier to type, and
> harder to read.  Which it should be. (Static casts in C++ have a fugly
> syntax, which has been defended by the language designers on the grounds
> that static casts are fugly, so the syntax for them should be as well to
> remind you to stop doing it. There is a fair amount of validity to that
> argument on affordance grounds, at least within C++.)  Using an easy short
> hand notation for something that is inherently a code smell when you're
> already typing your code only serves to encourage something we should be
> training people out of in the first place.
>
> Unless you like having `is_null()` scattered around your code in a hundred
> places...  I don't. :-)
>
> [1] https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions
>
> --Larry Garfield

My point is that `foo(bar(), $val)` won't die because bar may return
null. Bar is expected to return null sometimes.

For example, let's consider an administrator page where they look up
user information based on an identifier. The routine we'll use will
have this signature:

    function get_user(string $id): User | Null;

It is possible for an identifier to not exist and this is not an error
(database successfully returned no results). If there is no User data
to display then it makes sense for the UI to present that differently.
Thus it makes sense to pass that User | Null onto the code that will
present it:

    $user_data = get_user($id);
    // ...
    $user_html = render_user_data($user_data);

In fact this is a common operation that is encountered in many code
bases (I think every single one I've ever looked at).

---

## #92330 — Lester Caine — 2016-04-15T09:55:05+00:00

URL: https://externals.io/message/92303#92330 · In reply to: #92325

> > […]
You have lots of code instead in exception handling away fro the normal
program flow?

> > […]
> My point is that `foo(bar(), $val)` won't die because bar may return
> null. Bar is expected to return null sometimes.
> 
> For example, let's consider an administrator page where they look up
> user information based on an identifier. The routine we'll use will
> have this signature:
> 
>     function get_user(string $id): User | Null;
> 
> It is possible for an identifier to not exist and this is not an error
> (database successfully returned no results). If there is no User data
> to display then it makes sense for the UI to present that differently.
> Thus it makes sense to pass that User | Null onto the code that will
> present it:
> 
>     $user_data = get_user($id);
>     // ...
>     $user_html = render_user_data($user_data);
> 
> In fact this is a common operation that is encountered in many code
> bases (I think every single one I've ever looked at).

That is a possible database type scenario, although on all of my
systems, the 'guest' user will be accessed as a default which gives the
default user data set.

The main thing I see with the 'null is not needed' argument is that it
instead relies on 'exception handling'? If I am scanning a file or
reading a record set, at some point I hit the end, and in ALL my code
base I get a null object rather than result object, be that reading and
processing a file or a database feed. We have already had the complaints
about file handling should give an exception when there is nothing left,
but MY workflow keeps everything in line ... when the last record is
processed we see the 'null' and progress to the next step in the
process. There is nothing here that needs to involve throwing exceptions
which may well be coded out of line with the main program flow and make
debugging more difficult?

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #92336 — Larry Garfield — 2016-04-15T15:50:29+00:00

URL: https://externals.io/message/92303#92336 · In reply to: #92330

> 
> > […]
> You have lots of code instead in exception handling away fro the normal
> program flow?
>
> > […]
> That is a possible database type scenario, although on all of my
> systems, the 'guest' user will be accessed as a default which gives the
> default user data set.
>
> The main thing I see with the 'null is not needed' argument is that it
> instead relies on 'exception handling'? If I am scanning a file or
> reading a record set, at some point I hit the end, and in ALL my code
> base I get a null object rather than result object, be that reading and
> processing a file or a database feed. We have already had the complaints
> about file handling should give an exception when there is nothing left,
> but MY workflow keeps everything in line ... when the last record is
> processed we see the 'null' and progress to the next step in the
> process. There is nothing here that needs to involve throwing exceptions
> which may well be coded out of line with the main program flow and make
> debugging more difficult?

That there are a few small cases where PHP's current design makes `NULL` a 
reasonable sentinel value (custom iterators, `fread()` as you mention, 
etc.) does not mean that in most cases, returning ValueObject|Null is 
rude and abusive to users of your API.  Yes, end-of-file is not an 
exceptional case so should not throw an exception.  I completely agree 
there.  But "user not found" I'd argue is.  (Or rather, if it's not an 
exceptional case your data model is kinda broken to begin with, because 
why are you asking for a missing user?)  Or you're better off having an 
"empty" value instead, such as an anonymous user object.  That's still 
type safe.

I'm not suggesting that we purge `NULL` from the language.  That's 
impractical/impossible. I'm suggesting we shouldn't soften the type 
system added in 7.0, which discourages its use in most cases, as it 
should be.

-- 
--Larry Garfield

---

## #92338 — Levi Morrison — 2016-04-15T16:10:37+00:00

URL: https://externals.io/message/92303#92338 · In reply to: #92336

> I'm not suggesting that we purge `NULL` from the language.  That's
> impractical/impossible. I'm suggesting we shouldn't soften the type system
> added in 7.0, which discourages its use in most cases, as it should be.

It is a common misconception I've heard several times now that union
types is weakening or softening the type system. I want to reiterate
that it is already possible to use multiple types. It is already done
in the wild. It is done all over our standard library. The union types
RFC just allows you to encode the specific types to be passed or
returned. In other words it is aiming to make using the dynamic types
of PHP safer by allowing you to explicitly write out the options.

The Nullable Return Types RFC is basically arguing that the only
useful union of types is `T | Null` and only for return types. I've
already stated a few of my concerns with that belief and have not been
convinced by the rebuttles to change my mind.

Also, to specifically address a concern Larry had earlier about
nullable types in general:

> I am highly, highly sceptical about nullable parameters or returns, and frankly would rather they were not included in the language.

Just to clarify: we already have nullable parameters because of a
default of null. It's already in the language and people have asked
many times for this functionality to be expanded to include return
types. I should have kept a master list every time someone contacted
me on github, email, twitter, etc about this so I could easily list
them all as references in the relevant RFCs for demand for the
feature.

---

## #92339 — Levi Morrison — 2016-04-15T16:16:18+00:00

URL: https://externals.io/message/92303#92339 · In reply to: #92338

> convinced by the rebuttles to change my mind.

s/rebuttles/rebuttals/

I thought about just letting it go like many typos/spelling mistakes
but it seemed too funny to not correct

---

## #92342 — Tom Worster — 2016-04-15T16:59:38+00:00

URL: https://externals.io/message/92303#92342 · In reply to: #92324

> I am highly, highly sceptical about nullable parameters or returns, and
> frankly would rather they were not included in the language.  By nature
> they undermine type safety.  At best, they indicate to all callers
> "*every* time you call this function, you MUST put `is_null()` around it
> or your program may fail randomly."

Yes.


> While that's better to know
> explicitly than not (which is the case for any untyped return, aka any
> PHP code pre-7.0), it would be better still to, well, not have to worry
> about that billion dollar mistake[1] cropping up in my code.

I agree.

To be clear, I do not intend the RFC to encourage nullable return or 
suggest that it's a fine thing to use. But given where we are, it's hard 
to imagine how to extirpate it.

When we started using PHP 7.0 type, initially when authoring new models 
(and using Yii2), it immediately became clear that we lacked two things: 
this and void returns. We're getting the latter in 7.1. It would be very 
nice if we could have both.

I'm a practical PHP user, with a generally conservative attitude to the 
language, often unmoved by proposals add a feature because some other 
more fashionable language has it (I call it language envy, to borrow 
from Freud). And while PHP 7.0 is good, I'd rather have Something|null 
in the return declaration than just in the docblock. That's all.


> In a sense, if we really must allow for value-or-null (which I consider
> a code smell in the 98% case) I'd prefer if it was ONLY available via
> union types: That is, Something|null.  That's longer and clumsier to
> type, and harder to read.  Which it should be. (Static casts in C++ have
> a fugly syntax, which has been defended by the language designers on the
> grounds that static casts are fugly, so the syntax for them should be as
> well to remind you to stop doing it. There is a fair amount of validity
> to that argument on affordance grounds, at least within C++.)  Using an
> easy short hand notation for something that is inherently a code smell
> when you're already typing your code only serves to encourage something
> we should be training people out of in the first place.

With regard to syntax, I prefer the long form `Something|null`. That 
seems very clear to me. The proposed short-hand ? syntax always makes me 
think of what I hate most about regex.

Tom

---

## #92343 — Tom Worster — 2016-04-15T17:12:02+00:00

URL: https://externals.io/message/92303#92343 · In reply to: #92325

> My point is that `foo(bar(), $val)` won't die because bar may return
> null. Bar is expected to return null sometimes.
>
> For example, let's consider an administrator page where they look up
> user information based on an identifier. The routine we'll use will
> have this signature:
>
>      function get_user(string $id): User | Null;
>
> It is possible for an identifier to not exist and this is not an error
> (database successfully returned no results). If there is no User data
> to display then it makes sense for the UI to present that differently.
> Thus it makes sense to pass that User | Null onto the code that will
> present it:
>
>      $user_data = get_user($id);
>      // ...
>      $user_html = render_user_data($user_data);
>
> In fact this is a common operation that is encountered in many code
> bases (I think every single one I've ever looked at).

This is a good example.

My opinion is that *because* get_user() can return null (a red flag) I 
prefer to see explicit handing of the null case before doing anything else.

If I would end up with `render_user_data(get_user($id))` I would 
consider it fair to not hint the param because I didn't earn it. I 
invented the faux docblock tag @sorry for this kind of thing.

Tom

---

## #92374 — Fleshgrinder — 2016-04-17T07:19:02+00:00

URL: https://externals.io/message/92303#92374 · In reply to: #92336

> That there are a few small cases where PHP's current design makes `NULL` a
> reasonable sentinel value (custom iterators, `fread()` as you mention,
> etc.) does not mean that in most cases, returning ValueObject|Null is
> rude and abusive to users of your API.  Yes, end-of-file is not an
> exceptional case so should not throw an exception.  I completely agree
> there.  But "user not found" I'd argue is.  (Or rather, if it's not an
> exceptional case your data model is kinda broken to begin with, because
> why are you asking for a missing user?)  Or you're better off having an
> "empty" value instead, such as an anonymous user object.  That's still
> type safe.
> 

I disagree here. Your user example with the anonymous user object works
if I am asking for e.g. the creation of a session but it is a very
different situation if I would be asking for a user profile. The fact
that a user might have deleted her account is not an exceptional case,
is is to be expected and should be handled accordingly. How is up to the
caller. Otherwise any `array_key_exists($k, $a)` should result in an
exception or some default value according to your logic here.

I completely agree that `NULL` is not the best type and others languages
have other means to solve the issue but absolutely every language has
some way to indicate the absence of a meaningful value. PHP has `NULL`
like many others and that is fine. The problem is not that we have
`NULL` the problem is that it is just too often not checked if it can be
`NULL`.

Rust and many functional language solve this with an Option or Maybe
that requires creation, allocation, and userland checks for every return
and the compilers fail if you do not unpack it.

Ceylon solves this with union types as we are discussing it right now,
however, the difference to other languages is that the compiler will
fail if you are not checking the return value and bugs are avoided in
this way. This is something that we could adopt.

http://ceylon-lang.org/documentation/faq/language-design/#optional_types

The absence of something must be modellable.

    class ConstraintViolation {

        private ?Throwable $cause;

        private string $message;

        public function __construct(
            string $message,
            ?Throwable $cause = null
        ) {
            $this->message = $message;
            $this->cause = $cause;
        }

        public function getCause(): ?Throwable {
            return $this->cause;
        }

        public function hasCause(): bool {
            return isset($this->cause);
        }

        // ...

    }

An example of a class I was just working on. How could, would, or should
one model this without `NULL`? Throwing an exception? It is not
exceptional for such an object and expected that there is no cause
available. It is up to the caller how she wants to take care of this.

    /** @var ConstraintViolation $violation */
    if ($violation->hasCause()) {
        // Handle cause ...
    }

    $cause = $violation->getCause();
    if (isset($cause)) {
        // Handle cause ...
    }

    // Or maybe we just want it stringified?
    // Works nicely with `NULL`. :)
    echo $violation->getCause();

Throwing exceptions everywhere for non exceptional cases is a code smell
too and I see that ever to often in current open source code. Especially
throwing extremely low-level exception everywhere for real errors from
which one should not recover (e.g. `InvalidArgumentException`) because
they indicate developer mistakes and only add a lot of checks in
production for no reason. That being said, the above could be rewritten to.

    class ConstraintViolation {

        public function getCause(): Throwable {}

        public function hasCause(): bool {}

    }

This would mean that PHP emits an Error if someone calls `getCause` and
there is no cause and there would be only one way to check: `hasCause`.
This is a valid design decision since it minimizes the amount of
possibilities to work with the class and avoids `NULL` altogether.
However, the caller code did not really become less verbose; as was
already illustrated in the above examples. Plus, the ability to directly
use the `__toString`ability paired with `NULL` in a string is gone.

Everything always has pros and cons and I do not think that there is one
answer to all of these questions. Different languages handle this
problem differently. PHP has `NULL` and we should keep it this way. To
minimize bugs resulting from unchecked `NULL` usage a compiler feature
could be implemented that warns a developer in such cases. We already
have it for uncatched exceptions (although IDEs are currently not
telling one about that; Eclipse does in Java though).

-- 
Richard "Fleshgrinder" Fussenegger

---

## #92393 — Larry Garfield — 2016-04-18T03:56:39+00:00

URL: https://externals.io/message/92303#92393 · In reply to: #92374

> Everything always has pros and cons and I do not think that there is one
> answer to all of these questions. Different languages handle this
> problem differently. PHP has `NULL` and we should keep it this way. To
> minimize bugs resulting from unchecked `NULL` usage a compiler feature
> could be implemented that warns a developer in such cases. We already
> have it for uncatched exceptions (although IDEs are currently not
> telling one about that; Eclipse does in Java though).

Rather than debate the relative merits of Null as a concept, since I 
think all agree removing Null from the language is not even a thing, 
what do you think of my recommendation to NOT have the ? shorthand for 
"or null" on types, but keep the |null for union types?  That is, if you 
want to return Foo or null, you have to use the long-hand version:

function foo($a) : Foo|null

That

1) Allows for explicit or-null behavior.
2) Doesn't make it quite so easy, which hopefully discourages (but does 
not prohibit) its usage.
3) Neatly avoids the ?Foo / Foo? question entirely.

I think that's a win-win arrangement.

--Larry Garfield

---

## #92395 — Marcio Almada — 2016-04-18T05:22:49+00:00

URL: https://externals.io/message/92303#92395 · In reply to: #92393

Hi!

2016-04-17 23:56 GMT-04:00 Larry Garfield <larry@garfieldtech.com>:

> 
>
> > […]
>
> Rather than debate the relative merits of Null as a concept, since I think
> all agree removing Null from the language is not even a thing, what do you
> think of my recommendation to NOT have the ? shorthand for "or null" on
> types, but keep the |null for union types?  That is, if you want to return
> Foo or null, you have to use the long-hand version:
>
> function foo($a) : Foo|null
>
> That
>
> 1) Allows for explicit or-null behavior.
> 2) Doesn't make it quite so easy, which hopefully discourages (but does
> not prohibit) its usage.
> 3) Neatly avoids the ?Foo / Foo? question entirely.
>
> I think that's a win-win arrangement.
>
>
> --Larry Garfield
>
> --
> 
> 
>
>
I can agree with that.

Language design wise, if you have no way to forecast how language features
independently proposed are going to interact then it's a good idea to have
a converging strategy. Fortunately, this seems to be happening almost
spontaneously towards union types representation, as in the "multiple
catch" RFC (https://wiki.php.net/rfc/multiple-catch) now in voting phase.

Even if we decide not to commit to a full union types implementation now,
the design process will be much easier in the future if we decide to use
Foo|null instead of Foo? or ?Foo and we will not end up with 2 or 3 ways
alternative to declare the same thing.

Cheers,
Márcio

---

## #92398 — Lester Caine — 2016-04-18T08:00:05+00:00

URL: https://externals.io/message/92303#92398 · In reply to: #92393

> 2) Doesn't make it quite so easy, which hopefully discourages (but does
> not prohibit) its usage.

This implies that using 'null' is wrong ... and is a slippery slope to
then 'disabling' null where some people think it should be removed. If
PHP development is making these sort of decisions it should be clear
that is the intention, not just 'hopefully discourages' things that some
people have no appreciation of the usefulness of!

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #92416 — Larry Garfield — 2016-04-18T16:57:52+00:00

URL: https://externals.io/message/92303#92416 · In reply to: #92398

> 
> > […]
> This implies that using 'null' is wrong ... and is a slippery slope to
> then 'disabling' null where some people think it should be removed. If
> PHP development is making these sort of decisions it should be clear
> that is the intention, not just 'hopefully discourages' things that some
> people have no appreciation of the usefulness of!

I am not sure what you're implying by "some people have no appreciation 
of the usefulness of"... I am well aware of NULL's use cases.  I am also 
well aware that the general zeitgeist in the language development 
community is that they're dangerous; the designer of the first language 
to have them calls them a "billion dollar mistake", many languages 
actively avoid having `NULL` in favor of something deliberately more 
structured.  NULLs are a very common cause of avoidable fatal errors in 
many languages (including PHP). NULLs are rude to users of your API, as 
it balloons the error handling code they need to deal with.

I am on record and will continue to be on record that null is *usually* 
wrong.  I consider that position entirely justified, as does the 
academic CS community.  I am also now on record suggesting that we use 
union types to allow type-or-null returns/parameters, which you're 
welcome to quote me on. :-)

Are you comfortable with the compromise position I've proposed?

-- 
--Larry Garfield

---

## #92418 — Lester Caine — 2016-04-18T18:22:44+00:00

URL: https://externals.io/message/92303#92418 · In reply to: #92416

> 
> > […]
> 
> I am not sure what you're implying by "some people have no appreciation
> of the usefulness of"... I am well aware of NULL's use cases.  I am also
> well aware that the general zeitgeist in the language development
> community is that they're dangerous; the designer of the first language
> to have them calls them a "billion dollar mistake", many languages
> actively avoid having `NULL` in favor of something deliberately more
> structured.  NULLs are a very common cause of avoidable fatal errors in
> many languages (including PHP). NULLs are rude to users of your API, as
> it balloons the error handling code they need to deal with.

With a properly structured code flow, `NULL` is the ONLY logical solution
to elements of the data that do not physically exist. And in my book
that includes where we run out of whole records when running that work
flow. PHP is a scripting language that works well with these flows of
data, and `NULL` is certainly NOT a mistake IN that workflow. So in order
to remove `NULL` you need to come up with a reason why the SQL standard is
wrong and produce a new specification that can replace it ... and
'exception' is just another mistake that needs eliminating where that is
not appropriate when a simple `NULL` currently does the job more than
adequately.

> I am on record and will continue to be on record that null is *usually*
> wrong.  I consider that position entirely justified, as does the
> academic CS community.  I am also now on record suggesting that we use
> union types to allow type-or-null returns/parameters, which you're
> welcome to quote me on. :-)
> 
> Are you comfortable with the compromise position I've proposed?

As long as I can simply wipe any use of ANY of this type code overload
from my libraries and keep it out of ANY of the code PHP functionality
it so that the database extensions still handle 'null' exactly as it is
designed to work then that is all I need. I don't see ANY need to add
internally the very code you are complaining we need to add externally
removing the simple flexibility that provides. So I don't see the need
for any compromise ... just scrap the whole waste of time adding
unnecessary code and documenting why you think PHP is currently so
broken ...

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #92419 — Stanislav Malyshev — 2016-04-18T18:24:01+00:00

URL: https://externals.io/message/92303#92419 · In reply to: #92416

Hi!

> I am not sure what you're implying by "some people have no appreciation
> of the usefulness of"... I am well aware of NULL's use cases.  I am also
> well aware that the general zeitgeist in the language development
> community is that they're dangerous; the designer of the first language

I would like to note in general that following the latest fashion in
academic development is not always a good idea for PHP. It's fine when
you experiment with academic languages, but when you have language that
a) focused on simplicity and low entrance barrier and b) is in
production use by millions and has 20 years of existing practices,
libraries and habits, we have to be a bit more wary, I think. I am *not*
saying we should not improve, or ignore academic developments, I am
saying that we should be careful with not jumping to the idea-of-the-day
bandwagon too fast, before it is clear it is good and necessary for PHP.

As an example, I don't see how exactly eliminating null would be good
for PHP, or doing *anything* with null for that matter.

> to have them calls them a "billion dollar mistake", many languages
> actively avoid having `NULL` in favor of something deliberately more
> structured.  NULLs are a very common cause of avoidable fatal errors in
> many languages (including PHP). NULLs are rude to users of your API, as
> it balloons the error handling code they need to deal with.

I think this description is misleading in a way. Nulls are immediate
causes of many errors, technically, in a meaning that "if I find null
where I expected to have DB connection, I get an error" - but this is
only a technical cause. The *real* cause is the failure to check whether
your attempt to connect to the database succeeded, or that you have
proper DB configuration, or such, and null is just a symptom of that
error - and that error is not automagically fixed by having some other
object instead of null. You have to actually design and write code for
it, there's no replacement for it.

So declaring null "cause of all evils" is ignoring the real causes and
blaming immediate technical cause instead, and it would not be helpful.
It is true that for some languages with more complex type systems it is
possible to largely get rid of nulls by using those complex types and
ensure type system controls for all checks at least to be present (note
that doesn't guarantee proper function either, since no type system can
ensure you handle the case of missing DB connection properly, it just
can ensure you have a branch for it). But that requires much more
complex and involved type system that PHP has - or, in my opinion,
should have.

> I am on record and will continue to be on record that null is *usually*
> wrong.  I consider that position entirely justified, as does the
> academic CS community.  I am also now on record suggesting that we use
> union types to allow type-or-null returns/parameters, which you're
> welcome to quote me on. :-)

I think this position is way too narrow, simplistic and detached from
real language use towards abstract academic purity. There are tons of
causes where using null is completely fine and exactly what is needed. I
also think union types is a great and unnecessary complication of the
language and in order to do them properly we'd need lots of facilities
PHP does not have (like type pattern matching and static compilation)
and I am not sure it should have - ones looking for Haskell know where
to find it.
And there are a lot of cases where failing on null is exactly what one
needs - if it doesn't work, just fail and let somebody come and check
what is going on. If your database died, your DB-bound code is not going
to fix it. With or without nulls - it has to just fail and wait for
somebody to fix it. There's no need to overcomplicate that.
-- 
Stas Malyshev
smalyshev@gmail.com

---

## #92423 — Fleshgrinder — 2016-04-18T18:39:39+00:00

URL: https://externals.io/message/92303#92423 · In reply to: #92419

> > […]
> 
> I think this description is misleading in a way. Nulls are immediate
> causes of many errors, technically, in a meaning that "if I find null
> where I expected to have DB connection, I get an error" - but this is
> only a technical cause. The *real* cause is the failure to check whether
> your attempt to connect to the database succeeded, or that you have
> proper DB configuration, or such, and null is just a symptom of that
> error - and that error is not automagically fixed by having some other
> object instead of null. You have to actually design and write code for
> it, there's no replacement for it.
> 
> So declaring null "cause of all evils" is ignoring the real causes and
> blaming immediate technical cause instead, and it would not be helpful.
> It is true that for some languages with more complex type systems it is
> possible to largely get rid of nulls by using those complex types and
> ensure type system controls for all checks at least to be present (note
> that doesn't guarantee proper function either, since no type system can
> ensure you handle the case of missing DB connection properly, it just
> can ensure you have a branch for it). But that requires much more
> complex and involved type system that PHP has - or, in my opinion,
> should have.
> 

I agree with Stanislav here. *NULL* is not evil per se and just because
some functional languages get some attention right now does not mean
that they solved the biggest mistake in CS history. On the contrary,
they just invented another way of handling it by introducing new types
that require more book keeping and by refusing to compile if they
encounter a place where proper handling is missing.

As I wrote earlier, we could introduce such a feature into the language.
However, static code analyzers can already provide this functionality.
People just need to use them.

TL;DR *NULL* is just fine if used correctly and we cannot make sure that
people use it correctly.

-- 
Richard "Fleshgrinder" Fussenegger

---

## #92422 — Lester Caine — 2016-04-18T18:39:44+00:00

URL: https://externals.io/message/92303#92422 · In reply to: #92419

> If your database died, your DB-bound code is not going
> to fix it. With or without nulls - it has to just fail and wait for
> somebody to fix it. There's no need to overcomplicate that.

If the DB read failed due to the connection being lost, then that is a
case for an exception and out of flow events? The 'null' would be
returned when an active connection has no data to return because a
search or query has produced none. Larry would probably be looking to
check the 'no_of_recs' to see if there were any results but then you
still have to read the result if there is one ... overcomplicating the
simple solution?

( ADOdb check the connection is still valid as part of the query prep
and run and changes the work flow if required )

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #92425 — Fleshgrinder — 2016-04-18T19:08:21+00:00

URL: https://externals.io/message/92303#92425 · In reply to: #92395

> 2016-04-17 23:56 GMT-04:00 Larry Garfield <larry@garfieldtech.com>:
> > […]
> I can agree with that.
> 
> Language design wise, if you have no way to forecast how language features
> independently proposed are going to interact then it's a good idea to have
> a converging strategy. Fortunately, this seems to be happening almost
> spontaneously towards union types representation, as in the "multiple
> catch" RFC (https://wiki.php.net/rfc/multiple-catch) now in voting phase.
> 
> Even if we decide not to commit to a full union types implementation now,
> the design process will be much easier in the future if we decide to use
> Foo|null instead of Foo? or ?Foo and we will not end up with 2 or 3 ways
> alternative to declare the same thing.
> 

I actually do not see a problem with the shorthand notation. I am
usually an extreme opponent of duplicated or aliased functionality
because it increases the cognitive load to keep all this crap in your
mind. This is however a useful shortcut and shortcuts are good things in
terms of usability if done write. Think of <Ctrl> + <c> vs. right click
> copy (or any other example of useful keyboard shortcuts). The usage of
*null* as an union type is the most common case compared to all the
others that are truly rare in comparison.

There are other shortcuts in PHP that are perfect:

- Iterator vs. Generator: they can achieve the exact same thing but
  slightly different and a generator can almost always be used to
  replace an iterator with less code, even if the special effects of
  it are irrelevant.
- `$x = $x + $y` vs. `$x += $y`: we have many of those and that is just
  fine as it is.
- `$x = $x + 1` vs. `++$x` vs. `$x++`: ditto
- `<?php echo 'Hello World'` vs. `<?= 'Hello World'`: ditto
- if-else vs. `?:`: ditto
- public function vs. function in interfaces: I think the sole reason
  why people include the public access modifier is because no PHP IDE
  automatically adds the public while implementing the methods.
- while vs. do-while vs. for vs. foreach: It is possible to achieve
  everything with a while loop.
- ...

Plain and simple, shorthand functionality is not always and with no
exceptions bad. On the contrary, it can make your life a whole lot
easier (I think this is best illustrated by the three loop constructs
which are all super usable).

That being said, I can also live with leaving out the shorthand
notation. Simply because we currently have to write it out fully in
PhpDoc anyways (not that this ever discouraged anyone to misuse *null*
everywhere, even if they properly documented everything).

Last but not least, 3) is already answered for me. It must be prefix to
allow later extensions like generics. Plus HHVM already has it as a
prefix which is another good argument in my book.

-- 
Richard "Fleshgrinder" Fussenegger

---

Next page: https://externals.io/message/92303.md?page=2
