Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Json.obj Scala, string concat: Compilation error

I'm trying to do the next in Scala, I'm using play2:

val str = "another"
val r = Json.obj("error_type" -> "invalid_request_error",
            "validation_errors" -> (Json.obj(
              "code" -> "this mode " + str + " does not exist",
              "param" -> "mode"
            )))

but it gives to me the error:

Type mismatch, expected: (String, Json.JsValueWrapper), actual: String

but if I do:

val r = Json.obj("error_type" -> "invalid_request_error",
            "validation_errors" -> (Json.obj(
              ("this mode ".+(str)).+(" does not exist"),
              "param" -> "mode"
            ))))

It compile and works...

How can I write it in the form str1 + str2 + str3 more readable? How is the order/precedence related here? In my answer I don't understand why is the () needed neither the comment. Is there another similar case when parenthesis are needed?

ps: I'm not sure if in Java is the same issue

like image 551
A Monad is a Monoid Avatar asked Aug 02 '17 15:08

A Monad is a Monoid


Video Answer


2 Answers

This is easily explained by looking at operator precedence.

From the language reference http://scala-lang.org/files/archive/spec/2.11/06-expressions.html#infix-operations, we can see that operators + and -> have the same precedence. This is because, in general, it is the first character of an operator that determines its precedence. In our case, the first characters are + and -, which both have the same precedence.

thus, writing "code" -> "this mode " + str + " does not exist" is the same as writing:

"code"
  .->("this mode ")
  .+(str)
  .+(" does not exist")

This is consistent with what the compiler tells you:

  • the result type of the first operation ("code" -> "this mode ") is (String, String) which is equivalent to Tuple2[String, String]
  • (String, String) + String triggers an implicit toString() conversion on the tuple, therefore the resulting type is String.

You seem to have already found the better way to format it in a more readable way.

As to other cases were parentheses are needed, the obvious answer would be that you need them as soon as you don't want what the behavior that operator precedence would give you. As such I highly recommend reading chapter 6.12 of the spec linked above!

like image 174
Frederic A. Avatar answered Oct 13 '22 01:10

Frederic A.


Finally I could do it, but I don't know the reason, I someone know, please let me know:

I sorrowed the strings with () and it compiled and works like a charm:

"code" -> ("payment mode " + another + " does not exist"), ...

all together it would be:

Json.obj("error_type" -> "invalid_request_error",
                      "validation_errors" -> (Json.obj(
                        "code" -> ("payment mode " + another + " does not exist"),
                        "param" -> "payment_mode"
                      ))))
like image 29
A Monad is a Monoid Avatar answered Oct 13 '22 01:10

A Monad is a Monoid