On Thu, Apr 14, 2016 at 6:48 PM, Larry Garfield <la...@garfieldtech.com> wrote:
> On 04/14/2016 07:33 PM, Tom Worster wrote:
>>
>> On 4/14/16, 5:46 PM, "Levi Morrison" <morrison.l...@gmail.com on behalf of
>> le...@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
>
>
> 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).

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to