Hello Andrew,

  how about @<expression>?:<default> style?

Like: $val = $myarray[$key] ?: $default;

marcus

Tuesday, September 11, 2007, 6:33:42 PM, you wrote:

> 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
>>
>>




Best regards,
 Marcus

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

Reply via email to