String concatenation like in PHP

Absolutely obvious idea, and I don't understand why other programming languages have not implemented that thousand years ago:

"string" . " concatenation" // "string concatenation"

This is the way to remove confustion between + sign for strings and + sign for numbers.

So, what would happen if you tried to use a number with this "." operator? Would it throw a type error? Or try to coerce it into a string?

And what about other operators that fall into a similar boat? Like using obj[attr] for both property access and array entry lookup? Should those be separated out as well, to make it more obvious what you're trying to do. (I know that technically array entry lookup is property access, but on a high level, the two actions are done for different purposes, and a similar argument can easily be made to have a different array lookup operator).

(Also, as a minor note, we would need to pick some other operator, as . already means property access. You wouldn't be able to concatenate two string variables.)

const x = 'hello '
const y = 'world!'
console.log(x . y) // Today this would print undefined, we can't break this behavior.

I'm a little skeptical about how much value this would actually add. I usually don't feel like I get that confused about what the "+" is doing when reading other people's code, it's usually easy to tell from the context. but as I actually think about this more, I do recall an area in my code where I've wanted to concatenate a bunch of items together as a string, some of which were not strings. I had ended up writing it like this:

return '' + a + b + c + d + e

which feels a little icky. Though, I guess an alternative solution would have been to simply coerce the non-string values into strings first.

return String(a) + String(b) + c + String(d) + e
return '' + a + b + c + d + e

...

return String(a) + String(b) + c + String(d) + e

Though these two are also not necessarily equivalent ;)

const o = v => ({
  [Symbol.toPrimitive]([d]) {
    return d === 'd' ? `<${v}>` : `[${v}]`
  }
})
const a = o('a')
const b = o('b')
const c = ' "c" '
const d = o('d')
const e = ' "e" '

console.log('' + a + b + c + d + e) // <a><b> "c" <d> "e" 
console.log(String(a) + String(b) + c + String(d) + e) // [a][b] "c" [d] "e" 

If we cannot use “.” (as does Perl or PHP), we can use “~” (as does Raku) or whatever else. This is not a problem.

The real problem is the legacy “+” operator, for which the legacy semantics will remain unchanged because of BC constraints, as no browser vendor would want to break the web. As a consequence, we are stuck with "1" + 1 == 11.

There's also that "template literals exist", which do all the right things, and just don't happen to involve a binary operator.

2 Likes