Applying Regex to Substring

Many methods on String return Substring. I found myself wanting to use a Regex to parse part of one of these substrings recently, but found that Regex only works on a full String.

Is there a reason that Regex could not work with Substrings as well?

8 Likes

@bjhomer What APIs are you exactly missing? I've just tested and the ones I personally would expect seem to work with Substring, too. Running this code in a playground worked as expected:

import Foundation

let string: String = "Hello, world!"
let substring: Substring = string.split(separator: ", ").first!

let regex = /abc/
string.matches(of: regex) // => []
substring.matches(of: regex) // => []

Can you be more specific? To me it seems like Substring is already supported ...

Ah, interesting. What I'm actually seeing is that although regexes support both String and Substring arguments, they don't support StringProtocol. I have a bunch of functions like this:

func parseLine(_ line: some StringProtocol) {
  let regex = /You earned (\d+) points by collecting (\d+) gems/
  if let match = try regex.wholeMatch(in: line) {
    // use the match here
  }
}

This makes it easy for me to pass it a Substring that arises as part of parsing a file line-by-line, but I can also test it individually by passing an individual string. But I get the error:

// error: No exact matches in call to instance method 'wholeMatch'

… because wholeMatch doesn't take a some StringProtocol. It only has concrete overrides for String and Substring.

I wonder if it would be possible to define the regex operations in terms of StringProtocol

7 Likes

This idea was considered and dismissed by one of the authors of SE-0357 in its review thread:

Instead of using StringProtocol, why not just use Substring? You can easily create a Substring from a String like so:

let substring = "string"[...]