Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend string concatenation operator (&) to support StringBuilder as its left operand #114

Open
AnthonyDGreen opened this issue Jun 28, 2017 · 7 comments

Comments

@AnthonyDGreen
Copy link
Contributor

Concatenation is fine for simple cases but we've all had it drilled into us that StringBuilder is the way to go for successively building up large strings, particularly in loops, to avoid creating lots of very large garbage. The problem is that you have to completely change your code to go from one to the other. But, if we extend & to support StringBuilder on the left then most of the code could stay the same using &= and only the declaration of the variable would need to change to reap performance improvements.

In short, StringBuilder & <value> would be defined to be StringBuilder.Append(<value>) and StringBuilder &= <value> would be defined as StringBuilder = StringBuilder.Append(<value>).

@AnthonyDGreen AnthonyDGreen added this to the VB15.x candidate milestone Jun 28, 2017
@reduckted
Copy link
Contributor

I can see the benefits of this, but most of the time when I use a StringBuilder, I'm using AppendLine() instead of Append(). I wonder if there's a way we could work AppendLine() into the design.

Also, I've always found using format strings with StringBuilders cumbersome. I could either

  1. Use Append() to add the individual parts:
    sb.Append("This is ")
    sb.Append(x)
    sb.Append(" hard to read")
  2. Use AppendFormat() to append the entire string, but then lose the benefits of an interpolated string:
    sb.AppendFormat("This is {0} slightly better", x)
  3. Or use an interpolated string, but I presume that reduces the benefits of using a StringBuilder because it performs string concatenation before appending the string to the StringBuilder:
    sb.Append($"This is {x} good, but...")
    ' That's equivalent to:
    sb.Append(String.Format("This is {0} good, but...", x))

Maybe if you concatenated a StringBuilder with an interpolated string, it could equate to an AppendFormat() call. So these two lines would be equivalent.

sb & $"This is {x} awesome"
sb.AppendFormat("This is {0} awesome", x)

@AnthonyDGreen
Copy link
Contributor Author

@reduckted the idea is that you should get the same results so if your code says this today:

Dim str As String = ""
str &= "Line1" & vbCrLf
str &= "Line2" & vbCrLf

You should be able to change the type of str to StringBuilder and get the same results (but more efficiently). In order for that to work we have to use Append even though I agree, I use AppendLine more. Re: AppendFormat I think that's a very reasonable thing to do, especially since String.Format internally allocates a StringBuilder. If we want to really reap the efficiency bonus we should probably do this.

Looking over it more, I think making &= work makes sense (because it's mutating) but making & work doesn't.

@reduckted
Copy link
Contributor

That makes sense, though StringBuilder uses Environment.NewLine (which could just be \n) instead of a strict \r\n.

Your example raises another question. Does sb &= "a" & "b" equate to:

sb.Append("a").Append("b")

or

sb.Append("a" & "b")

Also, don't forget that string concatenation is valid when the left-hand side is null, so this would need to initialise a new StringBuilder:

Dim sb As StringBuilder = Nothing

sb &= "abc"

@xieguigang
Copy link

xieguigang commented Jul 5, 2017

https://github.com/xieguigang/sciBASIC/blob/master/Microsoft.VisualBasic.Architecture.Framework/Scripting/ScriptBuilder.vb

@AnthonyDGreen I'm using & operator for Append and + for AppendLine:

Dim s As New ScriptBuilder

s = s & $"123, this is {test}" ' StringBuilder.Append
s += "456"    ' StringBuilder.AppendLine

@AnthonyDGreen
Copy link
Contributor Author

@xieguigang subtle. Very subtle.

sciBASIC?

@reduckted
Copy link
Contributor

subtle. Very subtle.

Too subtle for my liking. That's just asking for hard-to-find bugs.

@bandleader
Copy link

  1. Could we also do the other way around, for consistency? "A string" & sb should be converted to New StringBuilder.Append("A string").Append(sb.ToString)

  2. @reduckted, sb &= "a" & "b" should of course translate to sb.Append("a").Append("b"), because it's the same operator with same priority, so sb = sb & "a" is executed first and yields a StringBuilder, so the next one (StringBuilderResult) & "b" is executed on a StringBuilder and a String, just like the first time..

3. Regarding AppendLine

With string interpolation, we can simply do s &= $"something{vbCrLf}". Not as clean, and possibly slower, but works.

Another option would be an operator specially for AppendLine like &=|. But I'm reluctant to introduce a new token for something so small...

Maybe the best would be a newline-terminated string literal, which could be used everywhere. "This ends with a newline."- or "Maybe a backslash."\ Just ideas...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants