www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Deprecation of implicit string concatenation

reply Johan Engelen <j j.nl> writes:
Since 2.072, implicit string concatenation is deprecated [1].
Can someone give me a link to the discussion about this?

I am wondering about the language spec changes involved.

```
   "abc"
   "def"
```
means something different than
```
   "abc"
   ~ "def"
```
right? (for example because opBinary!(“~”) can be overloaded)
The first one will apparently no longer be allowed in the future.

Did we lose the ability to break strings across lines?

Thanks,
   Johan

[1] 
https://dlang.org/changelog/2.072.0.html#deprecated_implicit_cat
Apr 02 2017
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2017-04-02 11:22, Johan Engelen wrote:
 Since 2.072, implicit string concatenation is deprecated [1].
 Can someone give me a link to the discussion about this?

 I am wondering about the language spec changes involved.

 ```
   "abc"
   "def"
 ```
 means something different than
 ```
   "abc"
   ~ "def"
 ```
 right? (for example because opBinary!(“~”) can be overloaded)
It's not possible to overload operators for the built in types, or am I missing something? -- /Jacob Carlborg
Apr 02 2017
parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sunday, April 02, 2017 11:47:52 Jacob Carlborg via Digitalmars-d wrote:
 On 2017-04-02 11:22, Johan Engelen wrote:
 Since 2.072, implicit string concatenation is deprecated [1].
 Can someone give me a link to the discussion about this?

 I am wondering about the language spec changes involved.

 ```

   "abc"
   "def"

 ```
 means something different than
 ```

   "abc"
   ~ "def"

 ```
 right? (for example because opBinary!(“~”) can be overloaded)
It's not possible to overload operators for the built in types, or am I missing something?
No, it's definitely not possible to overload operators on built-in types. Overloaded operators must be member functions. You can't even add an overloaded operator to a user-defined type that you don't control via UFCS, let alone add an overloaded operator to a built-in type. So, there's zero risk of anyone messing with the semantics of "abc" ~ "def". And I'm not aware of any difference in semantics between "abc" "def" and "abc" ~ "def" In theory, the compiler could choose to do the concatenation at runtime in the second case, but it does it at compile time. And that's the only possible difference that I'm aware of that there even could be. As to why the change was made, it was made because of all of the bugs caused by missing a comma or ~ when dealing with string literals. Those bugs are caught if implicit concatenation is illegal, and it's not much more verbose to have to use ~. Also, the intention of the code is clearer. But the main motivator is to catch bugs. It's a lot like how having if statements or loops with ; as their body is illegal in D. You can use {} instead, so you don't lose any expressiveness, but it prevents some common bugs which can be very easy to miss and hard to find. - Jonathan M Davis
Apr 02 2017
parent reply Johan Engelen <j j.nl> writes:
On Sunday, 2 April 2017 at 10:05:57 UTC, Jonathan M Davis wrote:
 On Sunday, April 02, 2017 11:47:52 Jacob Carlborg via 
 Digitalmars-d wrote:
 On 2017-04-02 11:22, Johan Engelen wrote:
 Since 2.072, implicit string concatenation is deprecated 
 [1]. Can someone give me a link to the discussion about this?

 I am wondering about the language spec changes involved.

 ```

   "abc"
   "def"

 ```
 means something different than
 ```

   "abc"
   ~ "def"

 ```
 right? (for example because opBinary!(“~”) can be overloaded)
It's not possible to overload operators for the built in types, or am I missing something?
No, it's definitely not possible to overload operators on built-in types.
This is not about overloading of built-in types. It is about the code text `"abc" ~ "def"` and `"abc" "def"` not being equivalent. I am afraid the deprecation happened without careful thought behind it, because the deprecation text shows only the simplest of cases. It does not show a case where the ~ operator is used as part of a larger expression and together with operator overloading. ``` import std.stdio; class A { A opBinary(string op)(string rhs) { writeln(rhs); return this; } } void main() { A a = new A(); a ~ "abc" ~ "def"; a ~ "abc" "def"; } ``` - Johan
Apr 02 2017
next sibling parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sunday, April 02, 2017 10:55:22 Johan Engelen via Digitalmars-d wrote:
 On Sunday, 2 April 2017 at 10:05:57 UTC, Jonathan M Davis wrote:
 On Sunday, April 02, 2017 11:47:52 Jacob Carlborg via

 Digitalmars-d wrote:
 On 2017-04-02 11:22, Johan Engelen wrote:
 Since 2.072, implicit string concatenation is deprecated
 [1]. Can someone give me a link to the discussion about this?

 I am wondering about the language spec changes involved.

 ```

   "abc"
   "def"

 ```
 means something different than
 ```

   "abc"
   ~ "def"

 ```
 right? (for example because opBinary!(“~”) can be overloaded)
It's not possible to overload operators for the built in types, or am I missing something?
No, it's definitely not possible to overload operators on built-in types.
This is not about overloading of built-in types. It is about the code text `"abc" ~ "def"` and `"abc" "def"` not being equivalent. I am afraid the deprecation happened without careful thought behind it, because the deprecation text shows only the simplest of cases. It does not show a case where the ~ operator is used as part of a larger expression and together with operator overloading. ``` import std.stdio; class A { A opBinary(string op)(string rhs) { writeln(rhs); return this; } } void main() { A a = new A(); a ~ "abc" ~ "def"; a ~ "abc" "def"; } ```
True, those two statements are slightly different. I hadn't thought of that case. However, all you have to do is put parens around the string concatenation, and it's not an issue. I don't see why it would be a big deal at all. At most, it simply means that anyone changing code that purposely used implicit string concatenation is going to need to be aware of how there's a difference when dealing with a user-defined type. For the vast majority of cases, there is no difference whatsoever, and in some - if not most - cases, it'll actually catch bugs in the code, because most people don't use implicit string concatenation on purpose. I fail to see why deprecating implicit string concatenation would be a problem. Most of us agree that it's an anti-feature that makes it harder to catch bugs related to string literals, and it's perfectly possible to concatenate string literals explicitly. And if the problem is the deprecation message, well, you can only put so much in a deprecation message without making it too long. But if you have a suggestion for how the message could be better, feel free to open up an enhancement request for it over even to create a PR. - Jonathan M Davis
Apr 02 2017
parent Jacob Carlborg <doob me.com> writes:
On 2017-04-02 13:14, Jonathan M Davis via Digitalmars-d wrote:

 And if the problem is the deprecation message, well, you can only put so
 much in a deprecation message without making it too long.
It could contain a link to some documentation explaining it in more detail. -- /Jacob Carlborg
Apr 02 2017
prev sibling parent reply David Nadlinger <code klickverbot.at> writes:
On Sunday, 2 April 2017 at 10:55:22 UTC, Johan Engelen wrote:
   a ~ "abc"  "def";
If the order is important, make it `a ~ ("abc" ~ "def")` instead. I'd argue that with concatenation usually being left-associative, clearly stating the intention to evaluate the side first would be a good idea anyway. But even if you didn't agree with this line of thought, wouldn't having to add a pair of parentheses here and there be a small price to pay for avoiding a very real source of bugs? Or are you just worried about the deprecation message leading people into inadvertently introducing a behaviour change when they just mechanically applied the fix to the code? — David
Apr 02 2017
parent reply Johan Engelen <j j.nl> writes:
On Sunday, 2 April 2017 at 11:44:16 UTC, David Nadlinger wrote:
 On Sunday, 2 April 2017 at 10:55:22 UTC, Johan Engelen wrote:
   a ~ "abc"  "def";
If the order is important, make it `a ~ ("abc" ~ "def")` instead. I'd argue that with concatenation usually being left-associative, clearly stating the intention to evaluate the side first would be a good idea anyway. But even if you didn't agree with this line of thought, wouldn't having to add a pair of parentheses here and there be a small price to pay for avoiding a very real source of bugs? Or are you just worried about the deprecation message leading people into inadvertently introducing a behaviour change when they just mechanically applied the fix to the code?
I've been thinking for some time now about making a good code formatter, and the removal of the automatic concat (and the necessity of parens) makes automatic reformatting of code _a lot_ harder. About the deprecation message: perhaps the parentheses should be included to guarantee no behaviour change. It's important to be able to trust the compiler. But I am happy to see some thought went into this: https://forum.dlang.org/post/ibhug0$3065$1 digitalmars.com https://issues.dlang.org/show_bug.cgi?id=3827 It'd help to have such links in the release notes or in the deprecation description. -Johan
Apr 02 2017
parent Jacob Carlborg <doob me.com> writes:
On 2017-04-02 16:20, Johan Engelen wrote:

 I've been thinking for some time now about making a good code formatter,
 and the removal of the automatic concat (and the necessity of parens)
 makes automatic reformatting of code _a lot_ harder.
Assuming you're thinking of splitting up lines that are too long. In my opinion, splitting up string literals should only be chosen as one of the last resorts. For example the Clang formatter, at least in the beginning, only modifies whitespace. -- /Jacob Carlborg
Apr 04 2017
prev sibling parent reply Tobias Pankrath <tobias pankrath.net> writes:
On Sunday, 2 April 2017 at 09:22:38 UTC, Johan Engelen wrote:
 Did we lose the ability to break strings across lines?
 [1] 
 https://dlang.org/changelog/2.072.0.html#deprecated_implicit_cat
Delimited strings are the way to go. http://dlang.org/spec/lex.html#StringLiteral
Apr 02 2017
parent Johan Engelen <j j.nl> writes:
On Sunday, 2 April 2017 at 10:02:09 UTC, Tobias Pankrath wrote:
 On Sunday, 2 April 2017 at 09:22:38 UTC, Johan Engelen wrote:
 Did we lose the ability to break strings across lines?
 [1] 
 https://dlang.org/changelog/2.072.0.html#deprecated_implicit_cat
Delimited strings are the way to go.
So how does that work with indentation? ``` //... ~ "abc" "def"; ``` - Johan
Apr 02 2017