Change Request: Make myString.hasPrefix("") and myString.hasSuffix("") return true


(Chris Denter) #1

Hello –

Currently, the standard library String functions .hasPrefix() and
.hasSuffix() will return false when given the empty string as input:

$ swift
  1> "".hasPrefix("")
$R0: Bool = false
  2> "foo".hasPrefix("")
$R1: Bool = false
  3> "foo".hasSuffix("")
$R2: Bool = false

This feels unexpected. The reason the methods behave this way seems to be a
leaked implementation detail
<https://twitter.com/cdntr/status/755059959713427456>.
Some languages, such as Python, return True in these cases -- perhaps
motivated by the `someSet.contains(emptySet) == true` analogy.

The ship has sailed for NSString and Foundation, but we might want to bite
the bullet and fix this for Swift before 3.0 makes that much harder.

Thank you so much for your time,

    Chris


(Kevin Nattinger) #2

I agree, true is definitely the expected behavior. In particular, it seems absurd to me that `a.hasPrefix(b)` and `a.hasSuffix(b)` could be false when `a == b` is true.

···

On Jul 18, 2016, at 10:36 AM, Chris Denter via swift-evolution <swift-evolution@swift.org> wrote:

Hello –

Currently, the standard library String functions .hasPrefix() and .hasSuffix() will return false when given the empty string as input:

$ swift
  1> "".hasPrefix("")
$R0: Bool = false
  2> "foo".hasPrefix("")
$R1: Bool = false
  3> "foo".hasSuffix("")
$R2: Bool = false

This feels unexpected. The reason the methods behave this way seems to be a leaked implementation detail.
Some languages, such as Python, return True in these cases -- perhaps motivated by the `someSet.contains(emptySet) == true` analogy.

The ship has sailed for NSString and Foundation, but we might want to bite the bullet and fix this for Swift before 3.0 makes that much harder.

Thank you so much for your time,

    Chris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Dave Abrahams) #3

I expect to be reworking Strings for Swift 4, and this is one of the
many things we plan to address.

···

on Mon Jul 18 2016, Kevin Nattinger <swift-evolution@swift.org> wrote:

I agree, true is definitely the expected behavior. In particular, it
seems absurd to me that `a.hasPrefix(b)` and `a.hasSuffix(b)` could be
false when `a == b` is true.

--
Dave


(Charlie Monroe) #4

+1 - this shouldn't be hard to fix either - in StringLegacy.swift, add a check for prefix.isEmpty and return true...

···

On Jul 18, 2016, at 7:36 PM, Chris Denter via swift-evolution <swift-evolution@swift.org> wrote:

Hello –

Currently, the standard library String functions .hasPrefix() and .hasSuffix() will return false when given the empty string as input:

$ swift
  1> "".hasPrefix("")
$R0: Bool = false
  2> "foo".hasPrefix("")
$R1: Bool = false
  3> "foo".hasSuffix("")
$R2: Bool = false

This feels unexpected. The reason the methods behave this way seems to be a leaked implementation detail <https://twitter.com/cdntr/status/755059959713427456>.
Some languages, such as Python, return True in these cases -- perhaps motivated by the `someSet.contains(emptySet) == true` analogy.

The ship has sailed for NSString and Foundation, but we might want to bite the bullet and fix this for Swift before 3.0 makes that much harder.

Thank you so much for your time,

    Chris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Dmitri Gribenko) #5

Why not implement the change right now so that we change the semantics
in Swift 3 rather than in Swift 4?

Dmitri

···

On Mon, Jul 18, 2016 at 3:29 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Mon Jul 18 2016, Kevin Nattinger <swift-evolution@swift.org> wrote:

I agree, true is definitely the expected behavior. In particular, it
seems absurd to me that `a.hasPrefix(b)` and `a.hasSuffix(b)` could be
false when `a == b` is true.

I expect to be reworking Strings for Swift 4, and this is one of the
many things we plan to address.

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Michael Peternell) #6

+1
this should be a bugfix.

···

Am 18.07.2016 um 19:36 schrieb Chris Denter via swift-evolution <swift-evolution@swift.org>:

Hello –

Currently, the standard library String functions .hasPrefix() and .hasSuffix() will return false when given the empty string as input:

$ swift
  1> "".hasPrefix("")
$R0: Bool = false
  2> "foo".hasPrefix("")
$R1: Bool = false
  3> "foo".hasSuffix("")
$R2: Bool = false

This feels unexpected. The reason the methods behave this way seems to be a leaked implementation detail.
Some languages, such as Python, return True in these cases -- perhaps motivated by the `someSet.contains(emptySet) == true` analogy.

The ship has sailed for NSString and Foundation, but we might want to bite the bullet and fix this for Swift before 3.0 makes that much harder.

Thank you so much for your time,

    Chris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Dave Abrahams) #7

+1
this should be a bugfix.

PRs for bugfixes always appreciated.

···

on Wed Jul 20 2016, Michael Peternell <swift-evolution@swift.org> wrote:

Am 18.07.2016 um 19:36 schrieb Chris Denter via swift-evolution <swift-evolution@swift.org>:

Hello –

Currently, the standard library String functions .hasPrefix() and
.hasSuffix() will return false when given the empty string as input:

$ swift
  1> "".hasPrefix("")
$R0: Bool = false
  2> "foo".hasPrefix("")
$R1: Bool = false
  3> "foo".hasSuffix("")
$R2: Bool = false

This feels unexpected. The reason the methods behave this way seems to be a leaked implementation detail.
Some languages, such as Python, return True in these cases -- perhaps motivated by the `someSet.contains(emptySet) == true` analogy.

The ship has sailed for NSString and Foundation, but we might want to bite the bullet and fix this for Swift before 3.0 makes that much harder.

Thank you so much for your time,

    Chris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Dave


(Guillaume Lessard) #8

First, NSString’s prefix function returns false for empty string parameters, and this would be a significant departure in behaviour.

Second, while an empty string is technically a prefix to any other string, that is hardly ever an interesting answer; it is a trivial solution, just as y=0 is for y(x)=y’(x). It is easy to special-case if one really needs to consider the empty string.

Cheers,
Guillaume Lessard

···

On 20 juil. 2016, at 12:42, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

+1
this should be a bugfix.


(Guillaume Lessard) #9

I specifically used an example where the trivial solution (y=0 instead of y=exp(x)) is a pitfall.

How many empty strings are contained in any given string?
If the answer is infinitely many, it sounds like a pitfall to me.

Cheers,
Guillaume Lessard

···

On 20 juil. 2016, at 14:21, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Doesn't your second argument undermine your first? If it's a trivial solution and one rarely ever considers empty strings when invoking `hasPrefix`, then returning the technically correct result must be a trivial departure in behavior.


(Tony Allevato) #10

>
> +1
> this should be a bugfix.

First, NSString’s prefix function returns false for empty string
parameters, and this would be a significant departure in behaviour.

It would be a significant correction in behavior.

Second, while an empty string is technically a prefix to any other string,
that is hardly ever an interesting answer; it is a trivial solution, just
as y=0 is for y(x)=y’(x). It is easy to special-case if one really needs to
consider the empty string.

On the contrary—I've written code in the past that expected this behavior
(because why wouldn't I? It's the correct behavior) and was quite surprised
when NSString's behavior resulted in a bug.

NSString being plain wrong here should not consign us to wrongness forever.
Every other mainstream language I use day-to-day implements this correctly,
and so should Swift.

···

On Wed, Jul 20, 2016 at 1:14 PM Guillaume Lessard via swift-evolution < swift-evolution@swift.org> wrote:

> On 20 juil. 2016, at 12:42, Michael Peternell via swift-evolution < > swift-evolution@swift.org> wrote:

Cheers,
Guillaume Lessard

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #11

Doesn't your second argument undermine your first? If it's a trivial
solution and one rarely ever considers empty strings when invoking
`hasPrefix`, then returning the technically correct result must be a
trivial departure in behavior.

···

On Wed, Jul 20, 2016 at 15:14 Guillaume Lessard via swift-evolution < swift-evolution@swift.org> wrote:

> On 20 juil. 2016, at 12:42, Michael Peternell via swift-evolution < > swift-evolution@swift.org> wrote:
>
> +1
> this should be a bugfix.

First, NSString’s prefix function returns false for empty string
parameters, and this would be a significant departure in behaviour.

Second, while an empty string is technically a prefix to any other string,
that is hardly ever an interesting answer; it is a trivial solution, just
as y=0 is for y(x)=y’(x). It is easy to special-case if one really needs to
consider the empty string.

Cheers,
Guillaume Lessard

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #12

I'd run this by someone who actually knows math, but afaik there are
finitely many empty strings in any given string.

How many e's are in any given string? (Ignoring Unicode issues for now,)
for each index in the string's indices, form a substring one character in
length starting at that index and compare the value of that substring to e.

How many empty strings are in any given string? For each index in the
string's indices, form a substring zero characters in length starting at
that index and compare the value of that substring to an empty string.

···

On Wed, Jul 20, 2016 at 17:35 Guillaume Lessard <glessard@tffenterprises.com> wrote:

> On 20 juil. 2016, at 14:21, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
>
> Doesn't your second argument undermine your first? If it's a trivial
solution and one rarely ever considers empty strings when invoking
`hasPrefix`, then returning the technically correct result must be a
trivial departure in behavior.

I specifically used an example where the trivial solution (y=0 instead of
y=exp(x)) is a pitfall.

How many empty strings are contained in any given string?
If the answer is infinitely many, it sounds like a pitfall to me.

Cheers,
Guillaume Lessard


(Ross O'Brien) #13

To the question of whether any given string has the empty string as prefix:
yes it does. This is a correct answer, and returning true is a correct
behaviour.

To the question of how many times the empty string occurs in a string: yes,
this can be infinite. "a" == "a" + "" == "a" + "" + "" == "a" + "" + "" +
"" == "a" + "" + "" + "" + "" == ... etc.. Concatenating an empty string,
like adding zero or multiplying by zero for a numerical value, can be done
infinitely many times without making a difference.

However, there's correctness and convenience. For example, every integer
can be expressed as a multiple of prime factors. 1 is technically a prime
number - it's divisible by 1 and itself - but for convenience we say it
isn't a prime number, because if it isn't, every integer can be expressed
uniquely as a multiple of prime factors, whereas if it is, there are an
infinite number of such expressions for each integer.

There may be many algorithms which rely on an empty prefix returning false.
If hasPrefix and hasSuffix are corrected, those algorithms should be
altered to recognise that correction. For example, if breaking up a string
using the empty string as a separator, it seems sensible that the sequence
of substrings would never contain consecutive empty strings.

···

On Wed, Jul 20, 2016 at 11:58 PM, Xiaodi Wu via swift-evolution < swift-evolution@swift.org> wrote:

I'd run this by someone who actually knows math, but afaik there are
finitely many empty strings in any given string.

How many e's are in any given string? (Ignoring Unicode issues for now,)
for each index in the string's indices, form a substring one character in
length starting at that index and compare the value of that substring to e.

How many empty strings are in any given string? For each index in the
string's indices, form a substring zero characters in length starting at
that index and compare the value of that substring to an empty string.

On Wed, Jul 20, 2016 at 17:35 Guillaume Lessard < > glessard@tffenterprises.com> wrote:

> On 20 juil. 2016, at 14:21, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
>
> Doesn't your second argument undermine your first? If it's a trivial
solution and one rarely ever considers empty strings when invoking
`hasPrefix`, then returning the technically correct result must be a
trivial departure in behavior.

I specifically used an example where the trivial solution (y=0 instead of
y=exp(x)) is a pitfall.

How many empty strings are contained in any given string?
If the answer is infinitely many, it sounds like a pitfall to me.

Cheers,
Guillaume Lessard

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution