3

I'm trying out some things in Scala, coming from Python. Since Scala is a lot more strict about keeping types consistent, I was surprised to find out that I can do the following concatenation, which would blow up in Python:

def adder(one:Any, two:String) = {one+two}

adder("word", "suffix")

res13: String = wordsuffix

But also:

val x:Int = 1

adder(x, "suffix")

res12: String = 1suffix

  • So it just transforms an Int into a String w/out telling me. What is this called and what is the logic behind it?

  • And what is the benefit of this? I feel it can come back to bite me, e.g. when dealing with user input to a function.

I know this is not very specific and if this is too broad, I'll gladly retract the question.

1
  • 1
    If your question is really why this is so in Scala rather than how this is done, I suspect that this is done this way because in Java (the main target platform) see 5.4. String Conversion and also in .Net (historical additional target platform) it works that way. And as to why it is there, I think because of the convenience in some typical usages. Commented May 24, 2017 at 1:32

3 Answers 3

5

There is an implicit class in scala.Predef that operates on objects of any type

  implicit final class any2stringadd[A](private val self: A) extends AnyVal {
    def +(other: String): String = String.valueOf(self) + other
  }

That implements Any + String (as you have defined it in adder). As rogue-one mentioned, there is also a method for concatenating String + Any defined in StringOps. If you tried to do Any + Any it would fail because it's expecting a String as the argument.

So it just transforms an Int into a String w/out telling me

Scala is converting your Int into a String, but it's not a type conversion because Int cannot be coerced into a String. You can observe that by trying something like this:

def foo(str: String) = ???
foo(5)  // Type mismatch: expected: String, actual: Int

That will fail to compile because Scala can't magically coerce an Int into a String.

what is the logic behind it?

See implicit classes

And what is the benefit of this? I feel it can come back to bite me, e.g. when dealing with user input to a function.

It's a convenience method that's very specific to String and concatenation. This feature is implemented in Java, so I believe it was implemented in Scala to maintain source compatibility. My example above shows that (except in this specific case), user input to a function will respect the types defined on the function.

Sign up to request clarification or add additional context in comments.

3 Comments

also @rogue-one Thanks, that makes sense! Just so I get it right, this works because: this specific instance of + has a String on one side, where + is implemented this way; and: the Any is treated as a String no matter what cause that's what the Scala designers found most sensible in this setting?
Yup that's right. Any other type on the right (e.g. Any + Any) would produce an error.
Actually I think it's less to do with Scala designers thinking it's a good idea, and more to do with being compatible with Java because Java allows you to concatenate objects with String magically.
2
  • It's called implicit conversion (or implicit typecasting)
  • The purpose - convenience so you don't have to do everything manually. Most high-level languages will do that with the most used generics like strings, ints, bools...

You can check scala.Predef to see all the methods used when implicitly converting types, and you can take control of it using scala.language.implicitConversions. Read more at Scala Documentation.

Comments

1

This String concatenation not only works for Int but for any data-type. For instance

scala> case class Elephant(value: String)
defined class Elephant

scala> "Hello" + Elephant("elephant")
res2: String = HelloElephant(elephant)

This is because of the method + defined in StringOps (via Predef) class that accepts argument of type Any. So it is a method that is made available to a String object via implicit conversion that takes an argument of type Any. so "Hello" + Elephant("elephant") is actually "Hello".+(Elephant("elephant"))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.