[swift-evolution] [Pitch] Raw mode string literals

Xiaodi Wu xiaodi.wu at gmail.com
Thu Nov 23 12:35:30 CST 2017


This proposed addition addresses a known pain point, to be sure, but I
think it has many implications for the future direction of the language and
I'd like to explore them here.

The tl;dr version is that I'm not sure this is the right direction in which
to head to address the issue of regex ergonomics, and that the issue also
implicates other weaknesses in terms of literals for which I think the
solution exacerbates rather than solves the underlying problem. [Chris's
email just came through and cut to the meat of it, but I'll keep writing
this email and complete my thoughts.]

We've been talking on this list for quite some time about supporting `/this
syntax/` for a regex literal. Whether this can be accomplished or not
within the Swift 5 timeframe (and I think a reasonable barebones
implementation could be), the question here is whether your proposed
addition serves any useful purpose in a future version of Swift in which we
do have such a literal. After all, your motivation (and a very valid one)
is that regex literals are too difficult to type. I very strongly believe
that the solution here is what we've been talking about all along: actual
regex literals.

We should certainly move any discussion about regex literals into its own
thread, but to make it clear that I'm not simply suggesting that we
implement something in Swift 10 instead of addressing a known pain point
now, here's a sketch of how Swift 5 could make meaningful progress:

- Teach the lexer about basic /pattern/flag syntax.
- Add an `ExpressibleByRegularExpressionLiteral`, where the initializer
would be something like `init(regularExpressionLiteralPattern: String,
flags: RegularExpressionFlags)` where RegularExpressionFlags would be an
OptionSet type.
- Add conformance to `ExpressibleByRegularExpressionLiteral` to
`NSRegularExpression`.
- Have no default `RegularExpressionLiteralType` for now so that, in the
future, we can discuss and design a Swift standard library regular
expression type, which is justifiable because we've baked in language
support for the literal. This can be postponed.

Now, suppose we can motivate "raw" strings with some other use case. The
proposed syntax remains problematic and I'd like to discuss that for a
little bit.

I believe it was Chris who originally explained some time ago that it was a
deliberate design decision not to have little dangling bits on literals
such as "1.0f", opting instead for more readable spellings such as "1.0 as
Float". This `r` prefix is clearly undoing that deliberate design decision
and inconsistent with the direction of Swift. There are other options here,
should a use case arise that successfully motivate "raw" strings. For
example, one might be to use the long-reserved single-quoted 'string
literal' for this purpose, if this is judged to be a significant enough
feature that can justify it.

But there's another matter here that I'd like to touch on. Namely, for all
literal types, the `ExpressiblyBy*` protocols expose a processed version of
the literal. This leads to various issues that require hacky workarounds at
best. For instance, BigInt types can't initialize arbitrarily large values
with integer literals, because the literal has to be representable as a
built-in fixed-width integer; Decimal initializes its floating-point
literal values through a Double intermediary, which can lead to undesirable
results; and so on. What these issues have in common with your use case
here is the inability of `ExpressibleBy*` types to receive the underlying
"raw" literal as it is input. If we could come up with a holistic solution
here, we might be able to dispense with having any distinct syntax for
"raw" strings *and* solve all of these issues at once.


On Thu, Nov 23, 2017 at 11:43 AM, John Holdsworth via swift-evolution <
swift-evolution at swift.org> wrote:

> Hello S/E,
>
> I’d like to put forward a perhaps rather banal change to the Swift lexer
> primarily intended to make entering regular expression patterns easier.
>
> https://github.com/DoubleSpeak/swift-evolution/blob/master/proposals/NNNN-
> raw-string-escaping.md
>
> With a raw literal a string prefixed by “r” the \ character would have no
> special role at all and be processed like any other character i.e.
>
>     r"\n\(var)\n" == "\\n\\(var)\\n"
>
>     r"\?\y\=" == "\\?\\y\\="
>
>     r"c:\windows\system32" == "c:\\windows\\system32"
>
>     r"""
>         Line One\
>         Line Two\
>         """ == "Line One\\\nLineTwo\\"
>
> I had considered another version of the proposal where known escapes
> were still processed but it proved too difficult to reason exactly what was
> contained in the string.
>
> There is a example toolchain available for testing:
>
> http://johnholdsworth.com/swift-LOCAL-2017-11-23-a-osx.tar.gz
>
> Can we shepard this minor additive change into Swift 4.1?
>
> John
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171123/18b1a826/attachment.html>


More information about the swift-evolution mailing list