crystal icon indicating copy to clipboard operation
crystal copied to clipboard

Backslashes in `%w()` misbehave

Open HertzDevil opened this issue 3 years ago • 0 comments

Currently, backslashes inside a %w() string array literal may escape whitespaces and the literal delimiters: (contrast with #5403 where %q() cannot escape its own delimiters)

%w(\ \
\)\() # => [" \n)("]

However, backslashes here also indefinitely extend an escape sequence, and one \ is written for every extra backslash:

%w(\ a)   # => [" a"]
%w(\\ a)  # => ["\\ a"]
%w(\\\ a) # => ["\\\\ a"]
%w(\a)    # => ["\\a"]
%w(\\a)   # => ["\\\\a"]
%w(\\\a)  # => ["\\\\\\a"]

Consequently, it is not possible to use a backslash at the very end of an array, as any number of \s followed by the end delimiter merely escapes that delimiter:

%w(\) # Error: Unterminated string array literal
%w(\\) # Error: Unterminated string array literal
%w(\\)
#) # => ["\\)", "#"]

Here are the same literals in Ruby:

%w(\ a)   # => [" a"]
%w(\\ a)  # => ["\\", "a"]
%w(\\\ a) # => ["\\ a"]
%w(\a)    # => ["\\a"]
%w(\\a)   # => ["\\a"]
%w(\\\a)  # => ["\\\\a"]

%w(\)  # Error: unterminated list meets end of file
%w(\\) # => ["\\"]

%w(\\) # => ["\\"]
#)

I think we should follow suit and make \ escape only the following character. Like #5403, however, we should decide whether this would constitute a breaking change.

HertzDevil avatar Jul 16 '22 03:07 HertzDevil