Open johnkary opened 8 years ago
The constants USE_KEY
and USE_BOTH
belong to Haystack. The PHP flags are ARRAY_FILTER_USE_KEY
and ARRAY_FILTER_USE_KEY
The tests pass for PHP 5.5, so I'm not sure that I understand what the problem is.
You're right. My 1am-brain wasn't thinking correctly. However in the docblock for FunctionalInterface::filter() it mentions PHP 5.6 being required to pass the USE_BOTH flag. https://github.com/ericpoe/haystack/blob/master/src/Functional/FunctionalInterface.php#L36
The bigger issue I was trying to identify was FunctionalInterface::filter() accepting a flag as part of its interface feels imprecise. It prescribes functionality that can't be bound to the method signature--as in could two FunctionalInterface implementations be guaranteed to support the same flags? A separate implementation could decide they want to create a whole new flag USE_BOTH_BACKWARDS where their callback argument order is flipped to ($key, $value)
. Their implementation honors the interface but the implementation is not compatible with all FunctionalInterface implementations.
What if instead of accepting a flag argument the filter($fn)
method always accepted a callback function($value, $key)
? This is the behavior of USE_BOTH. If the calling code only cares about the value (in my opinion this would be most common) it is valid to pass a callback whose signature is function($value)
.
Many functions in Laravel's Collection class pass both ($value, $key)
to the callback. While functions in Doctrine's ArrayCollection class don't make this concession only passing ($value)
to the callback.
I like the idea. I spent a lot of time trying to figure out why ARRAY_FILTER_USE_BOTH
expected callback($value, $key)
rather than a more natural callback($key, $value)
; I finally found the reason by asking one of the internals devs who worked on that feature. I don't want others to look at Haystack and ask why the order of parameters is so funky. Also I would love to be able to not use flags in this method. This method should just work without the end-user needing to anything special.
There are 4 different types of array_filter
and Haystack is trying to cover all of them:
callback($value)
callback($key)
callback($key, $value)
I can picture easy ways to implement the no-callback and fully-loaded-callback possibilities. However, how should we discern between when only a $key is used and when only a $value is used in the callback? If I check for array_key_exists($key, $array)
to determine if callback($key)
is meant rather than callback($value)
and yet callback($value)
was meant and it just so happens that a supplied $value
has the same name as a $key
?
Any ideas?
Supplying the
$flag
parameter toFunctionalInterface::filter(callable $func = null, $flag = null);
currently relies on PHP 5.6 constants\USE_KEY
and\USE_BOTH
to decide whether the callback is called with the value, key or both <value, key>. This functionality should instead be available for all PHP versions supported via composer.json require statement, currently >= 5.5.9.I see two possible approaches here...
1) Haystack adds its own constants and uses them for
filter($func, null $flag = null)
.null
- Pass value.FunctionalInterface::USE_KEY
- Pass key.FunctionalInterface::USE_BOTH
- Pass both.2) Haystack adds two new methods that don't require calling code to provide the flags.
filter($func, null $flag = null)
-- Passes container value to callback unless $flag given. $flag can be one ofnull || FunctionalInterface::USE_KEY || FunctionalInterface::USE_BOTH
. Return true preserves key => value in new container.filterByKey($func)
-- Passes container key to callback. Implementation delegates to filter() and supplies the correct constant. Return true preserves key => value in new container.filterByBoth($func)
-- Passes container key as first callback argument, value as second argument. Implementation delegates to filter() and supplies the correct constant. Return true preserves key => value in new container.