On Wed, Oct 18, 2023, at 3:37 PM, Deleu wrote: > I believe my reservations have been registered, I would not like to have > `array_first()` behave in a non-obvious way (i.e. involving array $key) > because it's useful for Fibers users. I believe that writing your own > wrapper that always returns key and value simultaneously is easy and > straight-forward and may even make it into the core in the future. Rather > than trying to solve deep convoluted issues on version 1, I believe PHP > could introduce the simplest version of the function first and later on add > an array_first_key_value() in the future if needed.
I think there's a fundamental misunderstanding here. Fibers are not threads. They do not do preemptive multitasking. If a give function call stack does not explicitly suspend itself, then a fiber WILL NOT change the current context. If we assume that array_first(), being an internal function, does not explicitly suspend a fiber internally (which I think is a pretty safe assumption), then this code cannot possibly have a race condition in it: $key = array_key_first($arr); $value = array[$key]; The concerns about this having some kind of race condition around fibers are, as far as I am aware, entirely unfounded, and we should not consider them, as they do not exist. (Obviously if those two lines are separated by some other call, and that other call suspends a fiber, then it's possible there would be a race condition. But in that case the operation is not atomic anyway so all bets are completely off. Which is why you shouldn't be using shared mutable state arrays at all in the first place, fibers are not, but that's another story.) As far as the not-found error case goes, I cite my previous article on the subject here: https://peakd.com/hive-168588/@crell/much-ado-about-null More to the point, PHP arrays are untyped. That means there is absolutely no possible sentinel value that we can guarantee will never be an array value, because even if we defined some one-off enum to serve as a sentinel, that could be put into an array quite easily, even if it's dumb to do. `null` is the default sentinel value, but runs into various problems because its meaning in different contexts may be different. The question is whether null being a legit value in an array being accessed with array_first/array_last is a common *enough* case that we need to worry about it. I highly doubt it, frankly. I cannot think of a non-contrived case where that would be true. (An array with random null values in it that you don't want to filter out entirely seems like an edge case to me.) That means for the vast majority of use cases, this is completely fine: $v = array_first($arr) ?? $default; Because the cases where you care to differentiate between "there is no first value" and "there is a first value but it is a non-value" are small. And, as others have noted, in those cases count() isn't hard to use. So no, we don't need to do anything fancier than that. To the other points raised: Absolutely not to an in/out by-ref parameter. That is an abomination and I will vote against any API that does that, without hesitation. Let's not even discuss it. As far as the naming, most array functions that have a value version and key version don't specify "value", only the key. The unspecified version is the value version. (array_diff vs array_diff_key, array_intersect vs array_intersect_key, sort vs ksort, etc.) Pretty much nowhere do we specify "_value" in the function name. https://www.php.net/manual/en/ref.array.php That means array_first/array_last is consistent with the current API, and array_first_value would be the confusing oddball. For that reason, no, we should not do that and just use array_first/array_last. With all that said, I do support simple array_first/array_last functions, with just a null-for-not-found return. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php