scala : it is impossible to put a tuple as a function's argument
Asked Answered
G

4

8

I can't pass a tuple as a method parameter:

scala> val c:Stream[(Int,Int,Int)]= Stream.iterate((1, 0, 1))((a:Int,b:Int,c:Int) => (b,c,a+b))
<console>:11: error: type mismatch;
 found   : (Int, Int, Int) => (Int, Int, Int)
 required: ((Int, Int, Int)) => (Int, Int, Int)

thanks.

Gastroenterology answered 3/7, 2015 at 12:52 Comment(0)
V
10

Just as the function literal:

(x:Int) => x + 1

is a function of one argument, the following

(x:Int, y: Int, z: Int) => x + y + z

is a function of three arguments, not one argument of a 3tuple

You can make this work neatly using a case statement:

scala> val c: Stream[(Int,Int,Int)] = 
       Stream.iterate((1, 0, 1)){ case (a, b, c) => (b, c, a+b) }

c: Stream[(Int, Int, Int)] = Stream((1,0,1), ?)

An alternative is to pass the tuple, but that's really ugly due to all the _1 accessors:

scala> val c:Stream[(Int,Int,Int)] = 
         Stream.iterate((1, 0, 1))( t => (t._2, t._3, t._1 + t._2) )

c: Stream[(Int, Int, Int)] = Stream((1,0,1), ?)
Volz answered 3/7, 2015 at 13:0 Comment(4)
it works, thank you. In fact I tried something like this (the use of case) but I did not put the case between curly brackets. Why simple brackets do not work?Gastroenterology
@Gastroenterology Because case is not a simple expression, which is all that is allowed inside () argument listsTweeter
Another issue with case is you could get runtime errors if your types or number of arguments get out of sync. :(Zoophobia
In some contexts, yes - but here the Stream is already constrained to (Int,Int,Int) so case will always succeedVolz
S
4

The lambda (a:Int,b:Int,c:Int) => (b,c,a+b) is a function taking three arguments. You want it to take one tuple, so you can write ((a:Int,b:Int,c:Int)) => (b,c,a+b). But this gives an error!

error: not a legal formal parameter.
Note: Tuples cannot be directly destructured in method or function parameters.
      Either create a single parameter accepting the Tuple3,
      or consider a pattern matching anonymous function: `{ case (param1, ..., param3) => ... }
       (((a:Int,b:Int,c:Int)) => (b,c,a+b))
         ^

Luckily, the error suggests a solution: { case (a, b, c) => (b, c, a+b) }

Sanitation answered 3/7, 2015 at 13:18 Comment(0)
J
1

It is also possible to use the tupled option:

def a = (x:Int, y: Int, z: Int) => x + y + z).tupled
val sum = a((1,2,3))
Jagannath answered 28/10, 2020 at 15:53 Comment(0)
D
-1

My guess is that the expression (a:Int,b:Int,c:Int) => (b,c,a+b) defines a lambda with three arguments, and you need one decomposed argument.

Dannydannye answered 3/7, 2015 at 12:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.