On Wed, Jul 18, 2012 at 12:21 PM, Galen Wright-Watson <ww.ga...@gmail.com>wrote:

>
>
> On Wed, Jul 18, 2012 at 7:20 AM, Anthony Ferrara <ircmax...@gmail.com>wrote:
>
>>
>> On Wed, Jul 18, 2012 at 10:15 AM, Rafael Dohms <lis...@rafaeldohms.com.br
>> >wrote:
>>
>> > [...]
>>
>> >
>> > This is basically because the ternary operator does not do a internal
>> > implicit isset, only an empty.
>> >
>>
>> It does not do an empty. Empty would avoid notices as well. All it does is
>> an implicit bool cast...
>>
>>
>> > Does this seem like a possible improvement we can work on? Anyone
>> > interested in championing the change?
>> >
>>
>> I like it in principle. My only concern is *why* wasn't it done this way
>> in
>> the first place... Is there a reason?
>>
>
> It changes the semantics. If the variable is set to a falsey value and ?:
> uses an implicit isset, the value of the expression will be the falsey
> value.
>
>     $config['width'] = ''
>     $width = $config['width'] ?: 300
>     # $width == ''
>
> If !empty were used instead of isset, you could preserve semantics ($a ?:
> dflt = !empty($a) ? $a : dflt).
>

However, this would break if someone were to use an explicit isset, so ?:
could only use an implicit !empty if the expression isn't an isset
expression (which starts to get messy, grammar-wise).

Looking over the previous discussion, people objected to altering the
behavior of ?: precisely because it currently generates notices, which they
desire.

The following use-cases were put forward as commonly occurring and verbose
enough to desire syntactic sugar:

   1. isset($arr['key']) ? $arr['key'] : dflt
   2. ! empty($arr['key']) ? $arr['key'] : dflt
   3. ! is_null($arr['key']) ? $arr['key'] : dflt (used instead of isset
   version; both wouldn't appear in same code base)
   4. $arr['key'] = isset($arr['key']) ? $arr['key'] : dflt
   5. isset($arr['key']) ? strtoupper($arr['key']) : dflt

The following new operators were suggested:

   1. new ternary based on isset (e.g. "$a ?? strtoupper($a) : 'DFLT'" with
   implicit isset)
   2. new shortcut ternary based on isset
   3. new shortcut ternary based on !empty (objection: not as useful as
   isset, since !empty is equivalent to !! but with notice suppression)
   4. new shortcut ternary based on !== null or ! is_null
   5. new shortcut ternary that only works on arrays and is based
   on array_key_exists
   6. indexing operator that suppress undefined index notices
   7. variable access that suppresses undefined variable notices
   8. assign-if-not-set operator  (like ||= in Javascript)

Some objections to the above:

   1. (new ternary) ?
   2. (isset) Some developers always set variables and never want undefined
   notice suppression (the "never-unset" style), which isset will do. However,
   this isn't as common a style.
   3. (!empty) Not as useful as isset, since !empty is equivalent to !! but
   with notice suppression. Also, !empty($a)?$a:dflt isn't used as much as
   isset($a)?$a:dflt.
   4. (!== null / ! is_null) Not as useful as isset, since it doesn't
   suppress notices, so isn't a replacement for the isset($a)?$a:dflt pattern.
   However, it can be used in combination with 6 for the isset-based ternary
   for arrays (e.g. "$arr?['key'] ?: 'dflt'").
   5. (array_key_exists) Conceptually, anything unset has a null value, and
   should thus be equivalent in value to something set to NULL.
   array_key_exists distinguishes between unset and set to NULL, which
   won't always match how some want to use the shortcut ternary. Thus, not as
   useful as is_null.
   6. (indexing w/o notices) ?
   7. (variable access) Probably do more harm than good. It's easy to
   ensure a variable is set.
   8. (assign-if-not-set) For arrays, there's the alternative:

       $arr += Array('key' => 'value');

   This can also be used for a "never-unset" style to set defaults for an
   array, which goes with the "! is_null($a) ? $a : dflt" pattern.

Various syntax proposals:

   1. "$a ?? $b : dflt"  as a ternary, with shortcutting behavior.
   2. "$a ?? dflt" as a shortcut ternary
   3. "$a ?! dflt" as a shortcut ternary based on !empty (could be added
   along with "??"; objection is that it could ambiguate PHP's syntax,
   conflicting with the not operator)
   4. "$a $: dflt"  as a shortcut ternary
   5. "$arr?['key']" to suppress undefined index notices
   6. "$arr@['key']" to suppress undefined index notices
   7. "$?var" to suppress undefined variable notices
   8. "$a ??= dflt" as an assign-if-not-set operator (goes along with "??")
   9. "$a !?= dflt" as an assign-if-not-set operator ("!" suggests not-set)
   10. "$a $:= dflt" as an assign-if-not-set operator (goes along with "$:")


  ?? / isset vs ?? / is_null

Of the various proposals, "??" (with semantics of "isset($a) ? $a : dflt")
already has a precedence: in C# as the null-coalescing operator. While PHP
doesn't have non-nullable types (hence "??" isn't a necessity), using ?? is
perhaps the least surprising option, and (including "??=") would cover
use-cases 1 and 4. On the other hand, PHP's "??" wouldn't be the same as
C#, since C# requires that variables be declared. Arguably, having "??"
equivalent to "!is_null($a) ? $a : dflt" is closer to C# semantics. Also,
use-cases 2 and 3 would be left out, whereas operator proposals 4 (?? /
is_null), 6 (?[]) and 8 (??= / is_null) together cover use-cases 1, 3 and
4. Back on the first hand, use-cases 2 and 3 are less common and this is
(after all) merely syntactic sugar, which should be targeting the common
cases.

  ??: vs ??

The ternary "??:" (whether based on isset or is_null) can also cover
use-case 5, but isn't so good for case 4 ("??:=" would be ugly). One one
hand, the short-cut "??:" may be surprising to developers familiar with
C#'s "??:". On the other, PHP ain't C#, and documentation can cover "??:".
Besides, "??" isn't the only null-coalescing operator out there, so why
should C# be given special consideration? Less rhetorically, would
supporting both "??" and "??:", with "$a ??: dflt" equivalent to "$a ?? dflt",
be undesirable?

Personally, I support syntaxes 8. ??= with either 1. ??: / isset or
(1. ??:/ is_null and 5.
?[]).

Reply via email to