On 9/11/07, Marcus Boerger <[EMAIL PROTECTED]> wrote:
> Hello Andrew,
>
>   did you check out '?:' shortcut in HEAD?
>
>   php -r 'echo 4?:2;' -> 4
>   php -r 'echo 0?:2;' -> 2
>
> best regards
> marcus

Yes, I had hoped that the ?: operator would solve this. But it doesn't
serve the same purpose, because it causes an E_NOTICE for missing
values. However, ?: and array_get can be used together to provide
short-circuit evaluation, overcoming the limitations of both.

Example:
array_get($_GET, 'foo') ?: slowDefaultCalculation()


Here is a test of ?: with CVS HEAD + the array_get function:

>>> var_dump($_SERVER['test'] ?: 'nope');
PHP Notice:  Undefined index:  test in - on line 2
string(4) "nope"

>>> var_dump(array_get($_SERVER, 'test', 'nope'));
string(4) "nope"

>
> Tuesday, September 11, 2007, 3:20:46 PM, you wrote:
>
> > If there's a workable proposal for ifsetor() that fixes the concerns
> > brought up by the original and is likely to go in PHP 6, that would
> > be great.
>
> > In this case, perfect can be the enemy of good. array_get() helps
> > with many common use cases of ifsetor() while fitting into the the
> > standard PHP syntax and function model, potentially making its
> > adoption much easier.
>
> > See below for answers to what you mentioned.
>
> > On Sep 11, 2007, at 5:27 AM, Marcus Boerger wrote:
>
> >> Hello Andrew,
> >>
> >>   you can easily implement this function run time. It is not very
> >> flexible
> >> and far away from what ifsetor was meant to be. Thus I do not think
> >> it is a
> >> good idea. See comments below.
> >>
> >> marcus
> >>
> >> Tuesday, September 11, 2007, 12:12:55 AM, you wrote:
> >>
> >>> Here's a patch against HEAD that implements the array_get function
> >>> previously suggested on this list. I also attached a test suite,
> >>> which should go in ext/standard/tests/array/array_get.phpt. Feedback
> >>> is welcome.
> >>
> >>> Independently, someone else had posted the same idea as a feature
> >>> request for PHP 5, and if there's interest I can backport it.
> >>
> >>> 40792 Open       Wish: Function array_get(&$mixed, $key,
> >>> $defaultvalue)
> >>
> >>> /* Prototype:
> >>> *  mixed array_get ( array $search, mixed $key, mixed $default );
> >>
> >> array should not be passed as reference as that would be a slowdown
> >> unless
> >> the function is supposed to create the index key which according to
> >> the
> >> specs below it doesn't.
>
> > True, as you suggest, it is not passed by reference. (That bug title
> > was posted independently by someone who might not have thought that
> > particular aspect through, and it isn't important to the text.)
>
> >>
> >>> * Description:
> >>> *  Returns the value corresponding to the given key if the key exists
> >>> *  in the array. $key can be any value possible for an array index.
> >>> *  If the key does not exist, the function returns $default, or FALSE
> >>> *  if $default is not specified. Also works on objects.
> >>> *  Similar semantics to array_key_exists.
> >>> */
> >>
> >>> Here is the original proposal:
> >>> =======
> >>> array_get, a more palatable alternative to ifsetor
> >>
> >> Things this cannot do but ifsetor can.
> >> - Check whether the array exists
> > True, though there's an argument that this could even be better (less
> > error-prone) for the typical uses I've seen in my code and elsewhere,
> > where we're interested in whether the key exists in an array we
> > already have. An isset-like function doesn't allow you to separate
> > the two existence checks, allowing spelling errors in the array name
> > to go undetected when they could easily be caught. In circumstances
> > where you really do need to check both, you can call isset() or !empty
> > () on the array first:
> > $value = isset($array) ? array_get($array, 'mykey') : FALSE;
>
> >> - Mulitlevel queries
> > Use nested array_get().
>
> >> - Other types of queries (e.g. object members)
> > array_get() supports object members, just like array_key_exists().
>
> >> - In theory we could have ifsetor even return a writeable reference
> >> where a
> >> non existing key would either be created or (pretty bad imo) a
> >> reference to
> >> the default value gets returned.
> > Something like that would be nice, but it doesn't exist and I haven't
> > seen a concrete proposal for it.
>
> >>
> >>> MOTIVATION
> >>
> >>> There is an unmet need for an accessor that doesn't generate an
> >>> E_NOTICE when the value is missing, as shown by ongoing discussions
> >>> and repeated requests for an ifsetor operator. However, ifsetor had a
> >>> special-case syntax and generally didn't fit very well with the rest
> >>> of the language.
> >>
> >>> http://devzone.zend.com/node/view/id/1481#Heading2 has a brief
> >>> summary. See the Related Functions and Proposals section for more.
> >>
> >>> Reading over those ideas (firstset(), coalesce(), :?, ifset(), and a
> >>> workaround using settype()), most of the best uses boil down to
> >>> retrieving values from arrays.
> >>
> >>
> >>> PROPOSAL
> >>
> >>> As a simpler alternative to constructs such as this common double
> >>> array reference...
> >>>
> >>>                 $value = isset($_POST['command']) ? $_POST
> >>> ['command'] : '';
> >>>
> >>> I propose an array_get function, like this...
> >>>
> >>>                 $value = array_get($_POST, 'command', '');
> >>>
> >>> The third argument provides a default. This function would require no
> >>> special syntax, and makes a very common construct easier to read and
> >>> less error-prone to type. It's a concise way of saying that missing
> >>> values can be handled gracefully.
> >>
> >>> Though request processing was used as an example, the function has
> >>> wide applicability across many other uses of associative arrays.
> >>
> >>>
> >>> GREAT, BUT WHY NOT ADD IT TO AN INCLUDE FILE, INSTEAD OF THE CORE?
> >>
> >>> One of the goals is to make everyday PHP code simpler and clearer.
> >>> Writers of sample code snippets should be able to rely on array_get()
> >>> being available. Otherwise, they will not use it. Clearer sample code
> >>> particularly benefits beginners, who would probably find array_get
> >>> easier to understand, but anyone else who has to read or maintain
> >>> other people's code would benefit from its wide deployment in core as
> >>> well. The function is generally useful enough to be part of the
> >>> language, and the implementation in C is also more efficient than a
> >>> PHP version.
> >>
> >>> That said, a compatibility function for older versions of PHP is
> >>> given below.
> >>
> >>
> >>> SEMANTICS
> >>
> >>>           mixed array_get(array $array, mixed $key[, mixed
> >>> $default = FALSE]);
> >>>
> >>> If $array contains the key $key, $array[$key] is returned. Otherwise
> >>> $default is returned.
> >>>
> >>> If $default is not specified, it defaults to FALSE. (NULL would also
> >>> be possible, and would more closely match other languages such as
> >>> Python with its dict.get method, but other PHP functions tend to
> >>> return FALSE to indicate no value.)
> >>>
> >>> The semantics match
> >>>
> >>>                 array_key_exists($key, $array) ? $array[$key] :
> >>> $default
> >>>
> >>> ... but for comparison,
> >>>
> >>>                 isset($array[$key]) ? $array[$key] : $default
> >>>
> >>> is subtly different. The preferred array_key_exists version has these
> >>> differences:
> >>>           1. If $array[$key] exists but has been set to null, that
> >>> null
> >>> value will be returned instead of $default. This is likely to be the
> >>> least surprising thing to do.
> >>>           2. If $array itself is unset, an error is generated.
> >>> This is good.
> >>> The intention is to gracefully handle a missing $key. But if even
> >>> $array itself doesn't exist, there may be another problem, such as
> >>> misspelling the array variable. isset() ignores all errors, sweeping
> >>> more under the rug than we typically want.
> >>
> >>
> >>> IMPLEMENTATION
> >>
> >>> A core C implementation of array_get() benchmarked between two and
> >>> three times as fast as the implementation in PHP. I'll attach the
> >>> patch after responding to feedback.
> >>
> >>> See the last section for the code of the PHP implementation.
> >>
> >>
> >>> RELATED FUNCTIONS AND PROPOSALS
> >>
> >>> This function is different than the array_get function proposed and
> >>> rejected in http://bugs.php.net/bug.php?id=28185. That function had
> >>> no default value and throws a notice when the key doesn't exist,
> >>> eliminating the major purpose of this function.
> >>
> >>> The ?: operator doesn't serve the same purpose, because it causes an
> >>> E_NOTICE for missing values. However, ?: and array_get can be used
> >>> together to provide short-circuit evaluation, overcoming the
> >>> limitations of both. See the LIMITATIONS section for an example.
> >>
> >>> ifsetor: as discussed above, ifsetor wasn't a regular function. It
> >>> required special language syntax support because it attempted to test
> >>> whether a direct parameter itself was set or unset, and was
> >>> ultimately rejected.
> >>
> >>> ifset: a related proposal to ifsetor, with a simpler syntax, ifset
> >>> was missing a way to control the default value.
> >>
> >>> See here for more discussion about the 'E_STRICT ternary pain-in-the-
> >>> ass expression' and alternatives:
> >>>         http://keithdevens.com/weblog/archive/2005/Nov/24
> >>>         http://www.php.net/~derick/meeting-notes.html#id39
> >>>         http://devzone.zend.com/node/view/id/1481#Heading2
> >>
> >>>
> >>> LIMITATIONS
> >>
> >>> This proposal doesn't address every requested feature. The third
> >>> parameter is always evaluated, so calling a slow function there would
> >>> be undesirable. However, the limitation appears to be unavoidable
> >>> without special language support, and there are workarounds. These
> >>> snippets have approximately equal meanings (though they may differ is
> >>> the handling of array values that convert to false):
> >>
> >>>      array_get($_GET, 'foo', slowDefaultCalculation())
> >>
> >>>      $val = array_get($_GET, 'foo'); if (!$val) $val =
> >>> slowDefaultCalculation();
> >>
> >>>      array_get($_GET, 'foo') ?: slowDefaultCalculation()
> >>
> >>> The last example uses the new PHP 6 ?: operator.
> >>
> >>> This function applies only to array elements. Unlike other proposed
> >>> functions, it doesn't also attempt to determine whether variables are
> >>> set. However, the practical uses suggested for the other functions
> >>> generally ended up applying to array elements.
> >>
> >>
> >>> COMPATIBILITY FUNCTION FOR OLDER VERSIONS OF PHP
> >>
> >>> if (!function_exists('array_get')) {
> >>>      function array_get($arr, $key, $default = false) {
> >>>          if (array_key_exists($key, $arr)) {
> >>>              return $arr[$key];
> >>>          }
> >>>          else {
> >>>              return $default;
> >>>          }
> >>>      }
> >>> }
> >>
> >>> (This version turned in the fastest times out of several variants.
> >>> Passing $arr by reference or attempting to return the result by
> >>> reference had a huge negative impact, and using the ternary ? :
> >>> operator instead of the if/else was slightly slower.)
> >>
> >>> =======
> >>> --
> >>> Andrew Shearer
> >>> http://ashearer.com/
> >> Best regards,
> >>  Marcus
>
> > Andrew Shearer
> > http://ashearer.com/
>
>
>
>
> Best regards,
>  Marcus
>
>

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

Reply via email to