On 17 September 2015 01:50:31 BST, Robert Williams <rewilli...@thesba.com> 
wrote:
>On Sep 16, 2015, at 14:09, Rowan Collins <rowan.coll...@gmail.com>
>wrote:
>More common than different variables in different circumstances is the
>missing variable. Consider the user who’s setting up an instance of an
>application that uses a config file with bare variables — very easy to
>forget something, or type the name wrong, or whatever. Or the
>programmer writing a plugin for a poorly documented application who
>wants to be sure the runtime environment of the plugin is what’s
>expected. Really, a lot of the same situations where one might need to
>check the existence of an array element or object property, except that
>the item to be checked happens to be a plain old variable.

OK, so basically here you're after a louder version of the existing Notice, as 
a debugging aid. I can see that.


>> - you/they have used null as a value which needs to be positively
>asserted, not taken as the default state, so that isset() does not meet
>your needs
>
>Well, it’s not so important that null represents a non-default state,
>as that it represents any state. Often, null could just signal that a
>default should be used, but with an existence check, the programmer can
>be confidant that something/someone explicitly chose that option.

In my mind, if it has to be positively asserted, it's not a default. It might 
mean "automatic behaviour" when eventually processed, but that's not what I 
meant by "default state" in this context.


>Consider that you’ve refactored a delete function to add support for
>non-permanent deletion. You’ve done this by adding an optional
>parameter:
>
>function DeleteFile($file, $permanentlyDelete = null) {}
>
>If $permanentlyDelete is null, the default action specified in a config
>is used. The problem is, when the param is null, there’s no way for the
>function to know for sure what the programmer of the caller intended.


This is a really nice example, thanks. People do overuse optional parameters, 
and this is a good example. Interestingly, and I realise this wasn't the point 
of your example, there's no way I know of to detect if a parameter was omitted 
from your function call rather than passed an explicit null; exists() wouldn't 
help, because the local variable will be created to hold the parameter even if 
it's not passed in.


>It’s the same thing with exists() on a variable: it gives us extra
>intelligence about *why* a variable is null, whether it’s because of an
>actual decision somewhere or because of an error or oversight. 

OK, I'll buy that. I'm not saying I'm convinced over all, but it at least shows 
a reasonable use for it.


>If the variables are injected before your code runs, it’s too late. At
>that point, if you try to set a magic sentinel value, you’re just
>overwriting the real value if there is one. It would work, however, if
>you can pre-initialize before the injection


Yes, that's what I was getting at.


>I’m not really a fan of this pattern, though. If there’s going to be a
>magic value to indicate that no better value was set, null is the ideal
>choice:
>
>Here, we’ve used null exactly as intended. Unfortunately, this breaks
>if null already has meaning, even if it's just "go with a default”.


As you say, the "missing value" meaning is the generally accepted use of null. 
So the problem only comes about because you've reused null for some extra 
meaning, such as "automatic selection". Once again, it's not default behaviour 
if it has to be opted into.

People definitely do this - I know I have - but it's often a problem later. For 
instance what if, instead of just "automatic", we decide to allow "minimise" 
and "maximise" modes, alongside the explicit setting? We don't have a second 
built-in terminal value like null, so we need some new representation. If we'd 
stuck with a second variable, or a string in place of an integer, we'd have 
room for this expansion and still be able to use null for it's more  
traditional role of "missing value".


>And, of course, it also throws the annoying undefined error that we’re
>trying to avoid :-).


No it doesn't - you've defined the variable before the include, so there's 
nothing to warn about.


>It’s cleaner and shorter, but it also lets us again use null as
>intended


You mean it frees you to use null for something unrelated?


>> I've not found evidence that any other language treats variables in
>the proposed way, so it really doesn't feel like an "oversight" to me,
>but a request for a new and quite unusual feature.
>
>In JavaScript, there’s this:
>
>if (typeof never_heard_of_me === 'undefined') {
>       //uh-oh
>}


I mentioned that in a previous message. AFAICS, that behaves much like a PHP 
null - "var foo" exists but is undefined, if passed as a parameter, that 
parameter is undefined, etc. It certainly doesn't match the proposed 
functionality of exists().


>My fear is that the people who don't understand why isset() does what
>it does will think it's the answer to some imaginary problem, and end
>up more confused than ever when their code breaks.
>
>Haven’t we already arrived here with isset() confusion? ;-)


Yes, and I don't want to make it worse by implying that the people who said 
isset() was broken were right.


>to something like this:
>
>"Determine if a variable exists in the current scope and is not NULL.
>To test only whether a variable exists, use exists().


This is exactly what I *don't* want. The vast majority of the time, anyone 
reaching for exists() should be using isset(), not vice versa. During this 
discussion, we've come upon a couple of very specific edge cases where it might 
be acceptable to distinguish non-existence from null, but they are definitely 
not every day occurrences.



>> If the function had been proposed as a debugging aid, maybe filed
>under Reflection or debug_variable_is_initialised, I might have more
>sympathy, but that's not how it's been presented.
>
>Again, I don’t see this as something that directly controls business
>logic. I see it as something that supports defensive programming,
>improved error handling, and improved user experience. 


Indeed, which is why I wonder if a less tempting name than exists(), and a less 
prominent link in the manual, would highlight that intention.

Regards,
-- 
Rowan Collins
[IMSoP]


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

Reply via email to