[swift-evolution] Change Request: Make myString.hasPrefix("") and myString.hasSuffix("") return true

Ted F.A. van Gaalen tedvgiosdev at gmail.com
Wed Jul 20 20:52:51 CDT 2016


> On 21.07.2016, at 03:15, Saagar Jha <saagarjha28 at gmail.com> wrote:
> 
> 
> Saagar Jha
> 
> 
> 
>> On Jul 20, 2016, at 18:02, Ted F.A. van Gaalen via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> Hi Nevin,
>> 
>> extension String
>> {
>>     var count: Int
>>         {
>>         get
>>         {
>>             return self.characters.count
>>         }
>>     }
>>     
>>     // Sigh... String subscriptors should be already builtin in the String
>>     
> 
> Swift Strings use grapheme clusters, so subscripting doesn’t really work.
?????? sorry Saagar, but it does! try this code in Swift Playground
I mean that the subscritp functions implemented below could just as well be builtin.
Ted
> 
>>     subscript (idx: Int) -> String
>>         {
>>         get
>>         {
>>             return self.substringWithRange(
>>                 self.startIndex.advancedBy(idx)..<self.startIndex.advancedBy(idx + 1)
>>             )
>>         }
>>     }
>>     
>>     // range subscript [n1..n2] or [n1...n2]
>>     
>>     
>>     subscript (r: Range<Int>) -> String
>>     {
>>         get
>>         {
>>             return self.substringWithRange(
>>                 self.startIndex.advancedBy(r.startIndex)..<self.startIndex.advancedBy(r.endIndex)  )
>>         }
>>      }
>>     
>>     //////////////////////////////////////////////
>>     func hazPrefix(s: String) -> Bool
>>     {
>>         if self.isEmpty && s.isEmpty  // both are empty: match
>>         {
>>             return true
>>         }
>>         
>>         if self.isEmpty || s.isEmpty ||
>>            (s.count > self.count)
>>         {
>>             return false
>>         }
>>         
>>         var match = true
>>         
>>         for i in 0..<s.count
>>         {
>>             if self[i] != s[i]
>>             {
>>                 match = false
>>                 break
>>             }
>>         }
>>         
>>         return match
>>     }
>>     ///////////////////////////////////////////
>> } // end String extensions.
>> 
>> 
>> 
>> let s = "abcdefghijklmnopqrstuvwxyz"
>> let emptystr = ""
>> let emptystr2 = ""
>> 
>> print( s.hazPrefix("abc") )                   // true
>> 
>> print( s.hazPrefix("") )                      // false
>> print( s.hazPrefix("Led Zeppelin.") )         // false
>> print( emptystr.hazPrefix("Swift") )          // false
>> 
>> print(emptystr.hazPrefix(emptystr) )          // true
>> 
>> 
>> Please see further in-line comments below: 
>> 
>> Kind Regards,
>> Ted
>>  
>> 
>>> On 21.07.2016, at 00:57, Nevin Brackett-Rozinsky <nevin.brackettrozinsky at gmail.com <mailto:nevin.brackettrozinsky at gmail.com>> wrote:
>>> 
>>> On Wed, Jul 20, 2016 at 6:32 PM, Ted F.A. van Gaalen via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>> Hi,
>>> 
>>> Mathematical correct or not: 
>>> 
>>> in case of 
>>>      s1.hasPrefix(s2)
>>>          (or any other containment test method) 
>>> 
>>> s1 and s2 are just plain simple instances of String,
>>> nothing more nothing less. 
>>> 
>>> Which is interpreted by me as: 
>>> “test if String s1 starts with String s2”
>>> 
>>> 
>>> …which means, “Do the first n characters of s1 match s2, where n is the length of s2?”
>> Yes,. and of course  s1.count   <= s2.count. 
>>> 
>>> When s2 is the empty string, n is 0.
>> 
>>> 
>>> What are the first 0 characters of s1? Clearly the empty string, since that is the only string with 0 characters.
>>> 
>>> Do the first 0 characters of s1 match s2? Well they are both the empty string, and ""=="" is true, so…
>>> 
>>> That would be a resounding “Yes!”
>> how  dumb (for “”.hasPrefix(“”) ), my mistake. (handled correctly imho in code example above)
>> however, that is a matter of definition:
>> should “search for nothing in nothing” return “true” ??
> 
> Yes. For example, if you’re searching for “a” in the String “a”, you’d return true. Same thing for search for a nothing in a nothing-if the object is what you’re searching for, you can say it contains it.
> 
>> 
>> Again, Strings to me are just character arrays…
>>  
>>> 
>>> Nevin
>>> 
>>> 
>>>  
>>> which, to me,  implies that one will never find an occurrence
>>> of an empty string within another string,
>>> for the very simple reason that an empty string
>>> does not exist within another string. **
>>> Ergo: “false” is the right evaluation when s2.isEmpty.
>>> 
>>> ** In my mental model, a String is just an array of 0...n characters,
>>>   like it is in most languages, very straightforward.
>>> 
>>>  (returning false) This is exactly the reason why NSString does that, 
>>> for more than 20 years, why change it?
>>> 
>>> AFAIK no one has complained about this for years, 
>>> because imho it is logically sound. 
>>> 
>>> for a compiler this is very easy
>>> all it has to do is to return False
>>> when either s1 or s2 is empty.
>>> 
>>> 
>>> Ted
>>> 
>>> 
>>>> On 19.07.2016, at 23:11, Jacob Bandes-Storch <jtbandes at gmail.com <mailto:jtbandes at gmail.com>> wrote:
>>>> 
>>>> Not that it's needed, but another +1 from me.
>>>> 
>>>> a.hasPrefix(p) should be true iff there exists some string x for which p+x == a.  If p == "", then x := a satisfies this, so hasPrefix should return true.
>>>> 
>>>> Jacob
>>>> 
>>>> On Tue, Jul 19, 2016 at 1:29 PM, Jaden Geller via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>> Both `hasPrefix` and `hasSuffix` are analogous to the more general `hasSubset` function, which would return `true` for the empty set.
>>>> 
>>>>> On Jul 19, 2016, at 12:32 PM, Bianca via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>> 
>>>>> > Empty set is a subset of all sets.
>>>>> 
>>>>> True but all sets certainly do not _contain_ the empty set, which is what might be confusing, as the word "contains" in the context of sets implies that it's a member of the set of characters that make up a String. 
>>>>> 
>>>>> On Tue, Jul 19, 2016 at 12:23 PM Charlie Monroe via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>> 
>>>>> > On Jul 19, 2016, at 6:17 PM, Ted F.A. van Gaalen via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>> >
>>>>> > 1.  return “false”  seems to me logically correct, because
>>>>> >     there is never an empty string in another string, and an empty string cannot contain another empty string, right?
>>>>> 
>>>>> Empty set is a subset of all sets.
>>>>> 
>>>>> Just like:
>>>>> 
>>>>> let arr1: [String] = ["Hello", "Swift", "Evolution"]
>>>>> let arr2: [String] = []
>>>>> arr1.starts(with: arr2, isEquivalent: ==) // true
>>>>> 
>>>>> >    This has worked very conveniently for NSString in ObjC for more than 20 years, why change it?
>>>>> >    Do you know of cases that were problematic with this convention?
>>>>> >
>>>>> >
>>>>> > 2  throw a runtime error when trying to do this:
>>>>> >    str.hasPrefix(“”)     //  also for hasSuffix,  str.contains etc.
>>>>> >
>>>>> > some in-line questions below.
>>>>> >
>>>>> > Kind Regards
>>>>> >
>>>>> > Ted
>>>>> >
>>>>> >
>>>>> > On 19.07.2016, at 16:31, Dave Abrahams <dabrahams at apple.com <mailto:dabrahams at apple.com>> wrote:
>>>>> >>
>>>>> >>
>>>>> >> on Tue Jul 19 2016, "Ted F.A. van Gaalen" <tedvgiosdev-AT-gmail.com <http://tedvgiosdev-at-gmail.com/>> wrote:
>>>>> >>
>>>>> >>> Hi Dave
>>>>> >>>
>>>>> >>> “true” ? am I going nuts ? :o)
>>>>> >>>
>>>>> >>> var str = "Hello, playground"
>>>>> >>>
>>>>> >>> print( str.hasPrefix("”)) // case 1 : false
>>>>> >>>
>>>>> >>> print( str.hasSuffix("”)) // case 2 : false
>>>>> >>>
>>>>> >>> print("" == “a” )          // case 3 : false
>>>>> >>>
>>>>> >>> Currently, all cases above evaluate to “false”
>>>>> >>> i think that is correct,
>>>>> >>
>>>>> >> I don't know what to tell you.  It may seem intuitively correct to you,
>>>>> >> but others in the thread have laid out the reasons why it is not
>>>>> >> mathematically correct behavior.
>>>>> > Where? I couldn’t find any.
>>>>> >> One other way of rephrasing it: to get
>>>>> >> `false` for str.hasPrefix(""), you actually need special-case code in
>>>>> >> hasPrefix to check for the empty string,
>>>>> > again, maybe it should throw a run-time error instead.
>>>>> >
>>>>> >
>>>>> >> and the caller may well also
>>>>> >> need special-case code to handle the fact that the result is not
>>>>> >> mathematically consistent with other cases on the continuum.
>>>>> > In this context as “continuum” :
>>>>> >   are you referring to  “sets” or “collections” here?
>>>>> > what other cases?
>>>>> >
>>>>> >> Doing
>>>>> >> things that way doesn't work in practice for real programs.
>>>>> > please explain thank you, because I see no problems at
>>>>> > all with the current NSString-like evaluation…
>>>>> > I’d put an s.isEmpty() in front of it.
>>>>> >>
>>>>> >>> because:
>>>>> >>>
>>>>> >>> How can an empty string be a prefix or suffix value?
>>>>> >>> as there is no empty string present in a non-empty string.
>>>>> >>>
>>>>> >>> Note that if case 1 and case 2 would evaluate to “true”,
>>>>> >>> it would conflict with case 3.
>>>>> >>>
>>>>> >>> Can’t imagine that case 3 should in future also result in “true”
>>>>> >>>
>>>>> >>> ??
>>>>> >>>
>>>>> >>> -----
>>>>> >>>
>>>>> >>> Also I hope that changes to String functionality
>>>>> >>> for Swift 4 are not backward breaking changes
>>>>> >>> even the more for string handling, because Strings
>>>>> >>> are heavily used in most apps.
>>>>> >>>
>>>>> >>> I am firmly convinced that all future releases of Swift
>>>>> >>> should compile Swift 3 and higher source files without
>>>>> >>> any changes 100 % flawlessly! This prevents early diminishing
>>>>> >>> of Swift’s popularity, especially with those building large
>>>>> >>> codebases using Swift.
>>>>> >>>
>>>>> >>> I’ve started a thread about this a week ago,
>>>>> >>> however no one found this important enough to
>>>>> >>> share their opinions with me yet, or were too busy with
>>>>> >>> other subjects to do so.
>>>>> >>>
>>>>> >>> Increasingly I have dreams, me
>>>>> >>> programming complete apps in Smalltalk
>>>>> >>> and then automagically generate
>>>>> >>> an macOS, tvOS or iOS runtime app of it.
>>>>> >>>
>>>>> >>> (I have also dreams of this world becoming
>>>>> >>> a nice and peaceful placebut that is
>>>>> >>> beyond the context of this forum)
>>>>> >>>
>>>>> >>> Kind Regards
>>>>> >>> TedvG
>>>>> >>>
>>>>> >>> www.speyer.de <http://www.speyer.de/>
>>>>> >>>
>>>>> >>>> on Mon Jul 18 2016, Kevin Nattinger <swift-evolution at swift.org <mailto:swift-evolution at swift.org> <mailto:swift-evolution at swift.org <mailto:swift-evolution at 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.
>>>>> >>>>
>>>>> >>>> --
>>>>> >>>> Dave
>>>>> >>>>
>>>>> >>>>
>>>>> >>>
>>>>> >>
>>>>> >> --
>>>>> >> Dave
>>>>> >
>>>>> > _______________________________________________
>>>>> > swift-evolution mailing list
>>>>> > swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>>> > https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>> 
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>> -- 
>>>>> Bianca
>>>>> http://biancatamayo.me <http://biancatamayo.me/>_______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>> 
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>> 
>>>> 
>>> 
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160721/14ff9561/attachment.html>


More information about the swift-evolution mailing list