Question: I have a C# project developed with VS2017. 

The *server* on which Jenkins runs doesn't have VS installed. I have .NET 4.7 installed on the *dev* computer and the *server*.

This is what I get when I type msbuild.exe /version:

Microsoft (R) Build Engine version XXX(see below)

* On dev, I have 2 MSBUILD.exe: 

	+ C:...\MicrosoftVisualStudio\2017\Pro\MSBuild\15.0\Bin: 15.1.1012.6693
	+ C:\Windows\Microsoft.NET\Framework\v4.0.30319: 4.7.2053.0
* On server: C:\Windows\Microsoft.NET\Framework\v4.0.30319: 4.7.2053.0

I assume that when I build a project in VS2017, it uses the MSBUILD.exe located in the MicrosoftVisualStudio folder.

I'm concerned now to build on the Jenkins machine with a different version of MSBUILD.exe? What would be the best approach? Copy the folder *C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild* to the Jenkins computer?

Answer: 
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!
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"
                      ))))

```