"bananas".contains("") returns true...why?

why contains returns true when the pattern is an empty string?

The empty string "" is a substring of any other string. Here's one way to see this:

"Y is a substring of X" means that there exist two strings U, V such that X = U + Y + V, where '+' means string concatenation (so "egg" + " " + "salad" = "egg salad"). E.g. "nca" is a substring of "pancakes" because "pancakes" = "pa" + "nca" + "kes" (X = "pancakes", Y = "nca", U = "pa", V = "kes"). U is the part of X before Y, and V is the part of X after Y.

When Y = "", you can make this "equation" work for any string X, by setting U = X and V = "": X = X + "" + "" is always true. So "" is a substring of every string, and that's why "bananas".contains("") evaluates to true, because "bananas" = "bananas" + "" + "".

6 Likes

Because you can stick "more " and "bananas" together to get "more bananas".

Having done so the result, "more bananas", contains "more". Also "more bananas" contains "bananas"

Similarly you can stick "" and "bananas" together to get "bananas"

Having done so, and by the same logic the result, "bananas" must contain both the strings you started with. That is to say "bananas" contains "" and it contains "bananas".

This might seem a bit strange but I think you can see the logic works.

It might feel strange because it seems "bananas" contains "" even before you have stuck "bananas" and "" together. Unlike the first example above.

Think of it like 2 = 2. But also 2 + 0 = 2. And 2 + 0 + 0 = 2. And ...

1 Like

To add a third way to the set here, "bananas".contains("") is true because bananas[2..2] == "". (As is bananas[0..0] and ...)

"" is the identity element of the String::add monoid, you might say :smirk:

3 Likes

Another way to think about it is: if foo.contains(a + b) is true, then you’d pretty much expect foo.contains(a) and foo.contains(b) to also be true, regardless of what a and b are.

2 Likes

it was quite a illustrative example , thanks