Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hash::contains should return true for empty needle #8632

Closed
nrother opened this issue Apr 12, 2016 · 19 comments
Closed

Hash::contains should return true for empty needle #8632

nrother opened this issue Apr 12, 2016 · 19 comments
Labels
Milestone

Comments

@nrother
Copy link
Contributor

nrother commented Apr 12, 2016

Hash::contains(['a'], []); //false
Hash::contains([], []); //false

This is contradictory to the mathematical definition to a subset. I currently don't see a reason why contains should work this way. (This bug might exist due to a mixup of && and || here)

@markstory
Copy link
Member

Changing this would mean that all datasets contain all empty needle values. I'm not convinced that this is a good idea.

@markstory markstory added this to the 3.2.8 milestone Apr 12, 2016
@ADmad
Copy link
Member

ADmad commented Apr 12, 2016

Making this change is also likely to affect existing apps.

@markstory
Copy link
Member

Yes. It changes the behavior in a backwards incompatible way.

@thinkingmedia
Copy link
Contributor

If this is important, and I don't think it is. You could add a third parameter called strict that enables this check, but you know it's just extra code that most people won't use.

@nrother
Copy link
Contributor Author

nrother commented Apr 13, 2016

I tried to use this code to detect if one user has all rights another user has, and this failed, when the first user did not had any rights. I found this very confusing. I might be interesting to find out how often this method is really called with [] for the second parameter and someone is really expecting this to return false. But this might be just me, as I'm from a kind-of-mathematical background.

I'd vote (at least) for a strict parameter.

@nrother
Copy link
Contributor Author

nrother commented Apr 13, 2016

FYI: Currently all tests pass with my proposed modification. Don't know what is about real-world-applications, though.

@markstory
Copy link
Member

@nrother Sounds like we're missing a test case 😄

@lorenzo
Copy link
Member

lorenzo commented Apr 13, 2016

Arrays are not sets in the mathematical definition, so this is completely counter intuitive to how the rest of the language works

@nrother
Copy link
Contributor Author

nrother commented Apr 13, 2016

@lorenzo Do you have an example of this "rest of the language"? A quick search only reveals array_intersects, which works the way I'd expected it to: array_intersect(['a'], []); //[]

Still can't come up with a use-case where the current behaviour is useful...

@lorenzo
Copy link
Member

lorenzo commented Apr 13, 2016

Yes this, for example:

in_array([], ['a', []]); // true

in_array([], ['a']); // false

@nrother
Copy link
Contributor Author

nrother commented Apr 14, 2016

in_array([], ['a', []]); // true is a good point, but the import thing there is, that in_array threats the first parameter as a single value to search for, so [] is just any kind of value. I expected Hash::contains as "check if every value from $needle can be found in $haystack". I now found that the documentation says "Determines if one Hash or array contains the exact keys and values of another", which might be a slight different thing, as it does not say "contains all keys and value of another".

I found some other inconsistencies (IMHO) in the framework:

Hash::numeric(['1']) //true
Hash::numeric([]) //false
collection(['1'])->every(function($item) {return is_numeric($item);}) //true
collection([])->every(function($item) {return is_numeric($item);}) //true

But this might be due to the fact that a collection is more a (mathematical) set than a hash. But somehow there seems to be a bit of confusion how to handle empty needles.

@lorenzo
Copy link
Member

lorenzo commented Apr 14, 2016

I agree the second collection example is a bug.

@nrother
Copy link
Contributor Author

nrother commented Apr 19, 2016

Ok, that was not what I wanted to reach 😄. In the meantime I did some research:

//Java
Arrays.stream(new int[] {1}).allMatch(x -> false); //false
Arrays.stream(new int[] {}).allMatch(x -> false); //true
//C#
new int[]{1}.All(x => false); //false
new int[]{}.All(x => false); //true
#Python
all([False for x in [1]]) #false
all([False for x in []]) #true
//CakePHP (with 64669a9)
collection([1])->every(function() {return false;}) //false
collection([])->every(function() {return false;}) //false

That not what I'd expect as a developer! So for me #8670 clearly made the situation worse. and I could imagine that that even breaks someones code. (It would break mine).

@markstory markstory modified the milestones: 3.2.8, 3.2.9 Apr 25, 2016
@markstory markstory modified the milestones: 3.2.9, 3.2.10 May 17, 2016
@markstory markstory modified the milestones: 3.2.10, 3.2.11 May 26, 2016
@markstory markstory modified the milestones: 3.2.11, 3.2.12 Jun 21, 2016
@markstory markstory added this to the 3.6.7 milestone Jun 25, 2018
@markstory markstory modified the milestones: 3.6.7, 3.6.8 Jul 8, 2018
@markstory markstory modified the milestones: 3.6.8, 3.6.9, 3.6.10 Jul 24, 2018
@markstory markstory modified the milestones: 3.6.10, 3.6.11 Aug 5, 2018
@markstory markstory modified the milestones: 3.6.11, 3.6.12 Sep 3, 2018
@markstory markstory modified the milestones: 3.6.12, 3.6.13 Oct 2, 2018
@markstory markstory modified the milestones: 3.6.13, 3.6.14 Nov 4, 2018
@markstory markstory modified the milestones: 3.6.14, 3.7.0, Future Dec 7, 2018
@dereuromark
Copy link
Member

Do we want to address this for 4.0?

@markstory markstory modified the milestones: Future, 4.0.0 Feb 16, 2019
@markstory
Copy link
Member

I think that would be our next opportunity to do it.

@github-actions
Copy link

This issue is stale because it has been open for 120 days with no activity. Remove the stale label or comment or this will be closed in 15 days

@github-actions github-actions bot added the stale label Sep 19, 2019
@github-actions github-actions bot closed this as completed Oct 4, 2019
@dereuromark dereuromark removed the stale label Oct 4, 2019
@dereuromark dereuromark reopened this Oct 4, 2019
@othercorey
Copy link
Member

I don't think there is anything to do here though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants