String Concatenation Operator + Ambiguity

298 views Asked by At

I am currently working on a JVM-based programming language that supports operator overloading and custom operators. I wanted to stick to Java and use the + operator for String concatenation, and this is implemented and works flawlessly in my language. However, the operator is also used in various other places, for example to add elements to a collection:

public interface Collection[E]
{
    // ...
    public Collection[E] +(E element)
    // ...
}

List[String] strings = List()
List[String] strings2 = strings + "a"

As you can see, there is an ambiguity here: strings + "a" can either mean 'call the + method of Collection to add an element to the strings' or 'convert strings to a String and append the String "a" to that String`. For the second meaning, the above code would generate a compile-time type error, which is currently what happens if you were to type this code in my language.

How would I go about solving this ambiguity, and how do other languages with operator overloading and + for String concatenation (e.g. Scala, Xtend, ...) handle this problem?

3

There are 3 answers

0
iAdjunct On BEST ANSWER

If you're worried about that (which you should be), then define it.

Python has a concept of a reverse-operator in addition to the normal forward-operators. There is a defined method by which these work.

C++ takes the approach of "there's no such thing as a reverse-operator, but things can be casted." By Python's rules, your example would be:

Python would do this:

  • Does 'List[String]' have a + operator? Yes
  • Call it.
  • It returned NotImplemented? Darn. Does 'String' have a reverse+ operator?
  • If so, call it.

C++ would do this:

  • Are there any overloads of operator+ that match the arguments through an standard conversion sequence or template substitution? Yes: List[String]'s operator+ (which appends).

Now, if that weren't so, it'd do this next:

  • Are there any overloads of operator+ that match the arguments through a user-defined conversion sequence?

This, if necessary, goes through the list of all possible operator+ functions and sees if the arguments can undergo a constructor-based or operator-based cast to fit them to the function or a template instantiation of the function. THIS is when it would attempt to cast List[String] to String, but it would probably find that there's no user-defined conversion between a List[String] and a String.

The moral of the story: define it.

0
Binkan Salaryman On

You could evaluate from left to right; strings + "a" then is processed as follows:

  • Look for operator + in the definition of strings which accepts a parameter of the type of "a"
  • Optionally, try again with exchanged parameters, else fail

Read about evaluation of expressions online:

Programming Languages: Principles and Paradigms, chapter 6.1.2/6.1.3

0
svick On

In my opinion, the right way to deal with ambiguity is to produce an error. Your language shouldn't try to guess what the user meant.

But this means that you need to be very careful about not introducing ambiguities in your libraries. Because of that, I think you shouldn't use the same operator for both string and list concatenation.