#2903 StrBuf.plus()

SlimerDude Thu 18 Jan

Hi, may I ask / recommend that StrBuf be enhanced with a plus() function that just calls through to add()?

Why?

str := StrBuf2().add("Because: ")
str += "It would allow users "
str += "to easily concatenate "
str += "strings, just like this!!!"

I find myself using a helper / wrapper class a lot that does it for me.

class StrBuf2 {
  private StrBuf buf := StrBuf()
	
  @Operator
  This plus(Obj obj) { buf.add(obj); return this } 
	
  override Str toStr() { buf.toStr }
}

brian Thu 18 Jan

The problem is that we wouldn't be specifically implementing += (which I agree would be nice). But rather we are implementing + generically. So this would end up adding to the string buffer:

str := StrBuf()
str + "add this"

That seems like an abuse of the add operator because now its essentially mutating the LHS of what looks like in the code as a normal add. And I think its especially confusing that because that code mostly looks like its evaluating to the string concat of str + "add this". So I'm not sure we should be using the add operator to mutate instances

Gary Sat 20 Jan

Not to take away from your original question, Steve - but I'm just starting to play with add() and addAll() with strings and String list arrays. Would the following code snippet be idiomatic Fantom for concatenating Strings with StrBuf(). It compiles and the output is as expected.

strBuff1 := StrBuf().
            add("Only ").
            add("the ").
            add("Fantom ").
            add("knows").
            add("!")

echo (strBuff1)   // Only the Fantom knows!

Gary Sat 20 Jan

As an aside, I had to try this out in D - the tilde ~ operator is used to concatenate strings and dynamic arrays, not to be confused with Lua's ~= which means !=. As you can probably tell, I enjoy comparing syntax between languages :)

import std.stdio;

void main()
{
    auto str = "Because: ";
    str ~= "It would allow users ";
    str ~= "to easily concatenate ";
    str ~= "strings, just like this!!!";

    writeln(str);
}

SlimerDude Mon 22 Jan

Hi Gary,

The StrBuf class is Fantom's version of Java's StringBuffer class - which means it is more optimised for multiple concatenations than using plain Strings. So these statements all elicit the same final result:

str := "Only "
    + "the "
    + "Fantom "
    + "knows!"

str := "Only "
str += "the "
str += "Fantom "
str += "knows!"
        
str := StrBuf()
    .add("Only ")
    .add("the ")
    .add("Fantom ")
    .add("knows!")
    .toStr

Usually I create code using normal Strings, then optimisie it later with a StrBuf. But converting code to StrBuf syntax is awkward, hence this forum post.

StrBuf.join() is a handy method, as it lets you forget about appending trailing spaces.

str := StrBuf()
    .join("Only")
    .join("the")
    .join("Fantom")
    .join("knows!")
    .toStr

It is even more useful when formatting lists of objects, where you may not have control over the string literals themselves.

words := ["Only", "the", "Fantom", "knows!"]
buf   := StrBuf()
words.each |word| {
    buf.join(word)
}
str   := buf.toStr

There is also a join() method on List - which is great for formatting strings.

words := ["Only", "the", "Fantom", "knows!"]
str   := words.join(" ")

Gary Mon 22 Jan

Thank you Steve for the great explanation and sample code. That really helps solidify my Fantom knowledge base. I'm also enjoying your YouTube videos by they way! :) I've been messing around with the Java Stringbuilder class along with a couple other equivalents in other JVM languages comparing informally compile times between naive string concatenation vs string buffer classes (just for grins). I'll start another thread so as not to water down this thread and your original request.

Login or Signup to reply.