# Regex Type: Retrieve String Pattern

**URL:** <https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905>\
**Category:** Using Swift\
**Tags:** regex, predicate\
**Created:** [February 16, 2025, 3:29am UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905 "2025-02-16T03:29:08Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![bdkjones](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bdkjones/32/13872_2.png) [@bdkjones](https://forums.swift.org/u/bdkjones)\
**Post date:** [February 16, 2025, 3:29am UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/1 "2025-02-16T03:29:09Z")

</div>

## Context

I'm attempting to parse Swift Predicates generated by the `#Predicate` macro and turn them into a WHERE clause for querying a Couchbase database via SQL++.

One of these expressions is [stringContainsRegex](https://developer.apple.com/documentation/foundation/predicateexpressions/4341389-build_contains), which takes a `Regex`.

# Question

Regex exposes no public API (that I can find) for retrieving the pattern that was used to initialize the Regex. In other words:

```swift
let regex = /[a-z]/
let pattern: String = regex.pattern // "[a-z]" does not exist.

```

Why does Regex not expose the original pattern? Even a `Regex` built with the RegexBuilder must ultimately be translatable into a standard, string Regular Expression—that's the only thing that's able to leave the boundary of Swift and interact with everything else (SQLite, PHP, etc.)

How does the SwiftData team translate the `Regex` into an SQLite query string?

---

<div class="post-metadata">

**Author:** ![pyrtsa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/pyrtsa/32/740_2.png) [@pyrtsa](https://forums.swift.org/u/pyrtsa)\
**Post date:** [February 16, 2025, 5:20am UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/2 "2025-02-16T05:20:29Z")

</div>

I don't know for sure, but they could be using the underscore API [`_literalPattern`](https://github.com/swiftlang/swift-experimental-string-processing/blob/e1611c5be1bb9306ee697e638dd9eaa7a0f5b136/Sources/_StringProcessing/LiteralPrinter.swift#L37).

---

<div class="post-metadata">

**Author:** ![bdkjones](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bdkjones/32/13872_2.png) [@bdkjones](https://forums.swift.org/u/bdkjones)\
**Post date:** [February 16, 2025, 8:30am UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/3 "2025-02-16T08:30:30Z")

</div>

Thanks. The natural followup is: if `_literalPattern` is reliable and ready for SwiftData, why is it private API instead of public?

(I don't deal with App Stores, so `_literalPattern` will suffice for now.)

---

<div class="post-metadata">

**Author:** ![paiv](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/paiv/32/4041_2.png) [@paiv](https://forums.swift.org/u/paiv)\
**Post date:** [February 16, 2025, 12:47pm UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/4 "2025-02-16T12:47:06Z")

</div>

I don't know the status of the current implementation, but it was mentioned in the proposal as a future direction

> <https://github.com/swiftlang/swift-evolution/blob/main/proposals/0351-regex-builder.md#conversion-to-textual-regex>

Related: [Any way to get raw regex literal from RegexBuilder?](https://forums.swift.org/t/any-way-to-get-raw-regex-literal-from-regexbuilder/58327)

---

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [February 16, 2025, 4:01pm UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/5 "2025-02-16T16:01:44Z")

</div>

In general, Regexes do not have a “literal pattern” (the builder syntax allows you to construct a Regex that cannot be represented as a literal or string).

Predicate is OK working within the limitations imposed by that, which is why the SPI exists, but it’s not obvious that it makes for a great API. If there are other uses that make good sense within the semantic limitations, I’d be open to making it available as API, but so far not many have come forward.

---

<div class="post-metadata">

**Author:** ![bdkjones](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bdkjones/32/13872_2.png) [@bdkjones](https://forums.swift.org/u/bdkjones)\
**Post date:** [February 16, 2025, 6:48pm UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/6 "2025-02-16T18:48:46Z")

</div>

I think it ought to be public.

First, 90% of Regexes are going to be “mainstream” expressions that are representable as a literal pattern. Match an email. Match a phone number. Etc. The proportion of Regexes that leverage Swift-only features is probably small, no?

Second, what’s the downside? The SPI already returns an optional. Why prevent developers who DO need the capability from having it just because it’s not “common enough”? There are public capabilities (parsing Predicate expressions) that are blocked because this is private. Developers can handle the cases where a Regex has no literal pattern equivalent.

---

<div class="post-metadata">

**Author:** ![bbrk24](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bbrk24/32/27370_2.png) [@bbrk24](https://forums.swift.org/u/bbrk24)\
**Post date:** [February 16, 2025, 7:03pm UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/7 "2025-02-16T19:03:47Z")

</div>

I remember at one point making a custom type that effectively just wrapped a Regex and could only be initialized by a String, but because it needed to be `LosslessStringConvertible`, I had to store both the Regex and the String so that I could use the latter for `description` and nothing else. I asked about it on StackOverflow at the time (over two years ago now): [How to convert a Swift 5.7 Regex back to a string? - Stack Overflow](https://stackoverflow.com/questions/73903862/how-to-convert-a-swift-5-7-regex-back-to-a-string) -- and it seems like @bdkjones just left an answer about the private API.

---

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [February 16, 2025, 8:12pm UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/8 "2025-02-16T20:12:22Z")

</div>

> [@bdkjones](#):
>
> Match an email. Match a phone number

These are both classic examples of things that are a pain in the butt to do correctly with a regex (and most regexes you see for them will be wrong in some way), but a custom Regex wrapping a data detector can do very cleanly.

---

<div class="post-metadata">

**Author:** ![bdkjones](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bdkjones/32/13872_2.png) [@bdkjones](https://forums.swift.org/u/bdkjones)\
**Post date:** [February 16, 2025, 9:15pm UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/9 "2025-02-16T21:15:18Z")

</div>

> seems like @bdkjones just left an answer about the private API.

Ha, yep. Your question was the start of this latest rabbit hole.

> These are both classic examples of things that are a pain in the butt to do correctly with a regex (and most regexes you see for them will be wrong in some way), but a custom Regex wrapping a data detector can do very cleanly.

_Everything_ is a pain in the butt to do with Regex. But nothing about that justifies keeping `_literalPattern` private. Developers inside of Apple clearly had a need to represent Regex as a string. Developers outside of Apple have the same need.

If there’s demand for the ability and the private API isn’t unstable or full of footguns or still undergoing major, breaking revisions, it should be available. The “eh, we just haven’t had enough use cases yet” doesn’t make a lot of sense—the cases that DO exist are valid and helpful.

---

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [February 16, 2025, 9:28pm UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/10 "2025-02-16T21:28:59Z")

</div>

It is full of footguns—namely that it can fail (and frequently will), contrary to many developers expectations, as demonstrated by this thread.

That’s not insurmountable, but “what will your fallback be when the Regex doesn’t have a string representation” is a real issue (and if you want to disallow those cases, there’s already pretty good API for that—you use the string representation that you already have). It’s a perfectly reasonable pitch, but someone has to write it.

---

<div class="post-metadata">

**Author:** ![bdkjones](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bdkjones/32/13872_2.png) [@bdkjones](https://forums.swift.org/u/bdkjones)\
**Post date:** [February 16, 2025, 9:39pm UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/11 "2025-02-16T21:39:15Z")

</div>

> and if you want to disallow those cases, there’s already pretty good API for that—you use the string representation that you already have)

?  
I don’t have a string representation. The Predicate expression hands me a `Regex` needle and a KeyPath to the haystack. If I _had_ a string representation of the needle, I wouldn’t need this.

As for what to do if `_literalPattern` returns nil: in my case, I throw an error saying that the `#Predicate`’s regex can’t be transformed into an SQL++ query. Thats not a big issue and having the ability to handle 80% of Regexes is better than having the ability to handle 0% of them.

---

<div class="post-metadata">

**Author:** ![bdkjones](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bdkjones/32/13872_2.png) [@bdkjones](https://forums.swift.org/u/bdkjones)\
**Post date:** [February 16, 2025, 9:49pm UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/12 "2025-02-16T21:49:07Z")

</div>

I don’t really have a dog in this fight anymore. The private API will work perfectly for me.

I’m just pushing back against the idea that there isn’t “enough” demand for the feature to justify exposing it publicly. There _is_ demand. And while it may not be super common, the people who need this ability have _zero_ other workarounds (if they’re dealing with App Stores).

Sure, it can fail in edge cases. But the documentation comment makes that very clear. Publish the API with that warning and let developers cover the 80% of cases that work just fine.

---

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [February 16, 2025, 10:42pm UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/13 "2025-02-16T22:42:59Z")

</div>

Putting the public API on Predicate (or whatever other type/macro wraps a regex) would probably be cleaner in this case, because by the time it’s a predicate, you already have the necessary guarantee. But sure, exposing the building block would also be useful in other cases. It only needs someone to write a proposal.

---

<div class="post-metadata">

**Author:** ![bdkjones](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bdkjones/32/13872_2.png) [@bdkjones](https://forums.swift.org/u/bdkjones)\
**Post date:** [February 17, 2025, 6:15am UTC](https://forums.swift.org/t/regex-type-retrieve-string-pattern/77905/14 "2025-02-17T06:15:03Z")

</div>

> [@scanon](#):
>
> you use the string representation that you already have

Ah, I see what you mean now. (Should not pull up this stuff on iPhone screens; I saw `Regex` in the signature but did not pay close enough attention to the type.). The `Regex` in the predicate expression is `PredicateRegex`, which already has a `stringRepresentation` populated. That's fair for this case, but I still see no reason to keep `_literalPattern` private just because it won't work for every conceivable Regex.

It's a great tool to have when you need it, which will virtually always be at the boundary between Swift and some other language.
