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

Saagar Jha saagarjha28 at gmail.com
Wed Jul 20 23:32:26 CDT 2016


Sorry, my word choice here is poor. I meant that Swift Strings don’t really match up with character arrays in the usual sense; your “subscript” is O(n). Use a Range instead.
Saagar Jha



> On Jul 20, 2016, at 18:52, Ted F.A. van Gaalen <tedvgiosdev at gmail.com> wrote:
> 
>> 
>> On 21.07.2016, at 03:15, Saagar Jha <saagarjha28 at gmail.com <mailto: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/20160720/bc504650/attachment.html>


More information about the swift-evolution mailing list