Declarative String Processing Overview

I think this is a good time to consider adding union types to the standard library. We could make them using enumerations:

enum UnionOf2<First, Second> {
    case first(First)
    case second(Second)
}
// as well as UnionOf3, UnionOf4, etc.

or we could add union types to the language itself, similarly to tuples:

let x = (String | Int).0("example")
switch x {
case .0(let string):
    print(0, string)
case .1(let number):
    print(1, number)
}
let namedExample = (string: String | number: Int).string("example")

While the second one would be a more complex change, it would allow for infinitely many types within the union.

Union types would provide a good way to express regular expressions like this:

let r = /(\w+)|(\s+)/
print(type(of: r))
// prints RegEx<UnionOf2<Substring, Substring>>
// or prints RegEx<(Substring | Substring)>

Note that these union types aren’t the same as the union types mentioned in the commonly-rejected proposals list — they are fully compatible with Swift’s type system.

Union types have also been recently discussed in the precise error typing thread.


Yeah, after further consideration, I don’t think it’s a good idea to reuse " — regexes are different enough from strings that we’d want different syntax highlighting, and we wouldn’t be able to highlight regexes differently than strings if we reused string literal syntax (unless we added type inference to the syntax highlighting algorithm, which would create its own problems). I think #/.../# is an acceptable syntax, though we should still try to think of alternatives. Ideally the syntax we end up using would support a raw string–like syntax (i.e. #####/file/path/#####). I don’t think it’s as important to have multi-line syntax or inline comments — Patterns can be used to achieve a similar effect and inline comments aren’t allowed within multi-line strings anyway.

line.match {
    /([0-9A-F]+)/          // Hex scalar
    /(?:\.\.([0-9A-F]+))?/ // Optional scalar range
    /\s*;\s/               // Separator
    /(\w+)/                // Property
    /.*/                   // Ignore rest
}