Hey there,
I've been working on a little patch that will allow variables ($1) in
a short-ternary operation to go through an implicit isset
(zend_do_isset_or_isempty) check so that the average use-case for the
short-ternary operator doesn't yield in a notice whenever the first
variable of the expression isn't set.
So the use-case I'm considering is the following:
<?php
$list = array('name' => 'list');
echo $list['name'] ?: 'List not set.' . PHP_EOL;
echo $list['name-notset'] ?: 'List not set.' . PHP_EOL;
?>
This example, which we all know, will result in a notice for the
second echo statement because the requested array-key doesn't actually
exist in the array.
Now, looking at the original implementation thread of ifsetor and ?: I
can see that Marcus' patch had an implicit isset() on the first
variable but I cannot seem to track down why this wasn't implemented
in the final patch.
I'm merely looking for counter-arguments as to why an implicit
isset/isempty should not be performed when the first argument is
indeed a variable and not an expr. The only counter-argument (If this
can even be considered remotely related to an argument) is that having
an implicit isset() would return the boolean value of the check. See
in the common misconceptions of ifsetor on the wiki [1]
I am not trying to revive ifsetor() because I believe this is an
amazingly ugly language construct and I don't think it has an actual
place in PHP however, implicitly performing the ifestor check on
"variable"s and not "expr" could greatly improve it's usability I
believe.
Anyone has notes about the arguments against the implicit check at the
Chicago Round-Table meeting?
Thanks,
[1] Ifsetor cached wiki rfc:
http://webcache.googleusercontent.com/search?q=cache:jKrV2u7jeokJ:wiki.php.net/rfc/ifsetor+php+ifsetor+patch&cd=1&hl=en&ct=clnk&gl=us&client=firefox-a&source=www.google.com
--
David Coallier
Hey there,
I've been working on a little patch that will allow variables ($1) in
a short-ternary operation to go through an implicit isset
(zend_do_isset_or_isempty) check so that the average use-case for the
short-ternary operator doesn't yield in a notice whenever the first
variable of the expression isn't set.So the use-case I'm considering is the following:
<?php
$list = array('name' => 'list');echo $list['name'] ?: 'List not set.' . PHP_EOL; echo $list['name-notset'] ?: 'List not set.' . PHP_EOL;
?>
This example, which we all know, will result in a notice for the
second echo statement because the requested array-key doesn't actually
exist in the array.
I'm not familiar with the construct, but to be honest, I fail to see how
it is useful without the suppression of the notice. I mean, it's a
shorthand for isset($var)?$var:$something_else isn't it? That
presupposes that $var may not be set, but that you've accounted for that
fact, so don't want a notice about it. Obviously the isset() can only be
applied if the 'left hand side' is an lval, but I think it makes sense
to apply it whenever it is an lval.
So a big +1 from me.
Ben.
On Thu, Mar 31, 2011 at 7:46 PM, Ben Schmidt
mail_ben_schmidt@yahoo.com.au wrote:
Hey there,
I've been working on a little patch that will allow variables ($1) in
a short-ternary operation to go through an implicit isset
(zend_do_isset_or_isempty) check so that the average use-case for the
short-ternary operator doesn't yield in a notice whenever the first
variable of the expression isn't set.So the use-case I'm considering is the following:
<?php
$list = array('name' => 'list');echo $list['name'] ?: 'List not set.' . PHP_EOL;
echo $list['name-notset'] ?: 'List not set.' . PHP_EOL;
?>This example, which we all know, will result in a notice for the
second echo statement because the requested array-key doesn't actually
exist in the array.I'm not familiar with the construct, but to be honest, I fail to see how
it is useful without the suppression of the notice. I mean, it's a
shorthand for isset($var)?$var:$something_else isn't it? That
presupposes that $var may not be set, but that you've accounted for that
fact, so don't want a notice about it. Obviously the isset() can only be
applied if the 'left hand side' is an lval, but I think it makes sense
to apply it whenever it is an lval.So a big +1 from me.
Ben.
Its also a +1 for me, it would make the ternary operator much more
useful to me e remove lots of verbose code for handling arrays.
--
Rafael Dohms
PHP Evangelist and Community Leader
http://www.rafaeldohms.com.br
http://www.phpsp.org.br
On Thu, Mar 31, 2011 at 7:46 PM, Ben Schmidt
mail_ben_schmidt@yahoo.com.au wrote:Hey there,
I've been working on a little patch that will allow variables ($1) in
a short-ternary operation to go through an implicit isset
(zend_do_isset_or_isempty) check so that the average use-case for the
short-ternary operator doesn't yield in a notice whenever the first
variable of the expression isn't set.So the use-case I'm considering is the following:
<?php
$list = array('name' => 'list');echo $list['name'] ?: 'List not set.' . PHP_EOL; echo $list['name-notset'] ?: 'List not set.' . PHP_EOL;
?>
This example, which we all know, will result in a notice for the
second echo statement because the requested array-key doesn't actually
exist in the array.I'm not familiar with the construct, but to be honest, I fail to see how
it is useful without the suppression of the notice. I mean, it's a
shorthand for isset($var)?$var:$something_else isn't it? That
presupposes that $var may not be set, but that you've accounted for that
fact, so don't want a notice about it. Obviously the isset() can only be
applied if the 'left hand side' is an lval, but I think it makes sense
to apply it whenever it is an lval.So a big +1 from me.
Ben.
Its also a +1 for me, it would make the ternary operator much more
useful to me e remove lots of verbose code for handling arrays.
Well, it would change the semantics. And Ben, no, it isn't shorthand for
an isset() it is like writing (boolean)$var?$var:$something
-Rasmus
On Thu, Mar 31, 2011 at 7:46 PM, Ben Schmidt
mail_ben_schmidt@yahoo.com.au wrote:I've been working on a little patch that will allow variables ($1) in
a short-ternary operation to go through an implicit isset
(zend_do_isset_or_isempty) check so that the average use-case for the
short-ternary operator doesn't yield in a notice whenever the first
variable of the expression isn't set.So the use-case I'm considering is the following:
<?php
$list = array('name' => 'list');echo $list['name'] ?: 'List not set.' . PHP_EOL; echo $list['name-notset'] ?: 'List not set.' . PHP_EOL;
?>
This example, which we all know, will result in a notice for the
second echo statement because the requested array-key doesn't actually
exist in the array.I'm not familiar with the construct, but to be honest, I fail to see how
it is useful without the suppression of the notice. I mean, it's a
shorthand for isset($var)?$var:$something_else isn't it? That
presupposes that $var may not be set, but that you've accounted for that
fact, so don't want a notice about it. Obviously the isset() can only be
applied if the 'left hand side' is an lval, but I think it makes sense
to apply it whenever it is an lval.So a big +1 from me.
Ben.
Its also a +1 for me, it would make the ternary operator much more
useful to me e remove lots of verbose code for handling arrays.Well, it would change the semantics. And Ben, no, it isn't shorthand for
an isset() it is like writing (boolean)$var?$var:$something
It may change the semantics as they stand, but I'd argue that the
expectation from the shorthand ternary is to shorten code that
currently uses isset(). As it is, I have almost no use for it at this
point, as I end up needing to do:
$value = isset($a[$key]) ? $a[$key] : 'Not set';
which is exactly the situation I had before it was introduced.
--
Matthew Weier O'Phinney
Project Lead | matthew@zend.com
Zend Framework | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
It may change the semantics as they stand, but I'd argue that the
expectation from the shorthand ternary is to shorten code that
currently uses isset(). As it is, I have almost no use for it at this
point, as I end up needing to do:$value = isset($a[$key]) ? $a[$key] : 'Not set';
which is exactly the situation I had before it was introduced.
Not sure why you would have that expectation. The long ternary doesn't
do that, and there is nothing about the short ternary that changes that.
There was talk of a new ifsetor type of operator to have those semantics
but never any talk of changing existing semantics.
-Rasmus
Hello,
It may change the semantics as they stand, but I'd argue that the
expectation from the shorthand ternary is to shorten code that
currently uses isset(). As it is, I have almost no use for it at this
point, as I end up needing to do:
I don't think that changing it to do a implicit isset really fixes the
reason developers use it as previously mentioned. My code is littered
with isset checks, I would rather see a syntax or operator
specifically for this purpose, like ?? since ?: has already been
implemented in a different (and in my opinion in all to many cases not
a useful) way. Syntax doesn't matter to me though long as it serves my
purpose.
$var = Array('foo' => 'I am set');
$value = $var['foo'] ?? 'Foo was not set'; // value = "I am set"
$value = $var['bar'] ?? 'Bar was not set'; // value ="Bar was not
set"; !!no warning!!
It may change the semantics as they stand, but I'd argue that the
expectation from the shorthand ternary is to shorten code that
currently uses isset(). As it is, I have almost no use for it at this
point, as I end up needing to do:$value = isset($a[$key]) ? $a[$key] : 'Not set';
which is exactly the situation I had before it was introduced.
Not sure why you would have that expectation. The long ternary doesn't
do that, and there is nothing about the short ternary that changes that.
There was talk of a new ifsetor type of operator to have those semantics
but never any talk of changing existing semantics.
Well it could (and I believe that was the intention) call !empty instead
of isset, that way the semantics would not be changed, appart from the
lack of error for undefined variables.
Best,
-Rasmus
It may change the semantics as they stand, but I'd argue that the
expectation from the shorthand ternary is to shorten code that
currently uses isset(). As it is, I have almost no use for it at this
point, as I end up needing to do:$value = isset($a[$key]) ? $a[$key] : 'Not set';
which is exactly the situation I had before it was introduced.
Not sure why you would have that expectation. The long ternary doesn't
do that, and there is nothing about the short ternary that changes that.
There was talk of a new ifsetor type of operator to have those semantics
but never any talk of changing existing semantics.Well it could (and I believe that was the intention) call !empty instead
of isset, that way the semantics would not be changed, appart from the
lack of error for undefined variables.
Since I see the beast has risen from the dead, I'd like to chime in
again for my proposal to have a "function" called "filled". It is the
opposite of empty() and takes variable number of arguments. The first
non-empty value is returned. example:
$x = filled($myarray['badkey'], $varundef, $obj->nosuch, $default);
This must be created in the Zend engine because userland can not catch
the unset keys and variables.
Again, "filled()" would be the opposite of empty() and we'd need some
other function similar to be the opposite of isset() if you wanted that
type of check. The proposed filled() will suit all my needs with great
satisfaction :-)
-- Dante
D. Dante Lorenso
dante@lorenso.com
972-333-4139
Hi!
$value = isset($a[$key]) ? $a[$key] : 'Not set';
which is exactly the situation I had before it was introduced.
Not sure why you would have that expectation. The long ternary doesn't
do that, and there is nothing about the short ternary that changes that.
It is true, however I think the amount of boilerplate code produces by
this paradigm is staggering, and it's about time we fixed that. We had a
chance of doing it with ?: but for one reason or another it was passed,
but the need is still there. I think actually the idea of "expr ??
expr2", meaning (isset($expr)?$expr:$expr2) is not bad. Anybody sees any
holes in it?
And yes, I wouldn't be disappointed too much if ?: didn't generate
notices either. With modern IDEs times when it helped catch typos are
mostly gone, and now these warnings are just a very annoying reason to
write boilerplate code.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
$value = isset($a[$key]) ? $a[$key] : 'Not set';
which is exactly the situation I had before it was introduced.
Not sure why you would have that expectation. The long ternary doesn't
do that, and there is nothing about the short ternary that changes that.It is true, however I think the amount of boilerplate code produces by
this paradigm is staggering, and it's about time we fixed that. We had a
chance of doing it with ?: but for one reason or another it was passed,
but the need is still there. I think actually the idea of "expr ??
expr2", meaning (isset($expr)?$expr:$expr2) is not bad. Anybody sees any
holes in it?
And yes, I wouldn't be disappointed too much if ?: didn't generate
notices either. With modern IDEs times when it helped catch typos are
mostly gone, and now these warnings are just a very annoying reason to
write boilerplate code.
I'm not against coming up with a cleaner no-warning mechanism for this.
I was just responding to the idea that the intent of ?: was to solve
this. It never was. We need to be careful about changing the beahviour
of existing operators.
-Rasmus
We need to be careful about changing the beahviour of existing
operators.
Indeed.
The '?' character already is special, so using '??' seems like a safe,
practical approach. However, I'd prefer maintaining the form of the standard
ternary operator with the colon ($value = $var['bar'] ?? : 'Bar was not
set'; // value ="Bar was not) so the '??' operator could be applied in any
situation that one would normally use the standard ternary operator.
// standard
$value = isset($a[$key]) ? $a[$key] : 'Not set';
// new ?? double ternary that performs isset check and omits second
expression
$value = $a[$key] ?? : 'Not set';
// new ?? double ternary that performs isset check and uses second
expression
$value = $a[$key] ?? strtoupper($a[$key]) : 'Not set';
Granted, the last example might be infrequent, but I think there's also a
value in keeping the form of the double ternary (if used at all) the same as
the standard ternary operator for consistency sake.
Adam
--
Nephtali: A simple, flexible, fast, and security-focused PHP framework
http://nephtaliproject.com
Hi, just to drop an opinion on something I felt natural when reading this:
how about a word instead?:
$value = 'Not set' unless $a['key'];
I think it would be way more readable.
Regards,
David
On Fri, Apr 8, 2011 at 2:02 AM, Adam Richardson simpleshot@gmail.comwrote:
We need to be careful about changing the beahviour of existing
operators.Indeed.
The '?' character already is special, so using '??' seems like a safe,
practical approach. However, I'd prefer maintaining the form of the
standard
ternary operator with the colon ($value = $var['bar'] ?? : 'Bar was not
set'; // value ="Bar was not) so the '??' operator could be applied in any
situation that one would normally use the standard ternary operator.// standard
$value = isset($a[$key]) ? $a[$key] : 'Not set';// new ?? double ternary that performs isset check and omits second
expression
$value = $a[$key] ?? : 'Not set';// new ?? double ternary that performs isset check and uses second
expression
$value = $a[$key] ?? strtoupper($a[$key]) : 'Not set';Granted, the last example might be infrequent, but I think there's also a
value in keeping the form of the double ternary (if used at all) the same
as
the standard ternary operator for consistency sake.Adam
--
Nephtali: A simple, flexible, fast, and security-focused PHP framework
http://nephtaliproject.com
-----Original Message-----
From: Adam Richardson [mailto:simpleshot@gmail.com]
Sent: 08 April 2011 08:02
Indeed.
The '?' character already is special, so using '??' seems like a
safe,
practical approach. However, I'd prefer maintaining the form of the
standard
ternary operator with the colon ($value = $var['bar'] ?? : 'Bar was
not
set'; // value ="Bar was not) so the '??' operator could be applied
in any
situation that one would normally use the standard ternary operator.// standard
$value = isset($a[$key]) ? $a[$key] : 'Not set';// new ?? double ternary that performs isset check and omits second
expression
$value = $a[$key] ?? : 'Not set';// new ?? double ternary that performs isset check and uses second
expression
$value = $a[$key] ?? strtoupper($a[$key]) : 'Not set';
Like it! I would have proposed ??: for the isset() variant of ?:,
and I think decomposing it into a full ternary operator in this way,
with ??: as a degenerate variant, is brilliant.
(Only downside is, people would have to stop referring to the
ternary operator!)
Cheers!
Mike
--
Mike Ford,
Electronic Information Developer, Libraries and Learning Innovation,
Leeds Metropolitan University, C507 City Campus,
Woodhouse Lane, LEEDS, LS1 3HE, United Kingdom
Email: m.ford@leedsmet.ac.uk
Tel: +44 113 812 4730
To view the terms under which this email is distributed, please go to http://disclaimer.leedsmet.ac.uk/email.htm
Hi. I like Adam's suggestion a lot however I'd also find a third
case very useful.
In addition to:
// standard
$value = isset($a[$key]) ? $a[$key] : 'Not set';
// new ?? double ternary that performs isset check and omits second
expression
$value = $a[$key] ?? : 'Not set';
// new ?? double ternary that performs isset check and uses second
expression
$value = $a[$key] ?? strtoupper($a[$key]) : 'Not set';
I would also like a case where you could:
// new ?? double ternary that performs isset check and uses null
$value = $a[$key]??;
This would replace a lot of ugly code I have where: (the @ operator is ugly)
$value = @$a[$key];
When I want to treat all non existing indexes as containing the null value.
~Hannes
We need to be careful about changing the beahviour of existing
operators.Indeed.
The '?' character already is special, so using '??' seems like a safe,
practical approach. However, I'd prefer maintaining the form of the standard
ternary operator with the colon ($value = $var['bar'] ?? : 'Bar was not
set'; // value ="Bar was not) so the '??' operator could be applied in any
situation that one would normally use the standard ternary operator.// standard
$value = isset($a[$key]) ? $a[$key] : 'Not set';// new ?? double ternary that performs isset check and omits second
expression
$value = $a[$key] ?? : 'Not set';// new ?? double ternary that performs isset check and uses second
expression
$value = $a[$key] ?? strtoupper($a[$key]) : 'Not set';Granted, the last example might be infrequent, but I think there's also a
value in keeping the form of the double ternary (if used at all) the same as
the standard ternary operator for consistency sake.Adam
--
Nephtali: A simple, flexible, fast, and security-focused PHP framework
http://nephtaliproject.com
Dear Internals
I'm very happy that this is getting some attention again. Please allow
me to give my 2 cents too. The text below can also be seen nicely
formatted at https://gist.github.com/909711.
Intro
Isset and IsNotEmpty operators have for sure been a hot topic for several years
now and in my opinion rightly so. The non-DRY style of:
$my_array['my_long_boring_key'] = !empty($my_array['my_long_boring_key'])
? $my_array['my_long_boring_key'] : 'Default value';
$my_array['my_long_boring_key'] = isset($my_array['my_long_boring_key'])
? $my_array['my_long_boring_key'] : 'Default value';
is a true day-to-day hassle and addressing this annoyance would be a
big win for
the PHP community as a whole. As PHP has two keywords isset
and empty
that
can check for a non existing variable without throwing errors I think there
should exist two assignment/ternary operators who mirror those.
I have been thinking [1] about the same problem for my meta language Snow and
also ended up using ??
as an isset operator.
Proposal
I propose that two new operators ??
(IssetOperator) and ?!
(NotEmptyOperator) are added. ??
mirrors isset
and ?!
mirrors !empty
.
They are chainable ad nauseum but not with each other.
They would work like this:
Example 1 : Ternary shortcut
Old syntax:
$a = isset($b) ? $b : 42;
$a = !empty($b) ? $b : 42;
New syntax:
$a = $b ?? 42;
$a = $b ?! 42;
Example 2 : Direct assignment
Old syntax:
$arr['key'] = isset($arr['key']) ? $arr['key'] : 42;
$arr['key'] = !empty($arr['key']) ? $arr['key'] : 42;
New syntax:
$arr['key'] ??= 42;
$arr['key'] ?!= 42;
Example 3 : Works with statements too
Old syntax:
// a)
$tmp = get_stuff('foo');
$a = isset($tmp) ? $tmp : 42;
// b)
$tmp = get_stuff('foo');
$a = !empty($tmp) ? $tmp : 42;
New syntax:
// a)
$a = get_stuff('foo') ?? 42;
// b)
$a = get_stuff('foo') ?! 42;
Example 4 : Chaining
Old syntax [2]:
$a = false;
if (!empty($c) {
$a = $c;
} else {
$tmp = get_stuff();
$a = !empty($tmp) ? $tmp : false;
}
if ($a === false) {
$a = !empty($c) ? $c : 42;
}
New syntax:
$a = $c ?! get_stuff() ?! $b ?! 42;
Example 5 : Illegal syntax
$a = $d ?? $c ?! $b ?? 42; // `??` and `?!` cannot be mixed.
References
* [1]: http://code.google.com/p/php-snow/wiki/EmptyIssetOperators
* [2]: This could also be done by nesting ternary operators, but that gets
even more unreadable I think.
New syntax:
// a)
$a = get_stuff('foo') ?? 42;// b) $a = get_stuff('foo') ?! 42;
This is wrong. The "new syntax" is already available since 5.3.0 and is
$a = get_stuff('foo') ?: 42;
Now I agree with you, it sounds great and all, but we have to be clear:
$a ?: $b => $a ? $a : $b
And ?? should equal to !empty($a), or otherwise said isset($a) && $a
So:
$a ?? $b => (isset($a) && $a) ? $a : $b
Again, your example1 was unclear. !empty is not the equivalent of
isset(). They only are equal if the value is null, but not for false or
"" or array().
Seeing how everyone says confusing stuff here, I'm starting to think
those shortcuts may actually be more harmful than anything.
I'd just favor switching ?: to be equivalent to !empty() instead of just
a cast to boolean, because it means we can drop the isset checks, and
the semantics wouldn't change - only BC "break" would be warnings going
away. The rest, adding new operators, is dangerous imo.
Cheers
--
Jordi Boggiano
@seldaek :: http://seld.be/
I think "?!" wouldn't work as an operator as it would conflict with ternary
comparision + not operator. Also I don't see the point of adding an operator
for "empty" as the function/construct itself is pretty confusing and
non-useful as you have to memorize all the things that happen to be
considered "empty" by it and those things has too align up with the things
you want to check for by chance. (I never use it.)
Empty-ness is just one of a billion things you might want to write a
comparison for (and it's not even well defined). Having an operator for that
would be crazy. Dealing with possibly undefined indexes/properties is a very
common use case though which is why I think it deserves an operator. The
"empty comparison" thing is a separate issue and it can simply be dealt
with by separating the assignment and comparison into two expressions...
~Hannes
Dear Internals
I'm very happy that this is getting some attention again. Please allow
me to give my 2 cents too. The text below can also be seen nicely
formatted at https://gist.github.com/909711.Intro
Isset and IsNotEmpty operators have for sure been a hot topic for several
years
now and in my opinion rightly so. The non-DRY style of:$my_array['my_long_boring_key'] =
!empty($my_array['my_long_boring_key'])
? $my_array['my_long_boring_key'] : 'Default value';
$my_array['my_long_boring_key'] = isset($my_array['my_long_boring_key'])
? $my_array['my_long_boring_key'] : 'Default value';is a true day-to-day hassle and addressing this annoyance would be a
big win for
the PHP community as a whole. As PHP has two keywordsisset
andempty
that
can check for a non existing variable without throwing errors I think there
should exist two assignment/ternary operators who mirror those.I have been thinking [1] about the same problem for my meta language Snow
and
also ended up using??
as an isset operator.Proposal
I propose that two new operators
??
(IssetOperator) and?!
(NotEmptyOperator) are added.??
mirrorsisset
and?!
mirrors
!empty
.
They are chainable ad nauseum but not with each other.They would work like this:
Example 1 : Ternary shortcut
Old syntax:
$a = isset($b) ? $b : 42;
$a = !empty($b) ? $b : 42;New syntax:
$a = $b ?? 42;
$a = $b ?! 42;Example 2 : Direct assignment
Old syntax:
$arr['key'] = isset($arr['key']) ? $arr['key'] : 42;
$arr['key'] = !empty($arr['key']) ? $arr['key'] : 42;New syntax:
$arr['key'] ??= 42;
$arr['key'] ?!= 42;Example 3 : Works with statements too
Old syntax:
// a)
$tmp = get_stuff('foo');
$a = isset($tmp) ? $tmp : 42;// b)
$tmp = get_stuff('foo');
$a = !empty($tmp) ? $tmp : 42;New syntax:
// a)
$a = get_stuff('foo') ?? 42;// b)
$a = get_stuff('foo') ?! 42;Example 4 : Chaining
Old syntax [2]:
$a = false;
if (!empty($c) {
$a = $c;
} else {
$tmp = get_stuff();
$a = !empty($tmp) ? $tmp : false;
}
if ($a === false) {
$a = !empty($c) ? $c : 42;
}New syntax:
$a = $c ?! get_stuff() ?! $b ?! 42;Example 5 : Illegal syntax
$a = $d ?? $c ?! $b ?? 42; //
??
and?!
cannot be mixed.References
* [1]: http://code.google.com/p/php-snow/wiki/EmptyIssetOperators * [2]: This could also be done by nesting ternary operators, but that
gets
even more unreadable I think.
I just feels that !empty($arr['key']) or isset($arr['key']) do not express
the real meaning, instead I would choose to write array_key_exists('key',
$arr). It may be slower but it clearly express what I meant.
Regarding the operators, I believe they will do more harm than good.
To check if a variable was already defined is a bad programing habit, these
operators will encourage that kind of things
In the other hand, the isset check inside the condition ?: would silently
improve not-so-well written code, and could be a good feature for the lang.
Martin Scotta
On Fri, Apr 8, 2011 at 11:27 AM, Hannes Landeholm landeholm@gmail.comwrote:
I think "?!" wouldn't work as an operator as it would conflict with ternary
comparision + not operator. Also I don't see the point of adding an
operator
for "empty" as the function/construct itself is pretty confusing and
non-useful as you have to memorize all the things that happen to be
considered "empty" by it and those things has too align up with the things
you want to check for by chance. (I never use it.)Empty-ness is just one of a billion things you might want to write a
comparison for (and it's not even well defined). Having an operator for
that
would be crazy. Dealing with possibly undefined indexes/properties is a
very
common use case though which is why I think it deserves an operator. The
"empty comparison" thing is a separate issue and it can simply be dealt
with by separating the assignment and comparison into two expressions...~Hannes
Dear Internals
I'm very happy that this is getting some attention again. Please allow
me to give my 2 cents too. The text below can also be seen nicely
formatted at https://gist.github.com/909711.Intro
Isset and IsNotEmpty operators have for sure been a hot topic for several
years
now and in my opinion rightly so. The non-DRY style of:$my_array['my_long_boring_key'] =
!empty($my_array['my_long_boring_key'])
? $my_array['my_long_boring_key'] : 'Default value';
$my_array['my_long_boring_key'] =
isset($my_array['my_long_boring_key'])
? $my_array['my_long_boring_key'] : 'Default value';is a true day-to-day hassle and addressing this annoyance would be a
big win for
the PHP community as a whole. As PHP has two keywordsisset
andempty
that
can check for a non existing variable without throwing errors I think
there
should exist two assignment/ternary operators who mirror those.I have been thinking [1] about the same problem for my meta language Snow
and
also ended up using??
as an isset operator.Proposal
I propose that two new operators
??
(IssetOperator) and?!
(NotEmptyOperator) are added.??
mirrorsisset
and?!
mirrors
!empty
.
They are chainable ad nauseum but not with each other.They would work like this:
Example 1 : Ternary shortcut
Old syntax:
$a = isset($b) ? $b : 42;
$a = !empty($b) ? $b : 42;New syntax:
$a = $b ?? 42;
$a = $b ?! 42;Example 2 : Direct assignment
Old syntax:
$arr['key'] = isset($arr['key']) ? $arr['key'] : 42;
$arr['key'] = !empty($arr['key']) ? $arr['key'] : 42;New syntax:
$arr['key'] ??= 42;
$arr['key'] ?!= 42;Example 3 : Works with statements too
Old syntax:
// a)
$tmp = get_stuff('foo');
$a = isset($tmp) ? $tmp : 42;// b)
$tmp = get_stuff('foo');
$a = !empty($tmp) ? $tmp : 42;New syntax:
// a)
$a = get_stuff('foo') ?? 42;// b)
$a = get_stuff('foo') ?! 42;Example 4 : Chaining
Old syntax [2]:
$a = false;
if (!empty($c) {
$a = $c;
} else {
$tmp = get_stuff();
$a = !empty($tmp) ? $tmp : false;
}
if ($a === false) {
$a = !empty($c) ? $c : 42;
}New syntax:
$a = $c ?! get_stuff() ?! $b ?! 42;Example 5 : Illegal syntax
$a = $d ?? $c ?! $b ?? 42; //
??
and?!
cannot be mixed.References
* [1]: http://code.google.com/p/php-snow/wiki/EmptyIssetOperators * [2]: This could also be done by nesting ternary operators, but that
gets
even more unreadable I think.
Operators should have very specific purpose and function... a ternary if
statement should just be another way to express a normal if statement.
Making the ? operator suppress the not defined error would be a poor
compromise, making PHP inconsistent. Then I'd rather have access of
non-defined array indexes return null instead (simply removing the
not-defined notice for arrays - where array_key_exists and isset would still
work like normal if you want to check for undefined).
~Hannes
I just feels that !empty($arr['key']) or isset($arr['key']) do not express
the real meaning, instead I would choose to write array_key_exists('key',
$arr). It may be slower but it clearly express what I meant.Regarding the operators, I believe they will do more harm than good.
To check if a variable was already defined is a bad programing habit, these
operators will encourage that kind of thingsIn the other hand, the isset check inside the condition ?: would silently
improve not-so-well written code, and could be a good feature for the lang.Martin Scotta
On Fri, Apr 8, 2011 at 11:27 AM, Hannes Landeholm landeholm@gmail.comwrote:
I think "?!" wouldn't work as an operator as it would conflict with
ternary
comparision + not operator. Also I don't see the point of adding an
operator
for "empty" as the function/construct itself is pretty confusing and
non-useful as you have to memorize all the things that happen to be
considered "empty" by it and those things has too align up with the things
you want to check for by chance. (I never use it.)Empty-ness is just one of a billion things you might want to write a
comparison for (and it's not even well defined). Having an operator for
that
would be crazy. Dealing with possibly undefined indexes/properties is a
very
common use case though which is why I think it deserves an operator. The
"empty comparison" thing is a separate issue and it can simply be dealt
with by separating the assignment and comparison into two expressions...~Hannes
Dear Internals
I'm very happy that this is getting some attention again. Please allow
me to give my 2 cents too. The text below can also be seen nicely
formatted at https://gist.github.com/909711.Intro
Isset and IsNotEmpty operators have for sure been a hot topic for
several
years
now and in my opinion rightly so. The non-DRY style of:$my_array['my_long_boring_key'] =
!empty($my_array['my_long_boring_key'])
? $my_array['my_long_boring_key'] : 'Default value';
$my_array['my_long_boring_key'] =
isset($my_array['my_long_boring_key'])
? $my_array['my_long_boring_key'] : 'Default value';is a true day-to-day hassle and addressing this annoyance would be a
big win for
the PHP community as a whole. As PHP has two keywordsisset
and
empty
that
can check for a non existing variable without throwing errors I think
there
should exist two assignment/ternary operators who mirror those.I have been thinking [1] about the same problem for my meta language
Snow
and
also ended up using??
as an isset operator.Proposal
I propose that two new operators
??
(IssetOperator) and?!
(NotEmptyOperator) are added.??
mirrorsisset
and?!
mirrors
!empty
.
They are chainable ad nauseum but not with each other.They would work like this:
Example 1 : Ternary shortcut
Old syntax:
$a = isset($b) ? $b : 42;
$a = !empty($b) ? $b : 42;New syntax:
$a = $b ?? 42;
$a = $b ?! 42;Example 2 : Direct assignment
Old syntax:
$arr['key'] = isset($arr['key']) ? $arr['key'] : 42;
$arr['key'] = !empty($arr['key']) ? $arr['key'] : 42;New syntax:
$arr['key'] ??= 42;
$arr['key'] ?!= 42;Example 3 : Works with statements too
Old syntax:
// a)
$tmp = get_stuff('foo');
$a = isset($tmp) ? $tmp : 42;// b)
$tmp = get_stuff('foo');
$a = !empty($tmp) ? $tmp : 42;New syntax:
// a)
$a = get_stuff('foo') ?? 42;// b)
$a = get_stuff('foo') ?! 42;Example 4 : Chaining
Old syntax [2]:
$a = false;
if (!empty($c) {
$a = $c;
} else {
$tmp = get_stuff();
$a = !empty($tmp) ? $tmp : false;
}
if ($a === false) {
$a = !empty($c) ? $c : 42;
}New syntax:
$a = $c ?! get_stuff() ?! $b ?! 42;Example 5 : Illegal syntax
$a = $d ?? $c ?! $b ?? 42; //
??
and?!
cannot be mixed.References
* [1]: http://code.google.com/p/php-snow/wiki/EmptyIssetOperators * [2]: This could also be done by nesting ternary operators, but
that
gets
even more unreadable I think.
Hello all,
First post here; been watching for a while though.
IMHO:
-
Implicit isset() checks in ?: would be bad. This would not
"silently improve not-so-well written code"; In fact it would make
not-so-well written code more difficult to debug. I can't count the
number of times I've run across components that are acting oddly
because somebody wrote them to ignore the fact that they're not
receiving some required parameter. At least with the current
functionality of ?: we get a warning. If the collective decision were
to implement this, could it at least have a setting to force it to
function how it does currently? -
A shorthand assignment operator would be handy. I like the suggestion of ??=
where:
$var ??= $default;
is shorthand for
if( !isset($var) ) $var = $default;
Or, maybe similar to C#
$var = $var ?? $default;
(Correct me if I'm using this syntax incorrectly)
This would provide a clean way to set defaults for unset vars but
would make it easy to find blocks of code that are using unset vars
with the ternary operator.
-Matt
I just feels that !empty($arr['key']) or isset($arr['key']) do not express
the real meaning, instead I would choose to write array_key_exists('key',
$arr). It may be slower but it clearly express what I meant.Regarding the operators, I believe they will do more harm than good.
To check if a variable was already defined is a bad programing habit, these
operators will encourage that kind of thingsIn the other hand, the isset check inside the condition ?: would silently
improve not-so-well written code, and could be a good feature for the lang.Martin Scotta
First post here; been watching for a while though.
Same here.
Here's my take:
[1] I don't like ?? / ? because it is disjunctive with === / ==.. The
extra equals sign strengthens equality comparison, while the extra
question mark essentially weakens the ternary operator (making it
more forgiving). (Sure, a case could be made that an "extra" duplicate
operator has no inherent meaning overall, but these two operators seem
to be in a similar domain.)
[2] I would prefer @?. This makes the error-suppression obvious. But
this leads to...
[3] ... are we saying that [a] we are still suppressing a deep error
or [b] or that an error state does not exist anywhere when you use a
special operator? In other words, is it now going to be fully
supported to use undefined variables, as long as we always use
operators that take them into account? This seems to be inviting
criticism from other language fanboys (if we care) since they already
hold the non-fatal use of undefined variables in contempt.
[4] Strange idea: what about treating the variable as defined after
you test it with the special operator, even if you don't specifically
assign it a value?
So:
$varor2 = $var1 @?: 2 // $varor2==2, no warning because special
ternary is used
$varor3 = $var1 ?: 3 // $varor3=3, but no warning because $var1 has
been implicitly defined in special expression
[5] Sort of the opposite of [4] and continuing the question of [3],
what about only letting a variable be special-op-checked once before
throwing a warning. So you can suppress (or not throw) the undefined
warning once, but it is assumed that you will define the variable in
that statement. So this would discourage the continuous use of the
same undef var throughout code (which seems like a code smell), while
allowing for the real case that you're using the special-op to filter
$_REQUEST or whatever -- one time.
I haven't really thought about the edges, but thought I'd put those
out there.
Cheers,
Sandy
Hi guys
Below is a discussion about some of the issues being raised. Again a
nicely formatted version of the whole thing is here:
https://gist.github.com/909711.
Discussion
About changing the beviour of the ternary shortcut
@Jordi, others
Some suggest adding an implicit isset
around the value being tested in the
ternary shortcut. This I think is less than optimal because:
- It would be a huge BC break, because a boolean test and a isset test differs
greatly. [3] - It would be a major WTF, because it would work different than the normal
ternary operator that it is a shortcut of.
Jordi suggests adding an implicit !empty
around the value being tested in the
ternary shortcut. This would not break BC but it still wouldn't improve usecases
where the value tested for is allowed to be falsy ('', 0, "0", false, etc.):
function render_articles($rows, $settings) {
// Shows the last page per default. Zero based.
$settings['page_num'] = $settings['page_num'] ?: count($rows) - 1;
// ...
}
// Lets render_articles showing the first page.
echo render_articles ($rows, array('page_num' => 0));
The obvious bug here is that since 0 is considered falsy, render_articles
will show the last page instead of the first. The correct version is back in
non-dry mode:
$settings['page_num'] = isset($settings['page_num'])
? $settings['page_num']
: count($rows) - 1;
Im writing the same stuff three times. With the ??
operator it would be:
$settings['page_num'] ??= count($rows) - 1;
Why we need both an Isset and IsNotEmpty operator
@Hannes, Ben
What's considered falsy in PHP is very dynamic. Depending on context the
following can easily be considered falsy:
'', null, undefined, array(), false, 0
Therefore we need to be very precise when we are making decisions based on a
variable or statements value. This is where isset
and !empty
compliments
each other very well. Sometimes i want to use a default value when falsy means
"this variable is not defined". Other times I want to assign a default value
when falsy means "this variable is not an empty string".
Sometimes the behaviour we want will change while we are working on the code.
Therefore I strongly believe that not having both operators would severely break
the symmetry and force the end user to make tedious and non-dry refactorings
just because he needs a function to - under certain conditions -
return false or
vice versa.
References
* [3]: http://php.net/manual/en/types.comparisons.php
Sanford Whiteman wrote:
Same here.
Here's my take:
[1] I don't like ?? / ? because it is disjunctive with === / ==.. The
extra equals sign strengthens equality comparison, while the extra
question mark essentially weakens the ternary operator (making it
more forgiving). (Sure, a case could be made that an "extra" duplicate
operator has no inherent meaning overall, but these two operators seem
to be in a similar domain.)
I disagree. They both reinforce the operator.
The = character means equivalence. == means that it is equal, === means
that it is very very equal.
The ? character means uncertainity, doubt. A single ? in a ternary
operator means a question (if() construct).
A ?? would not only mean is this true? but also does it even exists?
It also looks strange to my code parser (looks like a wtf comment) but
I'd probably adapt to that new operator easily.
[4] Strange idea: what about treating the variable as defined after
you test it with the special operator, even if you don't specifically
assign it a value?So:
$varor2 = $var1 @?: 2 // $varor2==2, no warning because special
ternary is used$varor3 = $var1 ?: 3 // $varor3=3, but no warning because $var1 has
been implicitly defined in special expression
This looks like a source for all kind of side-effects to me. I'm not
even convinced
that testing for raw variables would be useful. I think the usecase is
for testing arrays.
[5] Sort of the opposite of [4] and continuing the question of [3],
what about only letting a variable be special-op-checked once before
throwing a warning. So you can suppress (or not throw) the undefined
warning once, but it is assumed that you will define the variable in
that statement. So this would discourage the continuous use of the
same undef var throughout code (which seems like a code smell), while
allowing for the real case that you're using the special-op to filter
$_REQUEST or whatever -- one time.
Tests shouldn't have side effects. Allowing the special-op one time, means
that the addition of a check in one place will start spewing in a
completely
different place of the codebase.
The way of forcing the users to set the undefined variable in one check is
not keeping a track if they have used a magic operation to check it and
didn't
set it after that, but defining a set-value-if-unset operator.
A syntax like ?= looks like a set-if-set, so perhaps it would be more
appropiate
using !?=
I haven't really thought about the edges, but thought I'd put those
out there.
Thanks for sharing!
Hey again
Updated here as always https://gist.github.com/909711. I've tried to
write down the goal of this new feature. Which patterns do we want to
make easier to write?
Do you agree with the goals I've set?
+1 From me of course :)
Also added a proposal that would make userland implementations possible.
Goal
So what should be solved before this new feature can be considered a succes? The
solution should offer DRY solutions to the following patterns:
// Set one variable from another or a default value.
// 1a.
$a = isset($b) ? $b : 'Default value';
// 1b.
$a = !empty($b) ? $b : 'Default value';
// Set one variable from itself or a default value.
// 2a.
$a = isset($a) ? $a : 'Default value';
// 2b.
$a = !empty($a) ? $a : 'Default value';
// Find the first set value from a range of variables and statements.
// 3a.
$tmp = get_value();
if (isset($tmp)) $a = $tmp;
$tmp = $myarr['mykey'];
if (!isset($a) && isset($tmp)) $a = $tmp;
if (!isset($a)) $a = 'Default value';
// 3b.
$tmp = get_value();
if (!empty($tmp)) $a = $tmp;
$tmp = $myarr['mykey'];
if (!isset($a) && !empty($tmp)) $a = $tmp;
if (!isset($a)) $a = 'Default value';
Proposal 2 : Making a userland implementation possible
The one thing preventing us PHP end users for implementing our own solution to
this problem is - as discussed many times before - that it is not possible to
check if a passed argument can be referenced and then reference it. This
proposal adds an AS_REFERENCE
bitmask that can be passed as the second
argument to func_get_arg
which then in turn throws an
ArgNotReferencableException
if the argument is not referenceable.
Below is an example of how firstset
(ifsetor) could be implemented.
function firstset() {
$num_args = func_num_args()
;
for ($i = 0; $i < $num_args; ++$i) {
try {
$arg = func_get_arg($i, AS_REFERENCE);
if (!isset($arg) {
$arg = null;
}
} catch (ArgNotReferencableException $e) {
$arg = func_get_arg($i);
}
if (isset($arg) {
return $arg;
}
}
return null;
}
On Sun, 10 Apr 2011 16:04:06 +0200, Rune Kaagaard rumi.kg@gmail.com
wrote:
Hey again
Updated here as always https://gist.github.com/909711. I've tried to
write down the goal of this new feature. Which patterns do we want to
make easier to write?Do you agree with the goals I've set?
I think these shortcuts could be really useful for array elements, but for
other variables I am really sceptical and I think they would do more harm
than good. Generally I do not really see any reason why a variable should
not be 'instanciated' before use.
So
+1 if this shortcut is implemented to only work for array elements.
-1 for any other variable type.
--
Ole Markus With
I think these shortcuts could be really useful for array elements, but
for other variables I am really sceptical and I think they would do
more harm than good. Generally I do not really see any reason why a
variable should not be 'instanciated' before use.So
+1 if this shortcut is implemented to only work for array elements.
-1 for any other variable type.
There are two issues here.
1. Suppression of notice. I agree, it is best done only for array
keys. It's not hard to initialise a variable with $var=null at the
beginning of a code block to avoid such a notice, and that is the
appropriate way to do it for variables.
2. Offering a shortcut for the common idiom isset($x) ? $x : $y in
line with the DRY design principle. A notice would never be emitted
here in any case. The problem is that this idiom is still in wide use
despite the shortcut ternary operator already provided, because an
isset() check is different to a boolean cast.
Some thoughts:
- Changing the existing behaviour of the ternary or shortcut ternary
operator is a bad idea. Good arguments have been offered against
it.
- The actual intent of 2. is probably $x!==null ? $x : $y i.e. it's
not about suppressing notices at all, but about offering a default
value, and the idiom quite probably only uses isset() because it
predated null in the language.
- If we view 2. in this way, the two problems are independent, and it
seems to me it would be best to solve them independently, rather
than with a single operator.
So, I suggest:
1. An array lookup mechanism that suppresses the notice for undefined
keys. It would work the same as regular array index lookups except
that the notice for undefined keys (and only for undefined keys)
would not be generated (it would not just be hidden, but would never
be even generated).
2. A shortcut for $x!==null ? $x : $y.
This allows people to opt out of either feature if they don't want it,
and doesn't encourage poor coding by suppressing warnings for undefined
variables.
Arguing about syntax is then a second step. However, my views on this
are:
1. Since we have @ meaning error-suppression already, why not reuse
that symbol, in a location that is unambiguous? $array@[$key] would
achieve this, right? It is localised to a single lookup, so can be as
precise as the coder wants. E.g. one could do
$array@["maybe-missing"]["expected"]@["maybe-missing"] and there's no
ambiguity about what is meant. Nesting is likewise unambiguous, so in
$array@[$lookups["key"]] if "key" does not exist, we still get a
notice.
2. We just need a single symbol, probably with multiple characters.
The key thing omitted by the shortcut is !==null so something that
evokes that would be a good choice. Two possibilities are using
something involving ? as in the ternary operator, or | as in the
logical short-circuiting or operator. E.g. we could have $x ??: $y or
$x ||| $y. However, both these somewhat imply either boolean tests or
boolean results, which would be best to avoid. This is not about
error suppression, so using @ would be unwise. Perhaps the best
character to use is $ because $ somewhat represents a variable. So
perhaps a good syntax would be $x $: $y. The $ somewhat evokes to me
'use the variable if you can (it is not null)' and the : somewhat
evokes 'otherwise', so I think it captures the meaning of the
operator.
In combination (which some people probably want), this looks like
$array@["key"] $: "default"
It's a bit different to what we're used to seeing, but the syntax is (1)
sensible and evocative of the right interpretation, and (2) not
misleading. I'd rather see something I'm unsure about and drives me back
to the docs than something that misleads me.
Ben.
Bottom posted.
I think these shortcuts could be really useful for array elements, but
for other variables I am really sceptical and I think they would do
more harm than good. Generally I do not really see any reason why a
variable should not be 'instanciated' before use.So
+1 if this shortcut is implemented to only work for array elements.
-1 for any other variable type.There are two issues here.
Suppression of notice. I agree, it is best done only for array
keys. It's not hard to initialise a variable with $var=null at the
beginning of a code block to avoid such a notice, and that is the
appropriate way to do it for variables.Offering a shortcut for the common idiom isset($x) ? $x : $y in
line with the DRY design principle. A notice would never be emitted
here in any case. The problem is that this idiom is still in wide use
despite the shortcut ternary operator already provided, because an
isset() check is different to a boolean cast.Some thoughts:
Changing the existing behaviour of the ternary or shortcut ternary
operator is a bad idea. Good arguments have been offered against
it.The actual intent of 2. is probably $x!==null ? $x : $y i.e. it's
not about suppressing notices at all, but about offering a default
value, and the idiom quite probably only uses isset() because it
predated null in the language.If we view 2. in this way, the two problems are independent, and it
seems to me it would be best to solve them independently, rather
than with a single operator.So, I suggest:
An array lookup mechanism that suppresses the notice for undefined
keys. It would work the same as regular array index lookups except
that the notice for undefined keys (and only for undefined keys)
would not be generated (it would not just be hidden, but would never
be even generated).A shortcut for $x!==null ? $x : $y.
This allows people to opt out of either feature if they don't want it,
and doesn't encourage poor coding by suppressing warnings for undefined
variables.Arguing about syntax is then a second step. However, my views on this
are:
- Since we have @ meaning error-suppression already, why not reuse
that symbol, in a location that is unambiguous? $array@[$key] would
achieve this, right? It is localised to a single lookup, so can be as
precise as the coder wants. E.g. one could do
$array@["maybe-missing"]["expected"]@["maybe-missing"] and there's no
ambiguity about what is meant. Nesting is likewise unambiguous, so in
$array@[$lookups["key"]] if "key" does not exist, we still get a
notice.
I cry whenever I see code with @ in it...
- We just need a single symbol, probably with multiple characters.
The key thing omitted by the shortcut is !==null so something that
evokes that would be a good choice. Two possibilities are using
something involving ? as in the ternary operator, or | as in the
logical short-circuiting or operator. E.g. we could have $x ??: $y or
$x ||| $y. However, both these somewhat imply either boolean tests or
boolean results, which would be best to avoid. This is not about
error suppression, so using @ would be unwise. Perhaps the best
character to use is $ because $ somewhat represents a variable. So
perhaps a good syntax would be $x $: $y. The $ somewhat evokes to me
'use the variable if you can (it is not null)' and the : somewhat
evokes 'otherwise', so I think it captures the meaning of the
operator.In combination (which some people probably want), this looks like
$array@["key"] $: "default"It's a bit different to what we're used to seeing, but the syntax is (1)
sensible and evocative of the right interpretation, and (2) not
misleading. I'd rather see something I'm unsure about and drives me back
to the docs than something that misleads me.Ben.
What we're wanting are existential assignment and ternary operators.
Simply put, a painless way to set or use a default value based on the
existence of a variable without needing a bunch of extra code to avoid
notices/errors. Sorry Ben, but I think extending the @ operator to
prevent errors from being generated in the first place is a terrible
idea. I would prefer to see @ removed from PHP if possible.
I like Rune's proposal, although I'd prefer ?= for the assignment
operator instead of ??=
I would also want this to work with objects and scalars. It would be
particularly useful within view scripts where the values are passed in
via extract, or as object properties, and you can't instantiate them
first because that would clear them.
Cheers,
David
inline posted
I cry whenever I see code with @ in it...
I always cry when somebody thinks that the @ cannot be used correctly.
btw we have the scream extension and xdebug.scream also, and you could use
an error handler to "scream" the errors suppressed by @, so I don't know why
are you crying.
What we're wanting are existential assignment and ternary operators.
Simply put, a painless way to set or use a default value based on the
existence of a variable without needing a bunch of extra code to avoid
notices/errors. Sorry Ben, but I think extending the @ operator to
prevent errors from being generated in the first place is a terrible
idea. I would prefer to see @ removed from PHP if possible.there are cases where you can't write clean code without @.
for example there is an instruction, which can generate an error and you can
predict that it is "safe" to execute or not.
for example:
- http://php.net/manual/en/simplexmlelement.construct.phphttp://hu2.php.net/manual/en/simplexmlelement.construct.php
- http://php.net/manual/en/function.simplexml-load-file.php
which can be worked around with
http://php.net/manual/en/function.libxml-use-internal-errors.phphttp://hu2.php.net/manual/en/function.libxml-use-internal-errors.php
or another example would be serialize/unserialize:
http://www.php.net/manual/en/function.unserialize.php
it can be a perfectly valid to suppress the notice and check for the return
value of the serialize/unserialize call to handle errors locally.
another example: you have a script, which checks for a cache file, if
present then you simply read it, if not, then you generate the result and
write it to the cache file, which gets invalidated(deleted) if it's older
than x.
but you can't atomically check the existence of the file then read it. and
it can happen (race condition) that you the file was present when you
checked with file_exists, but it is deleted when you try to open it in the
next line.
I think that it could be a good idea to provide an operator to not just
change the error reporting level, but to simply prevent the error
generation.
of course its a tricky question: should we discard the error if an error
handler is registered?
Tyrael
I cry whenever I see code with @ in it...
I don't like @ either. The whole point of this proposal though is to
offer a safe alternative, a way to suppress only those notices which are
being accounted for by the programmer and no more, without messing
around making a custom error handler that ignores one type of error,
which is the current way to do it 'safely'.
What we're wanting are existential assignment and ternary operators.
Simply put, a painless way to set or use a default value based on the
existence of a variable without needing a bunch of extra code to avoid
notices/errors. Sorry Ben, but I think extending the @ operator to
prevent errors from being generated in the first place is a terrible
idea. I would prefer to see @ removed from PHP if possible.
I never meant to extend @, I meant simply to reuse that symbol--i.e. the
@ character--as part of the syntax of a new safer feature, since it
performed a similar function. The actual @ operator is not changed in
any way. Rather, a new @[...] array indexing mechanism is added which
suppresses the Undefined Index notice, and only that notice, by not
generating it.
I would also want this to work with objects and scalars. It would be
particularly useful within view scripts where the values are passed in
via extract, or as object properties, and you can't instantiate them
first because that would clear them.
I guess that's a vaguely valid use case, though I still somewhat think
it is the responsibility of the caller of the view script to ensure all
variables are instantiated (to null if appropriate). I guess an
unambiguous syntax for this could be $@variable.
I guess object properties are another case. I wonder how common. I guess
$object@->property would be the way to deal with that.
I still lean towards just offering it for arrays, though. That seems to be
the area of greatest need by a significant margin.
Ben.
>> I think these shortcuts could be really useful for array elements, but
>> for other variables I am really sceptical and I think they would do
>> more harm than good. Generally I do not really see any reason why a
>> variable should not be 'instanciated' before use.
>>
>> So
>> +1 if this shortcut is implemented to only work for array elements.
>> -1 for any other variable type.
>
> There are two issues here.
>
> 1. Suppression of notice. I agree, it is best done only for array
> keys. It's not hard to initialise a variable with $var=null at the
> beginning of a code block to avoid such a notice, and that is the
> appropriate way to do it for variables.
>
> 2. Offering a shortcut for the common idiom isset($x) ? $x : $y in
> line with the DRY design principle. A notice would never be emitted
> here in any case. The problem is that this idiom is still in wide use
> despite the shortcut ternary operator already provided, because an
> isset() check is different to a boolean cast.
>
> Some thoughts:
>
> - The actual intent of 2. is probably $x!==null ? $x : $y i.e. it's
> not about suppressing notices at all, but about offering a default
> value, and the idiom quite probably only uses isset() because it
> predated null in the language.
>
I have never felt the need for a shortcut in these cases. It would be
interesting to see some code where this would be practical.
> - If we view 2. in this way, the two problems are independent, and it
> seems to me it would be best to solve them independently, rather
> than with a single operator.
>
> So, I suggest:
>
> 1. An array lookup mechanism that suppresses the notice for undefined
> keys. It would work the same as regular array index lookups except
> that the notice for undefined keys (and only for undefined keys)
> would not be generated (it would not just be hidden, but would never
> be even generated).
This is what I feel PHP is missing. Particularly when it comes to
multi-dimensional arrays. Because this feature is missing I tend to do
something like
function generateHash($x, $y, $z)
{
return "$x::$y::$z";
}
if (isset($a[generateHash($x, $y, $z)]) {
...
}
instead of
if (isset($a[$x]) && isset($a[$x][$y]) && isset($a[$x][$y][$z])) {
...
}
> Arguing about syntax is then a second step. However, my views on this
> are:
>
I think it best to avoid discussing the actual syntax before agreeing on
what we really need.
--
Ole Markus With
Systems Architect - Sportradar AS
Developer - Gentoo Linux
What is the purpose of that generateHash function? It doesn't work in the
isset check.
Anyway, you can do a simple $a = array('foo'); isset($a[$x][$y][$z]) without
notices at all unless any of $x $y or $z are not defined, you don't need to
check the indexes one by one.
2011/4/14 Ole Markus With olemarkus@olemarkus.org
On Thu, 14 Apr 2011 02:24:56 +0200, Ben Schmidt <
mail_ben_schmidt@yahoo.com.au> wrote:I think these shortcuts could be really useful for array elements, but
for other variables I am really sceptical and I think they would do
more harm than good. Generally I do not really see any reason why a
variable should not be 'instanciated' before use.So
+1 if this shortcut is implemented to only work for array elements.
-1 for any other variable type.There are two issues here.
Suppression of notice. I agree, it is best done only for array
keys. It's not hard to initialise a variable with $var=null at the
beginning of a code block to avoid such a notice, and that is the
appropriate way to do it for variables.Offering a shortcut for the common idiom isset($x) ? $x : $y in
line with the DRY design principle. A notice would never be emitted
here in any case. The problem is that this idiom is still in wide use
despite the shortcut ternary operator already provided, because an
isset() check is different to a boolean cast.Some thoughts:
- The actual intent of 2. is probably $x!==null ? $x : $y i.e. it's
not about suppressing notices at all, but about offering a default
value, and the idiom quite probably only uses isset() because it
predated null in the language.I have never felt the need for a shortcut in these cases. It would be
interesting to see some code where this would be practical.
- If we view 2. in this way, the two problems are independent, and it
seems to me it would be best to solve them independently, rather than with a single operator.
So, I suggest:
- An array lookup mechanism that suppresses the notice for undefined
keys. It would work the same as regular array index lookups except
that the notice for undefined keys (and only for undefined keys)
would not be generated (it would not just be hidden, but would never
be even generated).This is what I feel PHP is missing. Particularly when it comes to
multi-dimensional arrays. Because this feature is missing I tend to do
something likefunction generateHash($x, $y, $z)
{
return "$x::$y::$z";
}if (isset($a[generateHash($x, $y, $z)]) {
...
}instead of
if (isset($a[$x]) && isset($a[$x][$y]) && isset($a[$x][$y][$z])) {
...}
Arguing about syntax is then a second step. However, my views on this
are:
I think it best to avoid discussing the actual syntax before agreeing on
what we really need.--
Ole Markus With
Systems Architect - Sportradar AS
Developer - Gentoo Linux
What is the purpose of that generateHash function? It doesn't work in the
isset check.Anyway, you can do a simple $a = array('foo'); isset($a[$x][$y][$z]) without
notices at all unless any of $x $y or $z are not defined, you don't need to
check the indexes one by one.2011/4/14 Ole Markus With olemarkus@olemarkus.org
On Thu, 14 Apr 2011 02:24:56 +0200, Ben Schmidt <
mail_ben_schmidt@yahoo.com.au> wrote:I think these shortcuts could be really useful for array elements, but
for other variables I am really sceptical and I think they would do
more harm than good. Generally I do not really see any reason why a
variable should not be 'instanciated' before use.So
+1 if this shortcut is implemented to only work for array elements.
-1 for any other variable type.There are two issues here.
1. Suppression of notice. I agree, it is best done only for array
keys. It's not hard to initialise a variable with $var=null at the
beginning of a code block to avoid such a notice, and that is the
appropriate way to do it for variables.2. Offering a shortcut for the common idiom isset($x) ? $x : $y in
line with the DRY design principle. A notice would never be emitted
here in any case. The problem is that this idiom is still in wide use
despite the shortcut ternary operator already provided, because an
isset() check is different to a boolean cast.Some thoughts:
- The actual intent of 2. is probably $x!==null ? $x : $y i.e. it's
not about suppressing notices at all, but about offering a default
value, and the idiom quite probably only uses isset() because it
predated null in the language.I have never felt the need for a shortcut in these cases. It would be
interesting to see some code where this would be practical.- If we view 2. in this way, the two problems are independent, and it
seems to me it would be best to solve them independently, rather
than with a single operator.So, I suggest:
1. An array lookup mechanism that suppresses the notice for undefined
keys. It would work the same as regular array index lookups except
that the notice for undefined keys (and only for undefined keys)
would not be generated (it would not just be hidden, but would never
be even generated).This is what I feel PHP is missing. Particularly when it comes to
multi-dimensional arrays. Because this feature is missing I tend to do
something likefunction generateHash($x, $y, $z)
{
return "$x::$y::$z";
}if (isset($a[generateHash($x, $y, $z)]) {
...
}instead of
if (isset($a[$x]) && isset($a[$x][$y]) && isset($a[$x][$y][$z])) {
...}
Arguing about syntax is then a second step. However, my views on this
are:
I think it best to avoid discussing the actual syntax before agreeing on
what we really need.--
Ole Markus With
Systems Architect - Sportradar AS
Developer - Gentoo Linux--
http://news.php.net/php.internals/51877
array_key_exists($key, $array) for arrays
array_key_exists($varname, get_defined_vars()
) for locally scoped variables.
No need to use @.
isset() and empty() will not differentiate between an undefined
variable or index and a variable or an array element which is assigned
null.
The E_NOTICE
only ever gets fired for the undefined variable/key ...
Notice: Undefined variable
Notice: Undefined index
I think it depends upon the developer's requirement.
Are they attempting to determine the existence of a variable/index
entry or are they attempting to determine if the variable/element is
null.
I always declare my variables. So, I don't want to use isset() as they
will be an incorrect test. I use is_null()
. Specifically testing the
value. If I've made a mistake and NOT declared the variable (or made a
typo), I want to know. I don't want to hide it with isset()/empty().
--
Richard Quadling
Twitter : EE : Zend
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY
Am 14.04.2011 12:02, schrieb Richard Quadling:
I always declare my variables. So, I don't want to use isset() as they
will be an incorrect test. I useis_null()
. Specifically testing the
value. If I've made a mistake and NOT declared the variable (or made a
typo), I want to know. I don't want to hide it with isset()/empty()
yes and no
$config['modulename'] = array
(
'icon' => 'bla.gif',
'default_params' => array
(
'autocleanup' => 1,
'ignore_user_abort' => 0,
)
);
if 'default_params' are optional you NEED isset() to decide
do something with them or skip operations
Am 14.04.2011 12:02, schrieb Richard Quadling:
I always declare my variables. So, I don't want to use isset() as they
will be an incorrect test. I useis_null()
. Specifically testing the
value. If I've made a mistake and NOT declared the variable (or made a
typo), I want to know. I don't want to hide it with isset()/empty()yes and no
$config['modulename'] = array
(
'icon' => 'bla.gif',
'default_params' => array
(
'autocleanup' => 1,
'ignore_user_abort' => 0,
)
);if 'default_params' are optional you NEED isset() to decide
do something with them or skip operations
I think that depends upon the developer.
I don't mix the tests for existence.
Mixing the tests means a typo in the isset() will hide the lack of existence.
But array_key_exists()
is not going to do that. If the key exists then
I can process it. If not, then I can't.
--
Richard Quadling
Twitter : EE : Zend
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY
There are two issues here.
1. Suppression of notice. I agree, it is best done only for array keys. It's not hard to initialise a variable with $var=null at the beginning of a code block to avoid such a notice, and that is the appropriate way to do it for variables. 2. Offering a shortcut for the common idiom isset($x) ? $x : $y in line with the DRY design principle. A notice would never be emitted here in any case. The problem is that this idiom is still in wide use despite the shortcut ternary operator already provided, because an isset() check is different to a boolean cast.
Some thoughts:
- The actual intent of 2. is probably $x!==null ? $x : $y i.e. it's not about suppressing notices at all, but about offering a default value, and the idiom quite probably only uses isset() because it predated null in the language. - If we view 2. in this way, the two problems are independent, and it seems to me it would be best to solve them independently, rather than with a single operator.
So, I suggest:
1. An array lookup mechanism that suppresses the notice for undefined keys. It would work the same as regular array index lookups except that the notice for undefined keys (and only for undefined keys) would not be generated (it would not just be hidden, but would never be even generated).
http://news.php.net/php.internals/51877
array_key_exists($key, $array) for arrays
array_key_exists($varname,get_defined_vars()
) for locally scoped variables.
Apart from being long and ugly, surely that is horribly inefficient.
No need to use @.
True. And I don't think anybody is. We all know @ is dangerous and nasty
and don't use it. We're not seeking an alternative to @, we're seeking
an alternative to repeating ourselves by using
isset()/array_key_exists()/is_null() as well as the value being tested.
But we don't want to do this in a blanket way similar to @ where a whole
bunch of notices are suppressed. We want to specify precisely where
missing values are allowable by indicating exactly which array index
lookups may silently fail (and evaluate to null).
Basically we don't want to make again the mistake that @ was.
Are they attempting to determine the existence of a variable/index
entry or are they attempting to determine if the variable/element is
null.
For me, existence and nullness are basically the same, and I think this
is the common case. The whole point of being able to set something to
null is to have a 'value' to represent 'unsetness'. This is why I think
solving the conditional problem should use a !==null test. That gives
the flexibility to use/pass null to represent 'unsetness' but doesn't
pick up zero, false, etc. like a boolean cast does. Using
array_key_exists()
would remove that flexibility and be less useful.
As far as silencing notices goes, the rationale is that basically we
want to flag that 'null is OK, even if it's a fallback'. I.e. we don't
care whether a value is null because it was set to null, or because null
is a fallback because the variable was never defined. Either way, null
is OK, so don't tell me about it.
The conditional side lets us handle nulls nicely by providing our own
defaults/fallbacks if it appears. The notice-suppression side lets us
say that null is OK, even if that null itself is a fallback for
'undefined'. Quite often they will be used in combination, but they are
independent.
I always declare my variables. So, I don't want to use isset() as they
will be an incorrect test. I useis_null()
. Specifically testing the
value. If I've made a mistake and NOT declared the variable (or made a
typo), I want to know. I don't want to hide it with isset()/empty().
That's exactly why I think the conditional should use a !==null test,
not an isset() test.
Ben.
arrays are intent for holding values, not for represent things so use
objects for that.
the need for array_key_exists/isset to check for the presence of an index is
a smell that you need to refactor your code for a different datatype.
If you cannot change the array, you always can wrap it.
With good data abstractions the usage of array_key_exists/isset/empty is
barely reduced to the minimum.
Martin Scotta
On Thu, Apr 14, 2011 at 10:12 AM, Ben Schmidt <mail_ben_schmidt@yahoo.com.au
wrote:
There are two issues here.
Suppression of notice. I agree, it is best done only for array
keys. It's not hard to initialise a variable with $var=null at the
beginning of a code block to avoid such a notice, and that is the
appropriate way to do it for variables.Offering a shortcut for the common idiom isset($x) ? $x : $y in
line with the DRY design principle. A notice would never be emitted
here in any case. The problem is that this idiom is still in wide
use
despite the shortcut ternary operator already provided, because an
isset() check is different to a boolean cast.Some thoughts:
The actual intent of 2. is probably $x!==null ? $x : $y i.e. it's
not about suppressing notices at all, but about offering a default
value, and the idiom quite probably only uses isset() because it
predated null in the language.If we view 2. in this way, the two problems are independent, and
it
seems to me it would be best to solve them independently, rather
than with a single operator.So, I suggest:
- An array lookup mechanism that suppresses the notice for
undefined
keys. It would work the same as regular array index lookups except
that the notice for undefined keys (and only for undefined keys)
would not be generated (it would not just be hidden, but would never
be even generated).array_key_exists($key, $array) for arrays
array_key_exists($varname,get_defined_vars()
) for locally scoped
variables.Apart from being long and ugly, surely that is horribly inefficient.
No need to use @.
True. And I don't think anybody is. We all know @ is dangerous and nasty
and don't use it. We're not seeking an alternative to @, we're seeking
an alternative to repeating ourselves by using
isset()/array_key_exists()/is_null() as well as the value being tested.But we don't want to do this in a blanket way similar to @ where a whole
bunch of notices are suppressed. We want to specify precisely where
missing values are allowable by indicating exactly which array index
lookups may silently fail (and evaluate to null).Basically we don't want to make again the mistake that @ was.
Are they attempting to determine the existence of a variable/index
entry or are they attempting to determine if the variable/element is
null.For me, existence and nullness are basically the same, and I think this
is the common case. The whole point of being able to set something to
null is to have a 'value' to represent 'unsetness'. This is why I think
solving the conditional problem should use a !==null test. That gives
the flexibility to use/pass null to represent 'unsetness' but doesn't
pick up zero, false, etc. like a boolean cast does. Using
array_key_exists()
would remove that flexibility and be less useful.As far as silencing notices goes, the rationale is that basically we
want to flag that 'null is OK, even if it's a fallback'. I.e. we don't
care whether a value is null because it was set to null, or because null
is a fallback because the variable was never defined. Either way, null
is OK, so don't tell me about it.The conditional side lets us handle nulls nicely by providing our own
defaults/fallbacks if it appears. The notice-suppression side lets us
say that null is OK, even if that null itself is a fallback for
'undefined'. Quite often they will be used in combination, but they are
independent.I always declare my variables. So, I don't want to use isset() as they
will be an incorrect test. I use
is_null()
. Specifically testing the
value. If I've made a mistake and NOT declared the variable (or made a
typo), I want to know. I don't want to hide it with isset()/empty().That's exactly why I think the conditional should use a !==null test,
not an isset() test.Ben.
Sometimes this is true, but sometimes not. For example, HTTP GET/POST interfaces
often have optional parameters. These need to be tested for, and often defaults
provided, to write solid code.
Saying you can always wrap it is like saying you can write your programs for a
Turing machine.
Also, not everyone is writing highly abstracted object-oriented code in PHP.
Ben.
arrays are intent for holding values, not for represent things so use objects for
that.
the need for array_key_exists/isset to check for the presence of an index is a
smell that you need to refactor your code for a different datatype.If you cannot change the array, you always can wrap it.
With good data abstractions the usage of array_key_exists/isset/empty is barely
reduced to the minimum.Martin Scotta
On Thu, Apr 14, 2011 at 10:12 AM, Ben Schmidt <mail_ben_schmidt@yahoo.com.au
mailto:mail_ben_schmidt@yahoo.com.au> wrote:There are two issues here. 1. Suppression of notice. I agree, it is best done only for array keys. It's not hard to initialise a variable with $var=null at the beginning of a code block to avoid such a notice, and that is the appropriate way to do it for variables. 2. Offering a shortcut for the common idiom isset($x) ? $x : $y in line with the DRY design principle. A notice would never be emitted here in any case. The problem is that this idiom is still in wide use despite the shortcut ternary operator already provided, because an isset() check is different to a boolean cast. Some thoughts: - The actual intent of 2. is probably $x!==null ? $x : $y i.e. it's not about suppressing notices at all, but about offering a default value, and the idiom quite probably only uses isset() because it predated null in the language. - If we view 2. in this way, the two problems are independent, and it seems to me it would be best to solve them independently, rather than with a single operator. So, I suggest: 1. An array lookup mechanism that suppresses the notice for undefined keys. It would work the same as regular array index lookups except that the notice for undefined keys (and only for undefined keys) would not be generated (it would not just be hidden, but would never be even generated). http://news.php.net/php.internals/51877 array_key_exists($key, $array) for arrays array_key_exists($varname, `get_defined_vars()`) for locally scoped variables. Apart from being long and ugly, surely that is horribly inefficient. No need to use @. True. And I don't think anybody is. We all know @ is dangerous and nasty and don't use it. We're not seeking an alternative to @, we're seeking an alternative to repeating ourselves by using isset()/array_key_exists()/is_null() as well as the value being tested. But we don't want to do this in a blanket way similar to @ where a whole bunch of notices are suppressed. We want to specify precisely where missing values are allowable by indicating exactly which array index lookups may silently fail (and evaluate to null). Basically we don't want to make again the mistake that @ was. Are they attempting to determine the existence of a variable/index entry or are they attempting to determine if the variable/element is null. For me, existence and nullness are basically the same, and I think this is the common case. The whole point of being able to set something to null is to have a 'value' to represent 'unsetness'. This is why I think solving the conditional problem should use a !==null test. That gives the flexibility to use/pass null to represent 'unsetness' but doesn't pick up zero, false, etc. like a boolean cast does. Using `array_key_exists()` would remove that flexibility and be less useful. As far as silencing notices goes, the rationale is that basically we want to flag that 'null is OK, even if it's a fallback'. I.e. we don't care whether a value is null because it was set to null, or because null is a fallback because the variable was never defined. Either way, null is OK, so don't tell me about it. The conditional side lets us handle nulls nicely by providing our own defaults/fallbacks if it appears. The notice-suppression side lets us say that null is OK, even if that null itself is a fallback for 'undefined'. Quite often they will be used in combination, but they are independent. I always declare my variables. So, I don't want to use isset() as they will be an incorrect test. I use `is_null()`. Specifically testing the value. If I've made a mistake and NOT declared the variable (or made a typo), I want to know. I don't want to hide it with isset()/empty(). That's exactly why I think the conditional should use a !==null test, not an isset() test. Ben.
Trying to summarize this discussion... I think we can all agree that the
main problem is "code duplication for array access when parameters are
possibly not existing". I think we all can also agree that @ can be both
used properly and misused - and it is a blunt tool and not a nice solution
to the previously stated problem.
Some suggested that the ternary if comparison should suppress the notice
automatically. This would break existing code and also be confusing since
people expect a ternary if and normal if to work the same way.
Some suggested ?? as an array access operator that suppresses the notice and
has 3 variants: A: nothing specified - uses null as default, B: has default
specified, C: returns X if index exists or Y if index doesn't exist. This
effectively solves the code duplication problem and is a shortcut for saying
"the array index may or may not exist".
One person said that the relation between ? and ?? and == and === would make
the operator non-intuitive. Other people disagreed and claimed the opposite.
So basically the discussion now is what exact characters that should be used
to represent this operator? I really hope we can get this implemented
quickly... I worked with $_POST yesterday and I could really use that ??
operator.
~Hannes
Trying to summarize this discussion... I think we can all agree that the
main problem is "code duplication for array access when parameters are
possibly not existing".
For me the problem is 'code duplication when a value might be null'
(whether an array, variable or something else, and regardless of whether
it was set to null, or not defined at all).
I think we all can also agree that @ can be both used properly and
misused - and it is a blunt tool and not a nice solution to the
previously stated problem.
Yes.
Some suggested that the ternary if comparison should suppress the notice
automatically. This would break existing code and also be confusing since
people expect a ternary if and normal if to work the same way.
Yes.
Some suggested ?? as an array access operator that suppresses the notice and
has 3 variants: A: nothing specified - uses null as default, B: has default
specified, C: returns X if index exists or Y if index doesn't exist. This
effectively solves the code duplication problem and is a shortcut for saying
"the array index may or may not exist".
This only works if the test is made an isset() kind of test. If it
remains a boolean cast, it doesn't help much. (Or at least it doesn't
help me much.)
I also think it's a bit too blunt. In all but the simplest expressions
in the condition, desired notices could be silenced. I like the idea of
being able to specify exactly which array lookups should be silenced.
It also doesn't help the people who want an isset() style test, but
without the notice suppression, and I think there are a few people in
that category.
One person said that the relation between ? and ?? and == and === would make
the operator non-intuitive. Other people disagreed and claimed the opposite.So basically the discussion now is what exact characters that should be used
to represent this operator? I really hope we can get this implemented
quickly... I worked with $_POST yesterday and I could really use that ??
operator.
I still don't think we've reached agreement on exactly what we need.
Your summary seems to me to be of some of the earliest and least
developed ideas. I think the discussion has moved in a number of
interesting directions since then and we should draw on that later work.
Ben.
I can agree that implementing ?? with isset() and not array_key_exists()
would be acceptable... but empty() is a blunt compromise and much less
used... The general problem is the notice being thrown when array indexes
doesn't exist - which results in code duplication when you deal with it
nicely. empty() tries to be a generic solution but there will always be
people that has some other special definition of "emptiness" like "array
that contains a single null value" and they need to write the code that
defines that particular comparison anyway.
You can't have a solution that makes everything easier for everyone so let's
solve one thing at a time and start with the most generic problem
specifically and not all minor problems that happens to partially intersect
that one.
~Hannes
Trying to summarize this discussion... I think we can all agree that the
main problem is "code duplication for array access when parameters are
possibly not existing".For me the problem is 'code duplication when a value might be null'
(whether an array, variable or something else, and regardless of whether
it was set to null, or not defined at all).I think we all can also agree that @ can be both used properly and
misused - and it is a blunt tool and not a nice solution to the
previously stated problem.Yes.
Some suggested that the ternary if comparison should suppress the notice
automatically. This would break existing code and also be confusing since
people expect a ternary if and normal if to work the same way.Yes.
Some suggested ?? as an array access operator that suppresses the notice
and
has 3 variants: A: nothing specified - uses null as default, B: has
default
specified, C: returns X if index exists or Y if index doesn't exist. This
effectively solves the code duplication problem and is a shortcut for
saying
"the array index may or may not exist".This only works if the test is made an isset() kind of test. If it
remains a boolean cast, it doesn't help much. (Or at least it doesn't
help me much.)I also think it's a bit too blunt. In all but the simplest expressions
in the condition, desired notices could be silenced. I like the idea of
being able to specify exactly which array lookups should be silenced.It also doesn't help the people who want an isset() style test, but
without the notice suppression, and I think there are a few people in
that category.One person said that the relation between ? and ?? and == and === would
make
the operator non-intuitive. Other people disagreed and claimed the
opposite.So basically the discussion now is what exact characters that should be
used
to represent this operator? I really hope we can get this implemented
quickly... I worked with $_POST yesterday and I could really use that ??
operator.I still don't think we've reached agreement on exactly what we need.
Your summary seems to me to be of some of the earliest and least
developed ideas. I think the discussion has moved in a number of
interesting directions since then and we should draw on that later work.Ben.
I agree empty() is basically useless. We already have the existing
ternary operator (and its shortcut) to do a boolean test, which is
basically the same as empty().
The way I see it, if rather than making an isset() operator that
suppresses errors and offers a default, we added both a !==null operator
for the default, and a separate error-suppression mechanism, people
could use the suppression mechanism with the existing boolean ternary
operator if they want to (I would find that useful, as I often write
things such as isset($a[$k])&&$a[$k]?"yes":"no" for that kind of thing),
and use the !==null operator without error suppression (I would find
that useful, too, to avoid typos).
In summary, with two separate, simpler mechanisms, we could tackle these
paradigms (I have used @[...] for undefined index error-suppression and
$: for !==null default):
-
$v!==null ? $v : "default"
$v $: "default"
with notice -
$a[$k]!==null ? $a[$k] : "default"
$a[$k] $: "default"
with notice -
isset($a[$k]) ? $a[$k] : "default"
$a@[$k] $: "default"
without notice -
isset($a[$k]) ? $a[$k] : null
$a@[$k]
without notice -
isset($a[$k])&&!!$a[$k]
!!$a@[$k]
without notice -
isset($a[$k])&&$a[$k] ? "yes" : "no"
$a@[$k] ? "yes" : "no"
without notice
With !==null assignment (I've used $:=) we could also have:
- if (!isset($a[$k])) $a[$k] = "default";
$a[$k] $:= "default";
without notice (the LHS of an assignment never generates one)
To avoid encouraging poor coding, we would deliberately not have:
- isset($v) ? $v : "default"
$@v $: "default"
without notice
But it is a cinch to add it if enough people want it, and doing so
wouldn't affect anyone who didn't want to use it--no backward
compatibility problems on the horizon. I think that's the clincher. If
we just add an isset() operator (that suppresses errors, and gives a
default), we only get paradigms 3, 4, 5 and maybe 7, but worse, if we
want to add any of the others later, we need to design more complicated
new operators, or break backward compatibility, not just extend what we
have.
I personally use 1, 3, 5 and 6 quite often, and 2 and 7 occasionally, so
I see great value in being able to do them all, not just the restricted
set.
What numbers are others interested in being able to solve?
What do others think about the future-proofing issue?
Ben.
I can agree that implementing ?? with isset() and not
array_key_exists()
would be
acceptable... but empty() is a blunt compromise and much less used... The general
problem is the notice being thrown when array indexes doesn't exist - which
results in code duplication when you deal with it nicely. empty() tries to be a
generic solution but there will always be people that has some other special
definition of "emptiness" like "array that contains a single null value" and they
need to write the code that defines that particular comparison anyway.You can't have a solution that makes everything easier for everyone so let's solve
one thing at a time and start with the most generic problem specifically and not
all minor problems that happens to partially intersect that one.~Hannes
On 14 April 2011 16:26, Ben Schmidt <mail_ben_schmidt@yahoo.com.au
mailto:mail_ben_schmidt@yahoo.com.au> wrote:Trying to summarize this discussion... I think we can all agree that the main problem is "code duplication for array access when parameters are possibly not existing". For me the problem is 'code duplication when a value might be null' (whether an array, variable or something else, and regardless of whether it was set to null, or not defined at all). I think we all can also agree that @ can be both used properly and misused - and it is a blunt tool and not a nice solution to the previously stated problem. Yes. Some suggested that the ternary if comparison should suppress the notice automatically. This would break existing code and also be confusing since people expect a ternary if and normal if to work the same way. Yes. Some suggested ?? as an array access operator that suppresses the notice and has 3 variants: A: nothing specified - uses null as default, B: has default specified, C: returns X if index exists or Y if index doesn't exist. This effectively solves the code duplication problem and is a shortcut for saying "the array index may or may not exist". This only works if the test is made an isset() kind of test. If it remains a boolean cast, it doesn't help much. (Or at least it doesn't help me much.) I also think it's a bit too blunt. In all but the simplest expressions in the condition, desired notices could be silenced. I like the idea of being able to specify exactly which array lookups should be silenced. It also doesn't help the people who want an isset() style test, but without the notice suppression, and I think there are a few people in that category. One person said that the relation between ? and ?? and == and === would make the operator non-intuitive. Other people disagreed and claimed the opposite. So basically the discussion now is what exact characters that should be used to represent this operator? I really hope we can get this implemented quickly... I worked with $_POST yesterday and I could really use that ?? operator. I still don't think we've reached agreement on exactly what we need. Your summary seems to me to be of some of the earliest and least developed ideas. I think the discussion has moved in a number of interesting directions since then and we should draw on that later work. Ben.
I like this - especially .7 and .8.
The $: is intuitive because it looks like a variable that doesn't contain
anything and the : specifies what comes then.
However I'd rather use the "?" character than "@" for the simple reason that
I see this as a more careful way to access an array and not as an "error
silencing operation". E.g. it's not implemented by setting error reporting
to 0 but rather... to illustrate it, let's pretend that the PHP array where
implemented by the ArrayAccess class. The "offsetGet" signature would be
changed too take an extra argument:
offsetGet( mixed $offset, boolean $unset_defined )
Normal array access would have $unset_defined set to false, but an access
like $a?[$k] would set it to true (the ?[ modifier) would make
$unset_defined become true so:
if (!$unset_defined) {
\trigger_error("Undefined index: $offset", \E_NOTICE);
}
return null;
Of course, in userland, one could implement ArrayAccess and exploit the
$unset_defined parameter in any other way. Let's for example say that you
implement it to make an ArrayAccess class that maps data to the file system,
using the file name as a $offset. If $unset_defined is set to false you
would just go ahead and try to open the file in question, possibly raising a
file operation error - however if $unset_defined is true you might make a
careful check before opening the file to see if it really exist. If error
silencing would be used instead - other errors like file permission errors
could incorrectly be silenced - but $unset_defined specifically checks if
the file exist or not before access. So it could affect the read operation
itself - and I hope that explains why It's more than just "error silencing".
~Hannes
I agree empty() is basically useless. We already have the existing
ternary operator (and its shortcut) to do a boolean test, which is
basically the same as empty().The way I see it, if rather than making an isset() operator that
suppresses errors and offers a default, we added both a !==null operator
for the default, and a separate error-suppression mechanism, people
could use the suppression mechanism with the existing boolean ternary
operator if they want to (I would find that useful, as I often write
things such as isset($a[$k])&&$a[$k]?"yes":"no" for that kind of thing),
and use the !==null operator without error suppression (I would find
that useful, too, to avoid typos).In summary, with two separate, simpler mechanisms, we could tackle these
paradigms (I have used @[...] for undefined index error-suppression and
$: for !==null default):
$v!==null ? $v : "default"
$v $: "default"
with notice$a[$k]!==null ? $a[$k] : "default"
$a[$k] $: "default"
with noticeisset($a[$k]) ? $a[$k] : "default"
$a@[$k] $: "default"
without noticeisset($a[$k]) ? $a[$k] : null
$a@[$k]
without noticeisset($a[$k])&&!!$a[$k]
!!$a@[$k]
without noticeisset($a[$k])&&$a[$k] ? "yes" : "no"
$a@[$k] ? "yes" : "no"
without noticeWith !==null assignment (I've used $:=) we could also have:
- if (!isset($a[$k])) $a[$k] = "default";
$a[$k] $:= "default";
without notice (the LHS of an assignment never generates one)To avoid encouraging poor coding, we would deliberately not have:
- isset($v) ? $v : "default"
$@v $: "default"
without noticeBut it is a cinch to add it if enough people want it, and doing so
wouldn't affect anyone who didn't want to use it--no backward
compatibility problems on the horizon. I think that's the clincher. If
we just add an isset() operator (that suppresses errors, and gives a
default), we only get paradigms 3, 4, 5 and maybe 7, but worse, if we
want to add any of the others later, we need to design more complicated
new operators, or break backward compatibility, not just extend what we
have.I personally use 1, 3, 5 and 6 quite often, and 2 and 7 occasionally, so
I see great value in being able to do them all, not just the restricted
set.What numbers are others interested in being able to solve?
What do others think about the future-proofing issue?
Ben.
I can agree that implementing ?? with isset() and not
array_key_exists()
would be
acceptable... but empty() is a blunt compromise and much less used... The
general
problem is the notice being thrown when array indexes doesn't exist -
which
results in code duplication when you deal with it nicely. empty() tries to
be a
generic solution but there will always be people that has some other
special
definition of "emptiness" like "array that contains a single null value"
and they
need to write the code that defines that particular comparison anyway.You can't have a solution that makes everything easier for everyone so
let's solve
one thing at a time and start with the most generic problem specifically
and not
all minor problems that happens to partially intersect that one.~Hannes
On 14 April 2011 16:26, Ben Schmidt <mail_ben_schmidt@yahoo.com.au
mailto:mail_ben_schmidt@yahoo.com.au> wrote:Trying to summarize this discussion... I think we can all agree
that the
main problem is "code duplication for array access when parameters
are
possibly not existing".For me the problem is 'code duplication when a value might be null'
(whether an array, variable or something else, and regardless of
whether
it was set to null, or not defined at all).I think we all can also agree that @ can be both used properly and misused - and it is a blunt tool and not a nice solution to the previously stated problem.
Yes.
Some suggested that the ternary if comparison should suppress the
notice
automatically. This would break existing code and also be confusing
since
people expect a ternary if and normal if to work the same way.Yes.
Some suggested ?? as an array access operator that suppresses the
notice and
has 3 variants: A: nothing specified - uses null as default, B: has
default
specified, C: returns X if index exists or Y if index doesn't
exist. This
effectively solves the code duplication problem and is a shortcut
for saying
"the array index may or may not exist".This only works if the test is made an isset() kind of test. If it
remains a boolean cast, it doesn't help much. (Or at least it doesn't
help me much.)I also think it's a bit too blunt. In all but the simplest expressions
in the condition, desired notices could be silenced. I like the idea of
being able to specify exactly which array lookups should be silenced.It also doesn't help the people who want an isset() style test, but
without the notice suppression, and I think there are a few people in
that category.One person said that the relation between ? and ?? and == and ===
would make
the operator non-intuitive. Other people disagreed and claimed the
opposite.So basically the discussion now is what exact characters that
should be used
to represent this operator? I really hope we can get this
implemented
quickly... I worked with $_POST yesterday and I could really use
that ??
operator.I still don't think we've reached agreement on exactly what we need.
Your summary seems to me to be of some of the earliest and least
developed ideas. I think the discussion has moved in a number of
interesting directions since then and we should draw on that later
work.Ben.
That sounds fine to me, and the extension to ArrayAccess is really
clever. I agree that 'take more care' is a better way to view the array
access. It means both the array access should be more careful (to check
and avoid errors, rather than just proceed), and also the 'caller'
should be more careful by being more prepared to accept null values. I
don't know if ? is the best character to represent this, but I don't
really care--I'd just be glad of the functionality. Perhaps ! is another
possibility worth considering, though.
If 7 and 8 are included, there are actually then four new constructs:
- $: operator that evaluates to LHS if !==null, RHS otherwise
- $:= assignment only if the LHS is null or undefined (return final LHS)
- ?[...] array index lookup without notice (and ArrayAccess extension)
- $?name variable lookup without notice
I'd be happy with that. The only one I'm not so sure about is the last
one.
Ben.
(P.S. My earlier example for 7 was slightly wrong; it should require
what is now the ?[...] construct to avoid the notice; other compound
assignment operators like += produce notices. I've modified it below.)
I like this - especially .7 and .8.
The $: is intuitive because it looks like a variable that doesn't contain
anything and the : specifies what comes then.However I'd rather use the "?" character than "@" for the simple reason that
I see this as a more careful way to access an array and not as an "error
silencing operation". E.g. it's not implemented by setting error reporting
to 0 but rather... to illustrate it, let's pretend that the PHP array where
implemented by the ArrayAccess class. The "offsetGet" signature would be
changed too take an extra argument:offsetGet( mixed $offset, boolean $unset_defined )
Normal array access would have $unset_defined set to false, but an access
like $a?[$k] would set it to true (the ?[ modifier) would make
$unset_defined become true so:if (!$unset_defined) {
\trigger_error("Undefined index: $offset", \E_NOTICE);
}
return null;Of course, in userland, one could implement ArrayAccess and exploit the
$unset_defined parameter in any other way. Let's for example say that you
implement it to make an ArrayAccess class that maps data to the file system,
using the file name as a $offset. If $unset_defined is set to false you
would just go ahead and try to open the file in question, possibly raising a
file operation error - however if $unset_defined is true you might make a
careful check before opening the file to see if it really exist. If error
silencing would be used instead - other errors like file permission errors
could incorrectly be silenced - but $unset_defined specifically checks if
the file exist or not before access. So it could affect the read operation
itself - and I hope that explains why It's more than just "error silencing".~Hannes
I agree empty() is basically useless. We already have the existing
ternary operator (and its shortcut) to do a boolean test, which is
basically the same as empty().The way I see it, if rather than making an isset() operator that
suppresses errors and offers a default, we added both a !==null operator
for the default, and a separate error-suppression mechanism, people
could use the suppression mechanism with the existing boolean ternary
operator if they want to (I would find that useful, as I often write
things such as isset($a[$k])&&$a[$k]?"yes":"no" for that kind of thing),
and use the !==null operator without error suppression (I would find
that useful, too, to avoid typos).In summary, with two separate, simpler mechanisms, we could tackle these
paradigms (I have used @[...] for undefined index error-suppression and
$: for !==null default):
$v!==null ? $v : "default"
$v $: "default"
with notice$a[$k]!==null ? $a[$k] : "default"
$a[$k] $: "default"
with noticeisset($a[$k]) ? $a[$k] : "default"
$a@[$k] $: "default"
without noticeisset($a[$k]) ? $a[$k] : null
$a@[$k]
without noticeisset($a[$k])&&!!$a[$k]
!!$a@[$k]
without noticeisset($a[$k])&&$a[$k] ? "yes" : "no"
$a@[$k] ? "yes" : "no"
without noticeWith !==null assignment (I've used $:=) we could also have:
- if (!isset($a[$k])) $a[$k] = "default";
$a@[$k] $:= "default";
without noticeTo avoid encouraging poor coding, we would deliberately not have:
- isset($v) ? $v : "default"
$@v $: "default"
without noticeBut it is a cinch to add it if enough people want it, and doing so
wouldn't affect anyone who didn't want to use it--no backward
compatibility problems on the horizon. I think that's the clincher. If
we just add an isset() operator (that suppresses errors, and gives a
default), we only get paradigms 3, 4, 5 and maybe 7, but worse, if we
want to add any of the others later, we need to design more complicated
new operators, or break backward compatibility, not just extend what we
have.I personally use 1, 3, 5 and 6 quite often, and 2 and 7 occasionally, so
I see great value in being able to do them all, not just the restricted
set.What numbers are others interested in being able to solve?
What do others think about the future-proofing issue?
Ben.
On Thu, Apr 14, 2011 at 10:05 AM, Hannes Landeholm landeholm@gmail.comwrote:
Trying to summarize this discussion... I think we can all agree that the
main problem is "code duplication for array access when parameters are
possibly not existing". I think we all can also agree that @ can be both
used properly and misused - and it is a blunt tool and not a nice solution
to the previously stated problem.Some suggested that the ternary if comparison should suppress the notice
automatically. This would break existing code and also be confusing since
people expect a ternary if and normal if to work the same way.Some suggested ?? as an array access operator that suppresses the notice
and
has 3 variants: A: nothing specified - uses null as default, B: has default
specified, C: returns X if index exists or Y if index doesn't exist. This
effectively solves the code duplication problem and is a shortcut for
saying
"the array index may or may not exist".One person said that the relation between ? and ?? and == and === would
make
the operator non-intuitive. Other people disagreed and claimed the
opposite.So basically the discussion now is what exact characters that should be
used
to represent this operator? I really hope we can get this implemented
quickly... I worked with $_POST yesterday and I could really use that ??
operator.~Hannes
There was also my suggestion of a "checked ternary" operator [see my
previous email in this thread.] Backwards compatible, practical, and simple.
Adam
--
Nephtali: A simple, flexible, fast, and security-focused PHP framework
http://nephtaliproject.com
There was also my suggestion of a "checked ternary" operator [see my
previous email in this thread.] Backwards compatible, practical, and simple.
It doesn't address the main issues of code duplication and nullness
checking, IMHO, so isn't a contender. Even though it's simple and
compatible, it is only practical in a handful of cases.
Ben.
On Fri, Apr 15, 2011 at 8:46 PM, Ben Schmidt
mail_ben_schmidt@yahoo.com.auwrote:
There was also my suggestion of a "checked ternary" operator [see my
previous email in this thread.] Backwards compatible, practical, and
simple.It doesn't address the main issues of code duplication and nullness
checking, IMHO, so isn't a contender. Even though it's simple and
compatible, it is only practical in a handful of cases.
I believe describing nullness checking as a "main" issue is a rather strong
assessment.
David's original message and patch (and several of the suggestions in this
thread) speak to the issues with boilerplate code needed to avoid warnings
elicited when accessing a non-existant array key. This is the type of code
that you tend to see out in the wild that David and others have cited as a
pain:
$var = (isset($arr['key'])) ? $arr['key'] : 'empty';
Additionally, it might not be as succinct as you prefer, but surely
$var = $arr['key'] ?? : 'empty';
is a significant improvement over the current means and does in fact remove
redundant code.
Now, perhaps there are other options that are better. This is an interesting
dialogue to follow, and I've enjoyed the reading. However, after viewing the
other proposals thus far, my preference would still be for the checked
ternary operator.
Respectfully,
Adam
--
Nephtali: A simple, flexible, fast, and security-focused PHP framework
http://nephtaliproject.com
On Sat, 16 Apr 2011 03:42:11 +0200, Adam Richardson simpleshot@gmail.com
wrote:
On Fri, Apr 15, 2011 at 8:46 PM, Ben Schmidt
mail_ben_schmidt@yahoo.com.auwrote:There was also my suggestion of a "checked ternary" operator [see my
previous email in this thread.] Backwards compatible, practical, and
simple.It doesn't address the main issues of code duplication and nullness
checking, IMHO, so isn't a contender. Even though it's simple and
compatible, it is only practical in a handful of cases.I believe describing nullness checking as a "main" issue is a rather
strong
assessment.
I agree. To me, nullness checking is not interesting at all.
$var = $arr['key'] ?? : 'empty';
is a significant improvement over the current means and does in fact
remove
redundant code.
If I understood it correctly, this is the essense of what I want. Compared
to the original description of checked ternary I strongly object to this
working on non-arrays.
But given that constraint, my vote goes to the checked ternary operator as
well.
--
Ole Markus With
I believe describing nullness checking as a "main" issue is a rather
strong assessment.
I don't think so, obviously. :-)
$var = (isset($arr['key'])) ? $arr['key'] : 'empty';
Nullness checking is half of what that code does, isn't it? Otherwise it
would be (isset($arr['key']) && $arr['key']), right?
Additionally, it might not be as succinct as you prefer, but surely
$var = $arr['key'] ?? : 'empty';
is a significant improvement over the current means and does in fact remove
redundant code.
But it's not equivalent to your code snippet above, is it?
My vote's still with the line of discussion Hannes and I were on, of
separate 'careful array index lookup' and 'default-when-null'
operator(s). Partly because I think that approach can help everyone,
whereas the checked ternary operator really doesn't help me much at all.
Not sure if that's selfish or not. :-)
I'll try to stay a bit quieter for a bit, if I can manage it.... I've
said a lot today.
Returning due respect,
Ben.
$var = $arr['key'] ?? : 'empty';
Also note this is possible with the recent proposal Hannes and I were
discussing. It simply looks like
$var = $arr?['key'] ?: 'empty';
The ?[ avoids notices and the ?: works as it always has.
Ben.
Ben Schmidt wrote:
$var = $arr['key'] ?? : 'empty';
Also note this is possible with the recent proposal Hannes and I were
discussing. It simply looks like$var = $arr?['key'] ?: 'empty';
The ?[ avoids notices and the ?: works as it always has.
Ben.
If it was going to be ?[, I'd much prefer $arr['key'?]. It was proposed as
$arr[?'key'] instead to avoid a backtracking (would that really be
noticeable?
I'd prefer readibility), but ?[ would have the same problem.
On Thu, 14 Apr 2011 16:05:45 +0200, Hannes Landeholm landeholm@gmail.com
wrote:
So basically the discussion now is what exact characters that should be
used
to represent this operator? I really hope we can get this implemented
quickly... I worked with $_POST yesterday and I could really use that ??
operator.
When it comes to $_POST you probably want to use filter_input instead.
Cheers,
Ole Markus With
Nope. I prefer to treat "invalid" or "non existing" basic types as them
being set to a default value. This makes the input handler very robust and I
don't have to waste time by writing code that handles failed validation.
For example if I read an integer from $_POST I'd simply write:
$value = \intval(@$_POST["field"]);
(or a boolean:)
$value = (@$_POST["field"] == "set");
I'd prefer this syntax though:
$value = \intval($_POST["field"]??);
..simply because it's a more precise expression and no notice is generated
and have to be ignored when running the custom error handler - so it should
be faster too.
~Hannes
On Thu, 14 Apr 2011 16:05:45 +0200, Hannes Landeholm landeholm@gmail.com
wrote:So basically the discussion now is what exact characters that should be
used
to represent this operator? I really hope we can get this implemented
quickly... I worked with $_POST yesterday and I could really use that ??
operator.When it comes to $_POST you probably want to use filter_input instead.
Cheers,
Ole Markus With
Some suggested that the ternary if comparison should suppress the notice
automatically. This would break existing code and also be confusing since
people expect a ternary if and normal if to work the same way.Some suggested ?? as an array access operator that suppresses the notice and
has 3 variants: A: nothing specified - uses null as default, B: has default
specified, C: returns X if index exists or Y if index doesn't exist. This
effectively solves the code duplication problem and is a shortcut for saying
"the array index may or may not exist".One person said that the relation between ? and ?? and == and === would make
the operator non-intuitive. Other people disagreed and claimed the opposite.So basically the discussion now is what exact characters that should be used
to represent this operator? I really hope we can get this implemented
quickly... I worked with $_POST yesterday and I could really use that ??
operator.
Hi,
I must say that the prospect of yet more new syntax is scary. It
really looks like Perl, and I wouldn't have the slightest clue what it
meant if I'd missed the release notes.
I've pined for something like coalesce($_GET['foo'], $defaults['foo'],
- for years, and I think that style is far more in keeping with the
PHP ethos, and far more readily understandable than this suggested new
syntax.
If I've missed some argument against this then please correct me.
Regards,
Arpad
I've pined for something like coalesce($_GET['foo'], $defaults['foo'],
- for years, and I think that style is far more in keeping with the
PHP ethos, and far more readily understandable than this suggested new
syntax.
To elaborate, I'd probably think this code was an unlikely series of
typos, or an encoding error:
$var = $_GET[?'var'] $: $_POST[?'var'] $: 'default';
But as a PHP coder, I'm quite familiar with how coalesce() works.
Regards,
Arpad
Some suggested that the ternary if comparison should suppress the notice
automatically. This would break existing code and also be confusing since
people expect a ternary if and normal if to work the same way.Some suggested ?? as an array access operator that suppresses the notice and
has 3 variants: A: nothing specified - uses null as default, B: has default
specified, C: returns X if index exists or Y if index doesn't exist. This
effectively solves the code duplication problem and is a shortcut for saying
"the array index may or may not exist".One person said that the relation between ? and ?? and == and === would make
the operator non-intuitive. Other people disagreed and claimed the opposite.So basically the discussion now is what exact characters that should be used
to represent this operator? I really hope we can get this implemented
quickly... I worked with $_POST yesterday and I could really use that ??
operator.
Hi,I must say that the prospect of yet more new syntax is scary. It
really looks like Perl, and I wouldn't have the slightest clue what it
meant if I'd missed the release notes.I've pined for something like coalesce($_GET['foo'], $defaults['foo'],
- for years, and I think that style is far more in keeping with the
PHP ethos, and far more readily understandable than this suggested new
syntax.If I've missed some argument against this then please correct me.
Regards,
Arpad
What does coalesce() do?
If I'm guessing correctly, would proposal #2 that Rune Kaagaard put up
solve that for you?
https://gist.github.com/909711
Cheers,
David
What does coalesce() do?
If I'm guessing correctly, would proposal #2 that Rune Kaagaard put up
solve that for you?
https://gist.github.com/909711Cheers,
David
It was discussed in a separate thread.
generally it would do the same as in SQL, return the first non-null value
from the arguments.
and it wouldn't introduce a new syntax, but I guess that it should be added
as a language construct.
Tyrael
What does coalesce() do?
If I'm guessing correctly, would proposal #2 that Rune Kaagaard put up
solve that for you?
https://gist.github.com/909711
Rune's proposal #2, extending func_get_arg()
, is impossible to
implement/would not work.
His proposal #3, which is more like coalesce(), suffers from the
drawbacks/problems of coalesce() which I discussed in a recent post
(though you can see Rune has some workarounds/hacks to deal with some of
the problems).
IMHO, his proposal #1 is the only real contender. However, I believe it
conflates two problems which others do not want conflated. He briefly
dismisses the [?] syntax, because it addresses what he sees as a
different problem. However, that different problem is really part of his
problem. My contention is that the two parts of his problem are better
solved independently (notice-suppression separately to finding an
isset/!empty value), and furthermore that one of the two versions of his
problem is already partially solved and should be reused, not reinvented
(existing ternary operator for a !empty check).
Ben.
I must say that the prospect of yet more new syntax is scary. It
really looks like Perl, and I wouldn't have the slightest clue what it
meant if I'd missed the release notes.
I agree it looks a little bit strange. I think that's partly a benefit:
it doesn't look like something so that you assume you know what it means
but get it wrong; it drives you to the manual to find out what it means.
I've pined for something like coalesce($_GET['foo'], $defaults['foo'],
- for years, and I think that style is far more in keeping with the
PHP ethos, and far more readily understandable than this suggested new
syntax.
As I see it, there a are a number of drawbacks to this approach.
-
It doesn't help with a bunch of common paradigms. For instance,
$a['k'] = isset($a['k']) ? $a['k'] : "default" -
I think it's too 'blunt'. For instance, if you write
coalesce($_GET['foo'], $defaults['foo']) you probably actually do want
to see a notice if $defaults['foo'] is not defined. But if you include
42 as a last resort default, you of course do not. Treating the last
argument of a variable number of arguments differently is difficult and
unintuitive, and even that would not always be desired anyway.
Furthermore with something like $o->foo are you interested in whether $o
is defined or not, or only in whether $o->foo is null? Particularly if
you have many arguments, if you don't have tests that give full coverage
of all the possibilities for each argument, notices very helpful for
debugging could be easily undesirably silenced. -
It can't be equivalent to isset() on every argument. isset() is very
restricted in what it can operate on. For instance, isset(42) is not
legal; nor is isset(some_function()); and so on. This kind of thing
would be important to allow in coalescse(), but it would make things
difficult to parse: to have any chance of making it work, you'd need to
parse each item as if in isset(), and if it fails, backtrack and parse
it as an expression, and then the coalesce() operation(s) (it could not
be a function) would have to be able to deal with both scenarios for
every argument. Nasty. -
It's misleading regarding side effects because it looks like a
function. If coalesce() were a function and you wrote
coalesce($_GET['foo'],get_default('foo')), you would expect
get_default() to be called before coalesce() and regardless of the state
of $_GET['foo']. If it actually behaved like that, it would render
coalesce() somewhat less useful, but it would be misleading if it didn't
work like that. isset() gets away with this because it is restricted and
only has one argument, but coalesce() wouldn't.
To avoid/solve these problems:
-
Support missing paradigms: I suppose adding coalesce_set() and other
constructs could conceptually provide for that. -
Less blunt: You really need some kind of notice-free array index
and/or variable lookup that can pinpoint the notice to be omitted. A
function-like syntax doesn't really work: isset(), though better than
coalesce(), is still too blunt for many use cases. It's also very
verbose. Nobody wants to write
coalesce(ifset($_GET['foo']),ifset($defaults['foo']),42)
IMHO, it is better to have
coalesce($_GET[?'foo'],$defaults[?'foo'],42)
even though it's not 'familiar'. -
Avoid isset()-like restrictions: You can use a !==null test that can
be applied to any expression; if problem 1 is solved satisfactorily, an
expression will simply be evaluated without generating a notice, and
then compared to null. -
Sensible side-effect behaviour: To get that, you really need an
operator (or other language construct), and a function-like syntax is
misleading. Although unfamiliar,
$_GET[?'foo'] $: $defaults[?'foo'] $: 42
is less misleading. It also extends nicely to the assignment paradigm as
$_GET[?'foo'] $:= $defaults[?'foo'] $: 42;
Ben.
what about something like this?
$_GET += array( 'key' => 42, 'other' => 'blablah' );
echo $_GET [ 'key' ];
and it's already available on you current instalation :)
Martin Scotta
On Fri, Apr 22, 2011 at 11:27 PM, Ben Schmidt <mail_ben_schmidt@yahoo.com.au
wrote:
I must say that the prospect of yet more new syntax is scary. It
really looks like Perl, and I wouldn't have the slightest clue what it
meant if I'd missed the release notes.I agree it looks a little bit strange. I think that's partly a benefit:
it doesn't look like something so that you assume you know what it means
but get it wrong; it drives you to the manual to find out what it means.I've pined for something like coalesce($_GET['foo'], $defaults['foo'],
- for years, and I think that style is far more in keeping with the
PHP ethos, and far more readily understandable than this suggested new
syntax.As I see it, there a are a number of drawbacks to this approach.
It doesn't help with a bunch of common paradigms. For instance,
$a['k'] = isset($a['k']) ? $a['k'] : "default"I think it's too 'blunt'. For instance, if you write
coalesce($_GET['foo'], $defaults['foo']) you probably actually do want
to see a notice if $defaults['foo'] is not defined. But if you include
42 as a last resort default, you of course do not. Treating the last
argument of a variable number of arguments differently is difficult and
unintuitive, and even that would not always be desired anyway.
Furthermore with something like $o->foo are you interested in whether $o
is defined or not, or only in whether $o->foo is null? Particularly if
you have many arguments, if you don't have tests that give full coverage
of all the possibilities for each argument, notices very helpful for
debugging could be easily undesirably silenced.It can't be equivalent to isset() on every argument. isset() is very
restricted in what it can operate on. For instance, isset(42) is not
legal; nor is isset(some_function()); and so on. This kind of thing
would be important to allow in coalescse(), but it would make things
difficult to parse: to have any chance of making it work, you'd need to
parse each item as if in isset(), and if it fails, backtrack and parse
it as an expression, and then the coalesce() operation(s) (it could not
be a function) would have to be able to deal with both scenarios for
every argument. Nasty.It's misleading regarding side effects because it looks like a
function. If coalesce() were a function and you wrote
coalesce($_GET['foo'],get_default('foo')), you would expect
get_default() to be called before coalesce() and regardless of the state
of $_GET['foo']. If it actually behaved like that, it would render
coalesce() somewhat less useful, but it would be misleading if it didn't
work like that. isset() gets away with this because it is restricted and
only has one argument, but coalesce() wouldn't.To avoid/solve these problems:
Support missing paradigms: I suppose adding coalesce_set() and other
constructs could conceptually provide for that.Less blunt: You really need some kind of notice-free array index
and/or variable lookup that can pinpoint the notice to be omitted. A
function-like syntax doesn't really work: isset(), though better than
coalesce(), is still too blunt for many use cases. It's also very
verbose. Nobody wants to write
coalesce(ifset($_GET['foo']),ifset($defaults['foo']),42)
IMHO, it is better to havecoalesce($_GET[?'foo'],$defaults[?'foo'],42)
even though it's not 'familiar'.
Avoid isset()-like restrictions: You can use a !==null test that can
be applied to any expression; if problem 1 is solved satisfactorily, an
expression will simply be evaluated without generating a notice, and
then compared to null.Sensible side-effect behaviour: To get that, you really need an
operator (or other language construct), and a function-like syntax is
misleading. Although unfamiliar,$_GET[?'foo'] $: $defaults[?'foo'] $: 42
is less misleading. It also extends nicely to the assignment paradigm as
$_GET[?'foo'] $:= $defaults[?'foo'] $: 42;Ben.
It's good for some situations, but there are plenty more where it doesn't cut it,
e.g. $_GET[?'foo'] $:= get_default_from_db('foo') $: "hard-coded".
Ben.
what about something like this?
$_GET += array( 'key' => 42, 'other' => 'blablah' );
echo $_GET [ 'key' ];
and it's already available on you current instalation :)
Martin Scotta
On Fri, Apr 22, 2011 at 11:27 PM, Ben Schmidt<mail_ben_schmidt@yahoo.com.au
wrote:
I must say that the prospect of yet more new syntax is scary. It
really looks like Perl, and I wouldn't have the slightest clue what it
meant if I'd missed the release notes.I agree it looks a little bit strange. I think that's partly a benefit:
it doesn't look like something so that you assume you know what it means
but get it wrong; it drives you to the manual to find out what it means.I've pined for something like coalesce($_GET['foo'], $defaults['foo'],
- for years, and I think that style is far more in keeping with the
PHP ethos, and far more readily understandable than this suggested new
syntax.As I see it, there a are a number of drawbacks to this approach.
It doesn't help with a bunch of common paradigms. For instance,
$a['k'] = isset($a['k']) ? $a['k'] : "default"I think it's too 'blunt'. For instance, if you write
coalesce($_GET['foo'], $defaults['foo']) you probably actually do want
to see a notice if $defaults['foo'] is not defined. But if you include
42 as a last resort default, you of course do not. Treating the last
argument of a variable number of arguments differently is difficult and
unintuitive, and even that would not always be desired anyway.
Furthermore with something like $o->foo are you interested in whether $o
is defined or not, or only in whether $o->foo is null? Particularly if
you have many arguments, if you don't have tests that give full coverage
of all the possibilities for each argument, notices very helpful for
debugging could be easily undesirably silenced.It can't be equivalent to isset() on every argument. isset() is very
restricted in what it can operate on. For instance, isset(42) is not
legal; nor is isset(some_function()); and so on. This kind of thing
would be important to allow in coalescse(), but it would make things
difficult to parse: to have any chance of making it work, you'd need to
parse each item as if in isset(), and if it fails, backtrack and parse
it as an expression, and then the coalesce() operation(s) (it could not
be a function) would have to be able to deal with both scenarios for
every argument. Nasty.It's misleading regarding side effects because it looks like a
function. If coalesce() were a function and you wrote
coalesce($_GET['foo'],get_default('foo')), you would expect
get_default() to be called before coalesce() and regardless of the state
of $_GET['foo']. If it actually behaved like that, it would render
coalesce() somewhat less useful, but it would be misleading if it didn't
work like that. isset() gets away with this because it is restricted and
only has one argument, but coalesce() wouldn't.To avoid/solve these problems:
Support missing paradigms: I suppose adding coalesce_set() and other
constructs could conceptually provide for that.Less blunt: You really need some kind of notice-free array index
and/or variable lookup that can pinpoint the notice to be omitted. A
function-like syntax doesn't really work: isset(), though better than
coalesce(), is still too blunt for many use cases. It's also very
verbose. Nobody wants to write
coalesce(ifset($_GET['foo']),ifset($defaults['foo']),42)
IMHO, it is better to havecoalesce($_GET[?'foo'],$defaults[?'foo'],42)
even though it's not 'familiar'.
Avoid isset()-like restrictions: You can use a !==null test that can
be applied to any expression; if problem 1 is solved satisfactorily, an
expression will simply be evaluated without generating a notice, and
then compared to null.Sensible side-effect behaviour: To get that, you really need an
operator (or other language construct), and a function-like syntax is
misleading. Although unfamiliar,$_GET[?'foo'] $: $defaults[?'foo'] $: 42
is less misleading. It also extends nicely to the assignment paradigm as
$_GET[?'foo'] $:= $defaults[?'foo'] $: 42;Ben.
I was planning on replying to the "coalesce" suggestion but you really took
my concerns and stated them much better than I could have myself, plus a
couple of other concerns I didn't even think about.
To respond to Arpad Ray's statement:
"To elaborate, I'd probably think this code was an unlikely series of typos,
or an encoding error:"
In my opinion that's a good thing. Then you might actually look it up in the
documentation instead of making the assumption that the syntax has
function-like properties just because it looks like a function. For example,
it took me at least 1 year from first encountering empty() until
understanding that it's not a normal function and actually a language
construct that suppresses unset notices. And I'm a pretty seasoned
programmer. There's only one thing worse than magic: hidden magic.
~Hannes
It's good for some situations, but there are plenty more where it doesn't
cut it, e.g. $_GET[?'foo'] $:= get_default_from_db('foo') $: "hard-coded".Ben.
On Sat, Apr 23, 2011 at 1:21 PM, Hannes Landeholm landeholm@gmail.comwrote:
I was planning on replying to the "coalesce" suggestion but you really took
my concerns and stated them much better than I could have myself, plus a
couple of other concerns I didn't even think about.To respond to Arpad Ray's statement:
"To elaborate, I'd probably think this code was an unlikely series of
typos,
or an encoding error:"In my opinion that's a good thing. Then you might actually look it up in
the
documentation instead of making the assumption that the syntax has
function-like properties just because it looks like a function. For
example,
it took me at least 1 year from first encountering empty() until
understanding that it's not a normal function and actually a language
construct that suppresses unset notices. And I'm a pretty seasoned
programmer. There's only one thing worse than magic: hidden magic.
and we should try to avoid adding more magic where we can.
Tyrael
On Thu, 14 Apr 2011 15:25:45 +0200, Martin Scotta martinscotta@gmail.com
wrote:
arrays are intent for holding values, not for represent things so use
objects for that.
the need for array_key_exists/isset to check for the presence of an
index is
a smell that you need to refactor your code for a different datatype.
There is quite a difference in performance between using an array
representation of data structures such as graphs, matrices, etc and using
an OO representation. Also with the inclusion of closures it is possible
to write very elegant code using arrays and array functions such as
array_walk, array_map etc. If the multi-dimensional array is sparse, you
cannot really avoid a lot of isset calls.
Also, if you want to output everything as json in the end, working on
arrays is very natural.
--
Ole Markus
On Thu, 14 Apr 2011 10:59:41 +0200, Eloy Bote Falcon eloybote@gmail.com
wrote:
What is the purpose of that generateHash function? It doesn't work in the
isset check.
Instead of using a multi-dimensional array, I use a flat array.
Anyway, you can do a simple $a = array('foo'); isset($a[$x][$y][$z])
without
notices at all unless any of $x $y or $z are not defined, you don't need
to
check the indexes one by one.
Well, the example was just for brevity. If you want a full-blown example:
if (!isset($a[$x])) {
$a[$x] = array();
}
if (!isset($a[$x][$y])) {
$a[$x][$y] = array();
}
if (!isset($a[$x][$y][$z])) {
$a[$x][$y][$z] = array();
}
$a[$x][$y][$z] = 1;
Hope this clarifies.
--
Ole Markus
Suppression of notice. I agree, it is best done only for array
keys. It's not hard to initialise a variable with $var=null at the
beginning of a code block to avoid such a notice, and that is the
appropriate way to do it for variables.Offering a shortcut for the common idiom isset($x) ? $x : $y in
line with the DRY design principle. A notice would never be emitted
here in any case. The problem is that this idiom is still in wide use
despite the shortcut ternary operator already provided, because an
isset() check is different to a boolean cast.Some thoughts:
- The actual intent of 2. is probably $x!==null ? $x : $y i.e. it's
not about suppressing notices at all, but about offering a default
value, and the idiom quite probably only uses isset() because it
predated null in the language.I have never felt the need for a shortcut in these cases. It would be
interesting to see some code where this would be practical.
I have many, many uses for this. E.g. patterns like this:
class Foo {
private $defaultBar;
public function foobar(Bar $bar=null) {
$bar = isset($bar) ? $bar : $this->defaultBar;
$bar->doSomething();
}
}
The default value of null indicates that the argument is able to be
omitted, and the type hinting mechanism understands that. Yet it's
awkward to actually test whether it's been omitted or not without
writing the argument multiple times. It'd be great to be able to write
the first line succinctly, e.g.
$bar $:= $this->defaultBar;
That's just one case. There are many more.
As I said above, though, I probably should have written $bar!==null
rather than isset($bar), because I actually would want the warning if
$bar was not defined (i.e. I had mistyped it).
- If we view 2. in this way, the two problems are independent, and it
seems to me it would be best to solve them independently, rather
than with a single operator.So, I suggest:
- An array lookup mechanism that suppresses the notice for undefined
keys. It would work the same as regular array index lookups except
that the notice for undefined keys (and only for undefined keys)
would not be generated (it would not just be hidden, but would never
be even generated).This is what I feel PHP is missing. Particularly when it comes to
multi-dimensional arrays. Because this feature is missing I tend to do
something likefunction generateHash($x, $y, $z)
{
return "$x::$y::$z";
}if (isset($a[generateHash($x, $y, $z)]) {
...
}instead of
if (isset($a[$x]) && isset($a[$x][$y]) && isset($a[$x][$y][$z])) {
...
}
I don't really understand your example, or how an error-suppressing
array index lookup helps it, but I do think the feature is useful.
I actually think there is enough support for both these things, and
implementing them independently allows those who want to use one but not
the other to do so.
Arguing about syntax is then a second step. However, my views on this
are:I think it best to avoid discussing the actual syntax before agreeing on what we
really need.
I agree. In fact I sent the previous mail by mistake; I had intended to
archive my thoughts on syntax and send the mail without them, but I
bumped send.
Ben.
I have many, many uses for this. E.g. patterns like this:
class Foo {
private $defaultBar;
public function foobar(Bar $bar=null) {
$bar = isset($bar) ? $bar : $this->defaultBar;
$bar->doSomething();
}
}
I'm sorry but this is not a valid use case, isset() is totally
unnecessary here. You can use
$bar = $bar ?: $this->defaultBar;
Of course it still repeats $bar, but it's not that verbose, and will
work exactly the same as what you do. I'd argue it's even better than
what you do because, if it weren't for that Bar type hint, if someone
passes false or "blah" to your function, isset() will return true, and
you'll try to call doSomething on false/"blah", which is a cute fatal error.
Cheers
--
Jordi Boggiano
@seldaek :: http://seld.be/
I have many, many uses for this. E.g. patterns like this:
class Foo {
private $defaultBar;
public function foobar(Bar $bar=null) {
$bar = isset($bar) ? $bar : $this->defaultBar;
$bar->doSomething();
}
}I'm sorry but this is not a valid use case, isset() is totally
unnecessary here. You can use$bar = $bar ?: $this->defaultBar;
Of course it still repeats $bar, but it's not that verbose, and will
work exactly the same as what you do. I'd argue it's even better than
what you do because, if it weren't for that Bar type hint, if someone
passes false or "blah" to your function, isset() will return true, and
you'll try to call doSomething on false/"blah", which is a cute fatal error.
Actually, you'll get a cute fatal error when the function is called
because of the type hint in that case.
Anyway, yeah, sure, perhaps a bad example in its detail. I didn't spend
hours composing it. Just use a little imagination, though, and imagine
that it wasn't a type hinted object coming in, but some other value like
an integer. Then a boolean test would not work (would be false for zero
and erroneously use the default value). You then need the isset test. I
personally prefer to always use an isset/key_exists/is_null test when
I'm testing for something's 'existence' and not its 'truth'. I think
that makes the code more readable.
Ben.
Martin Scotta
On Thu, Apr 14, 2011 at 8:58 AM, Ben Schmidt
mail_ben_schmidt@yahoo.com.auwrote:
- Suppression of notice. I agree, it is best done only for array
keys. It's not hard to initialise a variable with $var=null at the
beginning of a code block to avoid such a notice, and that is the
appropriate way to do it for variables.
- Offering a shortcut for the common idiom isset($x) ? $x : $y in
line with the DRY design principle. A notice would never be emitted
here in any case. The problem is that this idiom is still in wide use
despite the shortcut ternary operator already provided, because an
isset() check is different to a boolean cast.Some thoughts:
- The actual intent of 2. is probably $x!==null ? $x : $y i.e. it's
not about suppressing notices at all, but about offering a default
value, and the idiom quite probably only uses isset() because it
predated null in the language.I have never felt the need for a shortcut in these cases. It would be
interesting to see some code where this would be practical.I have many, many uses for this. E.g. patterns like this:
class Foo {
private $defaultBar;
public function foobar(Bar $bar=null) {
$bar = isset($bar) ? $bar : $this->defaultBar;
$bar->doSomething();
}
}
Bad example... you could get a Bar object or a null value, so I would
write...
class Foo {
private $defaultBar; /* initialized somewhere */
public function foobar(Bar $bar=null) {
if (null === $bar) {
$bar = $this->defaultBar;
}
$bar->doSomething();
}
}
The default value of null indicates that the argument is able to be
omitted, and the type hinting mechanism understands that. Yet it's
awkward to actually test whether it's been omitted or not without
writing the argument multiple times. It'd be great to be able to write
the first line succinctly, e.g.$bar $:= $this->defaultBar;
That's just one case. There are many more.
As I said above, though, I probably should have written $bar!==null
rather than isset($bar), because I actually would want the warning if
$bar was not defined (i.e. I had mistyped it).
- If we view 2. in this way, the two problems are independent, and it
seems to me it would be best to solve them independently, rather
than with a single operator.So, I suggest:
- An array lookup mechanism that suppresses the notice for undefined
keys. It would work the same as regular array index lookups except
that the notice for undefined keys (and only for undefined keys)
would not be generated (it would not just be hidden, but would never
be even generated).This is what I feel PHP is missing. Particularly when it comes to
multi-dimensional arrays. Because this feature is missing I tend to do
something likefunction generateHash($x, $y, $z)
{
return "$x::$y::$z";
}if (isset($a[generateHash($x, $y, $z)]) {
...
}instead of
if (isset($a[$x]) && isset($a[$x][$y]) && isset($a[$x][$y][$z])) {
...
}I don't really understand your example, or how an error-suppressing
array index lookup helps it, but I do think the feature is useful.I actually think there is enough support for both these things, and
implementing them independently allows those who want to use one but not
the other to do so.Arguing about syntax is then a second step. However, my views on this
are:
I think it best to avoid discussing the actual syntax before agreeing on
what we
really need.I agree. In fact I sent the previous mail by mistake; I had intended to
archive my thoughts on syntax and send the mail without them, but I
bumped send.Ben.
Hey again
Updated here as always https://gist.github.com/909711. I've tried to
write down the goal of this new feature. Which patterns do we want to
make easier to write?Do you agree with the goals I've set?
+1 From me of course :)
Also added a proposal that would make userland implementations possible.
Interesting ideas, everyone.
However, I believe that the better approach would be to implement a new form
of the ternary operator as I suggested above. Just to save on typing, I'll
call the new form of the ternary operator a "Checked Ternary" in the
remainder of the email (but please don't judge its merits on the basis of
the name, the name can be anything you prefer.)
I believe the checked ternary operator would prove to be a reasonable
solution because:
- I firmly believe it's good that PHP elicits a warning when one tries to
access a non-existent element. We just need a way to work with arrays that
affords more parsimony. - Changing the semantics of the existing ternary operator (as suggested
by David) is not wise. I'm still trying to rally hosts to support PHP 5.3,
so I'm very cautious about changes that impact the semantics of existing
operators. - Developers are already familiar with the ternary operator, especially
in the context of working with arrays and providing defaults. Providing an
augmented form of the ternary operator will generalize well and be easy for
developers to learn and remember. - In contrast to Sanford, I don't see the meaning of '?' and '??' as
being disjunctive when compared to '=', '==', and '==='. - I don't see a need to mirror both empty() and isset().
Checked Ternary Operator (expression1) ?? (expression2) : (expression3)
The checked ternary operator follows the same rules as the ternary operator.
The difference between the checked version and the standard version is that
expression1 expands to the code below automatically IF the first expression
is a variable:
(isset($exrpession1) && $expression1) ?? (expression2) : (expression3)
Examples
$arr = array('k1' => 'v1', 'k2' => 'v2', 'k3' => 'v3');
$var1 = 'val1';
$var2 = 'val2';
// standard ternary operator
$arr['k3'] ? strtoupper($arr['k3']) : 'default'; // V3
$arr['k4'] ? strtoupper($arr['k4']) : 'default'; // elicits warning
$arr['k3'] ? : 'default'; // v3
$arr['k4'] ? : 'default'; // elicits warning
($var1 == $var2) ? 'same' : 'different'; // different
($var1 == $var3) ? 'same' : 'different'; // elicits notice
// checked ternary operator
$arr['k3'] ?? strtoupper($arr['k3']) : 'default'; // V3
$arr['k4'] ?? strtoupper($arr['k4']) : 'default'; // default
$arr['k3'] ?? : 'default'; // v3
$arr['k4'] ?? : 'default'; // default
($var1 == $var2) ?? 'same' : 'different'; // different
($var1 == $var3) ?? 'same' : 'different'; // different
In short, you could use the checked ternary operator anywhere you'd normally
use the standard ternary and the only difference in behavior would be the
lack of warnings and/or notices for accessing unset array keys and/or
variables.
This would be a safe, simple, and practical way of dealing with the issue.
Thanks for reading this far.
Adam
--
Nephtali: A simple, flexible, fast, and security-focused PHP framework
http://nephtaliproject.com
I just feels that !empty($arr['key']) or isset($arr['key']) do not express
the real meaning, instead I would choose to write array_key_exists('key',
$arr). It may be slower but it clearly express what I meant.
I don't like this. array_key_exists will return true for an array key
that exists but is set to null, which is rarely what is wanted (though
it sometimes is).
I agree that the variants with empty() aren't very good.
Just a single isset() variant seems like a good idea. I favour the ??:
syntax.
I liked the well-thought-out examples with assignment and chaining and
so on. For chaining, does associativity matter? (Too tired to figure it
out for myself right now!)
Ben.
On Thu, Mar 31, 2011 at 7:46 PM, Ben Schmidt
mail_ben_schmidt@yahoo.com.au wrote:Hey there,
I've been working on a little patch that will allow variables ($1) in
a short-ternary operation to go through an implicit isset
(zend_do_isset_or_isempty) check so that the average use-case for the
short-ternary operator doesn't yield in a notice whenever the first
variable of the expression isn't set.So the use-case I'm considering is the following:
<?php
$list = array('name' => 'list');echo $list['name'] ?: 'List not set.' . PHP_EOL;
echo $list['name-notset'] ?: 'List not set.' . PHP_EOL;
?>This example, which we all know, will result in a notice for the
second echo statement because the requested array-key doesn't actually
exist in the array.I'm not familiar with the construct, but to be honest, I fail to see how
it is useful without the suppression of the notice. I mean, it's a
shorthand for isset($var)?$var:$something_else isn't it? That
presupposes that $var may not be set, but that you've accounted for that
fact, so don't want a notice about it. Obviously the isset() can only be
applied if the 'left hand side' is an lval, but I think it makes sense
to apply it whenever it is an lval.So a big +1 from me.
Ben.
Its also a +1 for me, it would make the ternary operator much more
useful to me e remove lots of verbose code for handling arrays.Well, it would change the semantics. And Ben, no, it isn't shorthand for an
isset() it is like writing (boolean)$var?$var:$something
Thanks for the clarification, Rasmus. That makes sense.
I still think the patch would be very useful, though I can also see how an
argument could be made for keeping the warning. In my opinion, the case for
removing the warning is stronger than for keeping it.
Ben.