10

In Haskell you can write:

x :: (Int,Int) -> Int
x (p,s) = p

In Scala you would write:

def x(a: (Int, Int)) = a._1

or:

def x(a: (Int, Int)) = a match {
    case (p, s) => p
}

Why not have something like

def x(_: (p: Int, s: Int)) = p

or

def x(foo: (p @ Int, s @ Int)) = p

?

letmaik
  • 3,348
  • 1
  • 36
  • 43
  • That kind of pattern matching wouldn't very useful if you can have only *one* method definiton. You would need multiple definitions like in Haskell to make it *really* useful, and this would change the structure of the language considerably. – Landei Jun 19 '11 at 07:32
  • To clarify @Landei's comment, Haskell doesn't allow multiple definitions of a function. It just has nice sugar for pattern matching. In Scala terms it's as if you could write "def f[A](Some(p : A), alt : A) = p;def f(None, alt : A) = alt" instead of "def f(x : Option[A], alt : A) = x match { case Some(p) => p; case None => alt}". Unfortunately, Scala has Java style overloading and does algebraic data types through subtyping, both of which create ambiguity. – James Iry Jun 20 '11 at 14:53
  • @James Iry: Yes, I know technically the "multiple definitions" in Haskell are only hidden `case ... of` statements. But from a user's point of view this is only an implementation detail. – Landei Jun 21 '11 at 06:49
  • @Landei The translation into case expressions is an implementation detail. But the concept that they aren't multiple definitions is not an implementation detail. It's in the user's face given that f only has one type and all the patterns for f must agree with the one type of f. – James Iry Jun 21 '11 at 16:00
  • @James Iry: Although I think it is clear from the context that we're not talking about overloaded functions, I agree calling it "multiple definitions" is sloppy. But what would be a better term? Something like "pattern match based dispatch"? But that sounds ridiculous. – Landei Jun 22 '11 at 08:07

4 Answers4

11

The feature you're looking for is called destructuring and, in it's general form, would go well beyond just tuple unpacking. I've often found myself wishing that Scala had it since it's such a natural extension of the pattern matching syntax:

def first((f: Int, l: Int)) = f
def displayName(Person(first, last)) = last + ", " + first

Destructuring is (sort of) present in the form of variable/value definitions:

val (f, l) = tuple
val Person(first, last) = person

Unfortunately, there are some type safety issues around such definitions that I think make it unlikely that you'll see destructuring in parameter lists any time soon.

Aaron Novstrup
  • 20,967
  • 7
  • 70
  • 108
  • Thanks for all your answers. Daniel's answer is right as well but I've chosen this one as it contains useful web references to understand a bit more of the technical details. Thanks again to all! – letmaik Jun 20 '11 at 10:00
  • nice one, +1 from me--destructuring requires a predicate line of code, but still far easier to look at than myTuple._0, etc. – doug Sep 15 '15 at 21:34
4

You could create a function that receives an argument list which corresponds to the types of the Tuple, apply Function.tupled to that function and then apply the tuple:

scala> def fun(x:Int,y:Int)=x+y
fun: (x: Int,y: Int)Int

scala> val tuple = (1,2)
tuple: (Int, Int) = (1,2)

scala> Function.tupled(fun _)(tuple)
res9: Int = 3

This way you achieve a valid workaround for your problem

JaimeJorge
  • 1,885
  • 16
  • 15
  • Ok, you're right regarding the simple case I gave as an example, but what about more complex parameters like: list.foldLeft((0,0))((a: (Int, Int), x: Int) => ... a._1...) Here I can't just change the function definition. – letmaik Jun 19 '11 at 12:03
  • You could, using function currying, apply `tupled` the parameters of certain parts of the function. However, it would always be more complicated than using intermediary variables such as `val (a,b) = tuple`. I must say, nevertheless, I do not dislike tuple._1 or tuple._2 – JaimeJorge Jun 19 '11 at 21:38
2

That's called multiple dispatch, and it is not supported by JVM. Scala could rewrite a method to make the explicit match unnecessary, though, but it is not a priority -- or, as far as I know, even planned -- to do so.

Interestingly, it is supported for functions, in a sense, with the restriction that all variants must appear together. For example:

def x: ((Int, Int)) => Int = {
    case (p, _) => p
}
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • 2
    Not multiple dispatch. Haskell doesn't even have single dynamic dispatch. – James Iry Jun 19 '11 at 03:46
  • @James I believe you know what you are talking about, but it certainly does look to me that it chooses the definition to be applied based on the run-time value of the parameters, which is the very definition of multiple dispatch. So what's the difference? – Daniel C. Sobral Jun 19 '11 at 16:42
  • If you look at his examples again there's no dispatch - he's not trying to dynamically choose different methods. All that he's doing is pulling apart a tuple into named variables. He just happens to use the name "x" in several different ways to give examples of possible sugar Scala could put on destructuring method arguments. – James Iry Jun 19 '11 at 20:50
  • @James Well, yes, but I assumed that was just a simplification of his actual problem. – Daniel C. Sobral Jun 19 '11 at 21:35
0

Another approach would be to make parameter lists and tuples the same thing in the language.

John Nilsson
  • 17,001
  • 8
  • 32
  • 42