0.19.3 & master / Mac OS X 10.11.6
Code:
this.is_a.very.long.line.of_a.code \
rescue nil
When I run crystal tool format
,
it merges the lines like:
this.is_a.very.long.line.of_a.code rescue nil
If this is a desired action, having an option to prevent it might be very helpful.
An official formatter is one thing I really love about Crystal..
True, but I don't know, I dislike code that has \
in it, I'd maybe like to remove that from the language...
This is also the reason I never fixed #2517
I agree with @asterite. That syntax, while potentially helpful in some cases, is quite ugly
@iDev0urer Yes. I agree with him too. Even myself haven't used it for the last couple of years. (And I was a little surprised that I somehow wanted to use it in Crystal.)
I am waiting for myself (or anyone) to come up with better ideas. Backslash is helpful in some cases, so if we solve them, then we won't need \
anymore. 馃槈
Would it be an idea to allow operators on a new line in the same way methods can be split across new lines when started with a .
? The backslash-syntax could be removed than. For example, we would be allowed to write:
arr = [] of String
arr
<< "a very long string"
<< "another very long string"
<< "and another very long string"
which currently is a parse error, instead of:
arr = [] of String
arr << \
"a very long string" << \
"another very long string" << \
"and another very long string"
Above is supported now, but rather ugly. The operator has to be at the end, and you need to use a backslash.
You could of course use the version using .
-syntax:
arr = [] of String
arr
.<<("a very long string")
.<<("another very long string")
.<<("and another very long string")
Here you need to think of the parens, otherwise you're calling #<<
on the string instead of the array!
In case of @chaniks example, you'd need parens, as in:
this.is_a.very.long.line.of_a.code(
call.some_very_long.line_code
)
Nice idea. It'd also be necessary to do something like this if we ever reconsider introducing a pipe operator. Disclaimer: I have no idea whether we can actually parse this without further changes.
I'll soon remove the anti-feature of backslash. We have heredoc strings and \
looks ugly at the end of a line. People won't have to learn this in case someone uses it (I never use it) and the formatter and the compiler's code will be a bit simpler.
For strings, there is heredoc, but that removes only indentation and keeps linebreaks. If a long string without linebreaks should be split over several lines for better readability, backslashes are imho the best way. The alternative would be to concat the individual strings.
long_string = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam" \
" nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam"
Without backslash you'd have to write it this way:
long_string = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam "
.+("nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam ")
So I personally don't consider this an anti-feature. While it's not required very often, it is a nice and easy solution to a common problem. This concept is available in many programming languages, so many people would already be familiar with the semantics - and might be surprised if it would not work. For anyone else I find it is very self-explanatory (that's at least my experience when I first encountered a backslash linebreak without having read any documentation about it before) and easier to comprehend for someone inexperienced in Crystal then the alternative (see the above example).
I strongly advocate to consider keeping backslashes in the language. I don't think it inhibits people from learning the language and nobody is forced to use it. At least I have come to a lot of places where I wouldn't miss it because the alternatives are ugly.
Another example where it is not used to connect strings (this was the cause for #4533)
env.evaluate(%("foo http://www.example.com/ bar"|urlize)).should eq \
%(foo <a href="http://www.example.com/"http://www.example.com/</a> bar)
I'm not really convinced this would read better:
env.evaluate(%("foo http://www.example.com/ bar"|urlize)).should eq(
%(foo <a href="http://www.example.com/"http://www.example.com/</a> bar)
)
The correct solution is to remove \
and use +
for long strings. It's a lot clearer what the syntax exactly does and already works. The only problem is that the compiler currently can't recognise that that string can be optimised into 1 constant.
The only problem is that the compiler currently can't recognise that that string can be optimised into 1 constant.
@RX14 exactly, +
is a method call, whereas \
is a language feature. Also, quite known language feature - some of the languages supporting it: bash and other Unix shells, C and C++, Mathematica and Wolfram Language, Python, Ruby.
btw, there was PEP 3125 which tried to remove this feature from Python, yet it was rejected.
Damn, I just figured that this already works:
long_string = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam " +
"nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam "
So for string continuation this would be okish by me but these strings should be concatenated at compile time.
Even if this can be resolved, I'd still like backslash linebreaks to stay a part of the language for usage besides string concatenation, especially with DSLs (like my second example) where it makes a difference between inserting redundant and overcomplicating parenthesis and exceeding line limits.
I added a few rules to the formatter to correctly preserve backslashes. This works in some cases, I believe the most common ones. If you find others please report them, though in most cases line continuations can be indicated with operators, commas, etc.
@asterite There is still an issue with consecutive line continuations:
foo \
"" \
""
is formatted as:
foo \
"" \
""
Most helpful comment
True, but I don't know, I dislike code that has
\
in it, I'd maybe like to remove that from the language...