SE-0200: "Raw" mode string literals

What is your evaluation of the proposal?

I think it's good. The need for raw string literals can be common in certain situations and having a simple syntax for them makes them simple to use.

I doubt this proposal will be enough though. There should be a way to include a double-quote in a raw string literal.

Is the problem being addressed significant enough to warrant a change to Swift?

I think it's worth adding better support for raw strings.

Does this proposal fit well with the feel and direction of Swift?

Some people don't like the r prefix. I don't care much. A one-letter prefix has the advantage of keeping option opens for adding new forms of string literals in the future (we still have many letters to choose from). It'd be nicer if we could do without though, but I appreciate the number of non-alpabetic modifier characters available for this purpose is limited given that string literals are often adjacent to operators.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

The D language has many string literals, including one identical in syntax and semantics to this proposal. As far as I know, it's very useful for file paths on Windows and regular expressions. If you need quotes inside a raw string in D, you can escalate to the delimited string literal which is more versatile but a bit more complicated to parse in your head.

Also, I don't think all those string literals in D makes the language more complicated. It's somewhat obvious what they are in context... except perhaps for D's token string literal which doesn't look like a string at all.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Read the proposal.

New version of proposal

Iā€™ve uploaded a modified version of this proposal here. The changes are that it modified the syntax of a raw literal to #raw(ā€œa raw literalā€) and it expands on the motivation and endeavours to rebut many of the common criticisms encountered thus far. If you have any comments on this version please let me know here while they can easily be changed.

Iā€™ll file a PR on the new version tomorrow to swift-evolution and ask @Douglas_Gregor to merge and reset this review phase If possible. Weā€™ll still have plenty of time to discuss it before the 26th.

John

1 Like

@johnno1962 I object; this seems highly irregular. Ideas should be pitched before they just go to review. I don't see why this proposal is entirely circumventing that well-established process. I thought consensus had been reached to return to the pitch phase.

4 Likes

@xwu , Iā€™m just trying to get things done. I thought Swift was supposed to be more of a Functional language than Procedural :grinning:. The passage of multi-line strings was far from well-established but has had a useful outcome to many.

Itā€™s taken 5 months to make it this far and I think itā€™s good that this has come to review (perhaps prematurely) with a specific proposal as it has focused peoples minds a brought out specific objections and some better specific alternatives one of which I have adopted along with fleshing out the motivation and defences.

The prospect of going back to the pitch phase I donā€™t find attractive. The previous pitch got side tracked and I attempted to open such a discourse yesterday only to be greeted with radio silence. Letā€™s try not take a step back and get to a decision. If itā€™s ā€œno" thats fine but at least this wouldnā€™t be hanging over me. I donā€™t want a repeat of the year long wait from multi-line string PR to release.

John

I, at least, have much to talk about that would be appropriate for a pitch. It sounds like others do as well.

The possible designs for string literals are many, and I would expect that a successful proposal would put in the legwork to explore the entire design space as completely as possible. It sounds like you're trying explicitly to avoid such work. Again, I most strenuously object to such an approach.

2 Likes

Donā€™t hold back. The pitch thread is here: [Pitch] Raw mode string literals. Itā€™s obvious the many PRs you and I have worked on I take a different approach to life than you do. Iā€™d ask you to respect my way of working as I do yours. Itā€™s up to the gatekeepers in the Core team to decide if this proposal can be brought back into review or not. If not, then fine I will persevere until progress canā€™t be made or it is clear there is no interest. For now I am just proposing ways forward. No need to get strenuous! Iā€™m not trying to be unpleasant.

4 Likes

I wish I would read much more welcoming answers. Little mistakes do not deserve such a tactless reaction. If you want to help, @xwu , guide @johnno1962 out of the trap.

3 Likes

Entirely so. I'm recording my objection to that course of action--not because I'm certain that I'll be against the idea you've proposed, but because I'm communicating that I feel it's important for the full and agreed-upon process for approving new ideas to take place. As you know, I felt this proposal to be rushed and incomplete to begin with; I would hate to see it fail not because of merits but because it's being rushed again.

I can very much respect differences of opinion, but if your proposed "way of working" involves not going through the same process that others do in order to put forward their ideas, I must say that I cannot respect that and urge you to reconsider.

Yes, I can understand that objections are unpleasant. It's not a commentary about how I feel about people, or in this case even the proposed idea. But I do strenuously object to the proposed course of action, which is irregular. Not sure how I can phrase that differently. @johnno1962 knows exactly what I believe to be the best way to proceed: returning to the pitch phase as others have mentioned. There is no trap, only more work to be done.

2 Likes

No.

Another solution is for @johnno1962 to revert his changes so that the review keeps on normally. You have no entitlemenr to judge a case alone, and force a return to the pitch phase.

I don't expect much success of the proposal in its current form. Yet I expect a valuable conclusion. I, too, want the topic to move forward.

Sure, @johnno1962 can choose to do that as well. It's my understanding that he wants to withdraw his proposal and have another go at it, instead of having it rejected formally after review (which is a barrier to bringing it back). It also seems sensible not to wait for a review and have a core team decision on a proposal that the author himself doesn't want. I'm not forcing anything at all here.

One use case for raw string literals is for strings which contain code. In this case, a delimiter of " (or even ")) isn't ideal, since it may turn up in the string. Custom delimiters would be a great solution.

#raw(delimiter: "##", ##some.code("here")## )

The #raw ā€˜functionā€™ could then have a default value for the delimiter, allowing for the simpler version quoted.

3 Likes

Oooooo, I really like this, especially with the "default value for the delimiter" bit.

1 Like

Good to hear that you do not want to force anything. Now please give @johnno1962 the time he needs to decide, and eventually get other useful advice that help us all make progress.

Iā€™ve prepared a 4.0 toolchain for #raw(ā€œa literalā€) syntax available here. Please note that as the closing delimiter is ā€œ) according to the new proposal the following is perfectly legit: #raw(ā€œprint ā€œHello World\nā€;") however #raw("some.code(ā€œhereā€)ā€) is not as it will terminate before you expect it to. Iā€™m hoping this will satisfy most of the need for custom delimiters which would be considerably harder to implement. You always have the option of a raw multi-line literal. The PR has not been updated and will not likely reach itā€™s final form until weā€™ve reached a decision and Iā€™ve re-synced to master.

The #raw("...") syntax is too verbose and distracting in my opinion. It also has the wrong syntactic model: it looks like one of those compiler magic functions, but it's actually a modifier flag for the parser with no semantic effect. And it's not necessarily clear that #raw would "returns" a string at a glance.

If I were to pick another syntax for r"...", I'd favor something that is as simple:

#"..."   // basic raw string literal

And then expand it for cases were you want a quote inside:

#("...") // now looking for  ")  as the closing delimiter

And expand it more for when you want a "")" inside:

#(("...")) // looking for  "))  as the closing delimiter

And so on.

3 Likes

Update: While I was typing this, @michelf beat me to it. He is also proposing dropping the word raw, which I am neutral about.

The revised introduction is a big improvement over the original one, but you do not need to get too defensive.

Concerning the revised syntax itself, as you noted ") is not enough as it is itself a very common sequence.

@MutatingFunk's suggestion for a delimiter argument makes it too verbose.

I have an alternate suggestion:

How about we let people define the delimiter on-the-fly like this:

#raw(^/\^"literal string"^\/^) 
// or 
#raw(a`["literal string"]`a) 
// or ... 
#raw(šŸ› "literal string"šŸ› )

Basically the delimiter always starts with ( and ends with ". but you can put a sequence of any characters except another " or parentheses between those. The closing would be reversed (using counterparts such as ] for [ when available).

Based on the nature of the raw string, it should be pretty easy to find an impossible-to-encounter pattern without making it as elaborate as above.

The main issue with my suggestion is that it is a totally unprecedented syntax. Also, I have no idea how hard it would be to handle in the Swift parser.

5 Likes

I'm going to restate my opinions from the original version of the proposal, in an attempt to respond to arguments that I feel have already been addressed: I like the #whatever syntax, and I really think that #raw is too short and doesn't fit in with the current literal syntax (#imageLiteral, #fileLiteral). I'd prefer #rawLiteral or #rawStringLiteral. In addition, I'd like a delimiter argument that would be used like so:

#rawLiteral(delimiter: DELIMITER, value: DELIMITERthis is a raw stringDELIMITER)

delimiter would be defaulted to be ".

I think this is a feature, not a detraction. There will probably be IDE features to make it more convenient to use, as there are currently with the other literals.

This matches the current literal syntax that's already in use. If it's a "magic" compiler function, it's certainly not one without precedent.

See my modifications above, which I think solve this issue.

99% of the time, a custom delimiter will be used for escaping "(). Preventing exactly these characters from the delimiter string seems a perfect way to cause users a lot of frustration.

Yes, that's why I suggest going with my suggestion, which has an established precedent.

Thanks for your feedback. I realized I made a mistake in the characters you can't have between. ( and ". It is only ". For example, you could write #raw(=("literal string")=) but not #raw(=""literal string""=) as it would be ambiguous (is the second " part of delimiter or literal?). For multi-line, the single " becomes """, otherwise, it will be the same. There are other issues about multi-line (indentation, etc) that needs clarification for raw mode, though.

Fair enough. IDE support can make it look really nice. It could hide the actual opening and closing delimiters and automatically choose and update delimeter based on what is actually in the literal string.

On the other hand, I think raw literal support is most useful in Swift as a scripting language scenario and IDE support may not always be present in those cases. That is why I like a short syntax to be feasible for writing and reading plain text of the source code without IDE magic.

That's nice. But if we restrict delimiters to single characters, we can make it even shorter: the delimiter is simply the first (non-space) character after the opening parenthesis:

#raw(^literal string^) 
// or 
#raw(aliteral stringa) 
// or ... 
#raw(šŸ› literal stringšŸ› )
2 Likes

I'm still unhappy with the concession we need to make here. I'd really prefer not putting restrictions on the delimiter if we don't have to.

I find #raw plenty readable. It's short and it's not like it uses any special characters, so it's easy to type as well. The "IDE magic" is only there as a small convenience; it's entirely possible, and relatively straightforward, to write code without it.