1

What is the difference between passing two arguments vs passing one argument?

val option1 = Option(String,String)
and
val option2 = Option(String)
dbc
  • 104,963
  • 20
  • 228
  • 340
G G
  • 1,049
  • 4
  • 17
  • 26

2 Answers2

8

When you write something like Option(1, 2), the compiler first desugars this to Option.apply(1, 2), and then when it sees that the Option companion object doesn't have an apply method that takes two arguments, it automatically converts the arguments into a tuple:

scala> Option(1, 2)
res0: Option[(Int, Int)] = Some((1,2))

It would do something similar for Option(1, 2, 3), Option(1, 2, 3, 4), etc.

This is known as auto-tupling and only works for methods with a single argument. For example, the following won't compile:

scala> def foo[T](t: T, u: T): T = t
foo: [T](t: T, u: T)T

scala> foo(1, 2, 3)
<console>:13: error: too many arguments for method foo: (t: T, u: T)T
       foo(1, 2, 3)
          ^

This "feature" is provided for syntactic convenience, and it brings Scala a little closer (at least in a superficial way) to other functional languages where tuples and function argument lists are more unified. Lots of people hate auto-tupling, though, because these things aren't actually unified in Scala, and pretending they are can lead to confusing code and annoying error messages. If you're one of these people (I am), you can turn on the -Ywarn-adapted-args compiler flag, which gives you warnings when the compiler tries to do this:

scala> Option(1, 2)
<console>:12: warning: Adapting argument list by creating a 2-tuple: this may not be what you want.
        signature: Option.apply[A](x: A): Option[A]
  given arguments: 1, 2
 after adaptation: Option((1, 2): (Int, Int))
       Option(1, 2)
             ^
res0: Option[(Int, Int)] = Some((1,2))

This is a matter of taste, though.

Travis Brown
  • 138,631
  • 12
  • 375
  • 680
  • How come Jörg got a compile error in the other answer? Does auto-tupling not work reliably (can be turned off, or not available in the REPL or something)? – Thilo Mar 11 '17 at 01:30
  • 1
    @Thilo I don't know what code he was actually trying to compile. As far as I know it's not possible to turn auto-tupling _off_, although `-Ywarn-adapted-args` plus fatal errors gets you something similar. – Travis Brown Mar 11 '17 at 01:31
  • @TravisBrown I have RDD[(Int, (Option[String], Option[(Option[String], Option[String])]))]. I can have case(id:Int,option1,optionTuple) and use optionTupel._1 and optionTuple._2 to access the values. Can I have all the options in case like case(id:Int,(option1,optionTupel(tuple1,tuple2))) – G G Mar 11 '17 at 01:54
  • @GG I'm not sure I understand but that sounds like it should be a new question of its own. – Travis Brown Mar 11 '17 at 02:01
  • @Thilo: because the OP's code is `Option(String, String)`, whereas Travis's code is `Option(1, 2)`. `1` and `2` *are* values, they are instances of the `scala.Int` class. `String` is *not* a value, it is a *type*. Travis's answer answers a very different question than the OP is asking. – Jörg W Mittag Mar 11 '17 at 07:58
  • 1
    I read the question as contrasting `Option(x, y)` and `Option(x)` for some arbitrary strings or whatever, not about the `String` part specifically, which is a non-starter even for the `Option(String)` case. Maybe the OP can clarify the intent. – Travis Brown Mar 11 '17 at 21:14
1

There is no overload of Option.apply with two arguments, so the simple difference between the two is that the first one gives an error related to the number of arguments:

error: too many arguments (2) for method apply: (x: A)Option[A] in object Option

Whereas the second one gives an error because String is a type, not a value, and you are trying to pass a type as an argument, which is impossible:

error: object java.lang.String is not a value
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • 1
    I'm not what the OP is asking but I feel like he is asking `Option("Jam Baxter", "Dirty Dike")` vs `Option("Fliptrix")` – prayagupa Mar 11 '17 at 01:52
  • Also should not the error be `object java.lang.String is not a value` for both case? Because `too many arguments for apply` does not make any sense as it takes if you provide real values. eg `Option("Jam Baxter", "Dirty Dike")` – prayagupa Mar 11 '17 at 01:56
  • I cut and pasted the code *directly* from the OP's question, and those were the results I got (and also the results I expected, at least the second one). – Jörg W Mittag Mar 11 '17 at 07:53
  • My best guess is that overload resolution doesn't even look at the arguments if it cannot even find an overload with the right arity. It makes sense, really: why would you want to perform name resolution (which in the Scala type system is Turing-complete, after all!) if you already know that there is no applicable overload anyway! – Jörg W Mittag Mar 11 '17 at 07:55
  • 1
    My answer is addressing the question in prose and yours is taking the example code literally—I guess both are worthwhile until the OP clarifies what they mean. – Travis Brown Mar 11 '17 at 21:22