How to pass a tuple argument the best way? - scala

How to pass a tuple argument the best way ?
Example:
def foo(...): (Int, Int) = ...
def bar(a: Int, b: Int) = ...
Now I would like to pass the output of foo to bar. This can be achieved with:
val fooResult = foo(...)
bar(fooResult._1, fooResult._2)
This approach looks a bit ugly, especially when we deal with a n-tuple with n > 2. Also we have to store the result of foo in an extra value, because otherwise foo has to be executed more than once using bar(foo._1, foo._2).
Is there a better way to pass through the tuple as argument ?

There is a special tupled method available for every function:
val bar2 = (bar _).tupled // or Function.tupled(bar _)
bar2 takes a tuple of (Int, Int) (same as bar arguments). Now you can say:
bar2(foo())
If your methods were actually functions (notice the val keyword) the syntax is much more pleasant:
val bar = (a: Int, b: Int) => //...
bar.tupled(foo())
See also
How to apply a function to a tuple?

It is worth also knowing about
foo(...) match { case (a,b) => bar(a,b) }
as an alternative that doesn't require you to explicitly create a temporary fooResult. It's a good compromise when speed and lack of clutter are both important. You can create a function with bar _ and then convert it to take a single tuple argument with .tupled, but this creates a two new function objects each time you call the pair; you could store the result, but that could clutter your code unnecessarily.
For everyday use (i.e. this is not the performance-limiting part of your code), you can just
(bar _).tupled(foo(...))
in line. Sure, you create two extra function objects, but you most likely just created the tuple also, so you don't care that much, right?

Using tupled, as #Tomasz mentions, is a good approach.
You could also extract the tuple returned from foo during assignment:
val (x, y) = foo(5)
bar(x, y)
This has the benefit of cleaner code (no _1 and _2), and lets you assign descriptive names for x and y, making your code easier to read.

Related

What's the purpose of Currying given other alternatives to return a function in Scala?

I'm currently doing a Scala course and recently I was introduced to different techniques of returning functions.
For example, given this function and method:
val simpleAddFunction = (x: Int, y: Int) => x + y
def simpleAddMethod(x: Int, y: Int) = x + y
I can return another function just doing this:
val add7_v1 = (x: Int) => simpleAddFunction(x, 7)
val add7_v2 = simpleAddFunction(_: Int, 7)
val add7_v3 = (x: Int) => simpleAddMethod(x, 7)
val add7_v4 = simpleAddMethod(_: Int, 7)
All the values add7_x accomplish the same thing, so, whats the purpose of Currying then?
Why I have to write def simpleCurryMethod(x: Int)(y: Int) = x + y if all of the above functions do a similar functionality?
That's it! I'm a newbie in functional programming and I don't know many use cases of Currying apart from saving time by reducing the use of parameters repeatedly. So, if someone could explain me the advantages of currying over the previous examples or in Currying in general I would be very grateful.
That's it, have a nice day!
In Scala 2 there are only four pragmatic reasons for currying METHODS (as far as I can recall, if someone has another valid use case then please let me know).
(and probably the principal reason to use it) to drive type inference.
For example, when you want to accept a function or another kind of generic value whose generic type should be inferred from some plain data. For example:
def applyTwice[A](a: A)(f: A => A): A = f(f(a))
applyTwice(10)(_ + 1) // Here the compiler is able to infer that f is Int => Int
In the above example, if I wouldn't have curried the function then I would need to have done something like: applyTwice(10, (x: Int) => x + 1) to call the function.
Which is redundant and looks worse (IMHO).
Note: In Scala 3 type inference is improved thus this reason is not longer valid there.
(and probably the main reason now in Scala 3) for the UX of callers.
For example, if you expect an argument to be a function or a block it is usually better as a single argument in its own (and last) parameter list so it looks nice in usage. For example:
def iterN(n: Int)(body: => Unit): Unit =
if (n > 0) {
body
iterN(n - 1)(body)
}
iterN(3) {
println("Hello")
// more code
println("World")
}
Again, if I wouldn't have curried the previous method the usage would have been like this:
iterN(3, {
println("Hello")
// more code
println("World")
})
Which doesn't look that nice :)
(in my experience weird but valid) when you know that majority of users will call it partially to return a function.
Because val baz = foo(bar) _ looks better than val baz = foo(bar, _) and with the first one, you sometimes don't the the underscore like: data.map(foo(bar))
Note: Disclaimer, I personally think that if this is the case, is better to just return a function right away instead of currying.
Edit
Thanks to #jwvh for pointing out this fourth use case.
(useful when using path-dependant types) when you need to refer to previous parameters. For example:
trait Foo {
type I
def bar(i: I): Baz
}
def run(foo: Foo)(i: foo.I): Baz =
foo.bar(i)

Sequencing functions with multiple arguments in Cats

I was going through "Scala with Cats" by Underscore and stumbled upon the following statement:
Cats provides a cats.syntax.apply module that makes use of Semigroupal and Functor to allow users to sequence functions with multiple arguments.
As far as I understand we can only sequence functions with single arguments because functions can return only single value.
import cats.implicits._
val f1: Int => Int = x => x + 1
val f2: Int => Int = x => x * 4
val f3: Int => String = x => s"x = $x"
f1.map(f2).map(f3)(5)
For the following example, it says: Internally mapN uses the Semigroupal to extract the values from the Option and the Functor to apply the values to the function.
final case class Cat(name: String, born: Int, color: String)
(
Option("Garfield"),
Option(1978),
Option("Orange & black")
).mapN(Cat.apply)
// res10: Option[Cat] = Some(Cat("Garfield", 1978, "Orange & black"))
Here Cat.apply is indeed a function with multiple arguments but it is chained to a function that itself returns a tuple of options i.e., a single value. We could probably make it accept multiple arguments like so:
final case class Cat(name: String, born: Int, color: String)
val f: (String, Int, String) => (Option[String], Option[Int], Option[String]) =
(name, year, color) => (Option(name), Option(year), Option(color))
f("Garfield", 1978, "Orange & black").mapN(Cat.apply)
Now we have functions f and Cat.apply that accept multiple arguments and are chained together. Is it what the above statement was pointing to? But then I can't seem to find a way to chain more functions further. Is the statement applicable to chaining multiple argument functions only at one level? Also, notice here that function f is applied eagerly in contrast to the single argument function chaining example depicted above. Is is possible to apply functions lazily here?
There isn't much explanation I could find anywhere on Semigroupal on internet. Could anyone please explain this statement with an example? TIA.
But then I can't seem to find a way to chain more functions further.
I think we can because we can continue mapping over the context for example
f("Garfield", 1978, "Orange & black")
.mapN(Cat.apply)
.map(_.name) // here is another step in the chain of operations
mapN is product + map behind the scenes; we can reveal the constituent map like so
f("Garfield", 1978, "Orange & black")
.tupled
.map { case (a, b, c) => Cat.apply(a, b, c) }
.map { _.name }
where tupled extension method eventually calls Semigroupal#product.
When they say
...allow users to sequence functions with multiple arguments.
my interpretation is not that we keep chaining with just mapN, but instead we can continue chaining over the context in the general sense of the functor, and if at some point in the chain, usually the beginning, we have multiple values within multiple contexts of the same type, then semigroupal + functor allows us to join the values within the single context and continue chaining.
Also, notice here that function f is applied eagerly in contrast to the single argument function chaining example depicted above. Is is possible to apply functions lazily here?
That is kind of the main selling point of Semigroupal over the Monad, that is, to be able to "eagerly" execute independent operations, join the resulting values within the context and then continue chaining. With monadic chaining even if operations are independent one would still have to wait for the other before continuing the chain.

Scala Future[myType] to MyType

I have Future[MyType] and I need to pass the value of MyType to a method which returns Seq[Future[MyType]], so basic signature of problem is:
val a: Seq[Future[MyType]] = ...
getValue(t: MyType): Seq[Future[MyType]] = {...}
I want to pass value of a to getValue. I tried something like:
val b:Seq[Future[MyType]] = a.map{v => getValue(v)}
I want b to be of Seq[Future[MyType]] type
but, it obviously didn't worked as v is of type Future[MyType] and getValue needs only MyType as parameter. What could be a possible solution??
You can do:
val b = a.map(_.map(getValue(_)))
This will give you a Seq[Future[Seq[Future[MyType]]]]. That's pretty ugly. There are three tools that can make that better.
Future.sequence takes a Seq[Future[A]] and gives you a Future[Seq[A]]. The output future will wait for all input futures to complete before giving a result. This might not always be what you want.
fut.flatMap takes a function computing a Future as a result but does not return a nested Future, as would happen with .map.
You can call .flatten on a Seq[Seq[A]] to get a Seq[A]
Putting this all together, you could do something like:
val b: Seq[Future[Seq[MyType]] = a.map(_.flatMap(x => Future.sequence(getValue(x))))
val c: Future[Seq[MyType]] = Future.sequence(b).map(_.flatten)
More generally, when dealing with "container" types, you'll use some combination of map and flatMap to get at the inner types and pass them around. And common containers often have ways to flatten or swap orders, e.g. A[A[X]] => A[X] or A[B[X]] => B[A[X]].

A Map of Different Function Types in Scala

I have two functions with different type signatures, and I want to store them both in a Map:
val add = ((a: Int, b: Int) => a + b)
val odd = ((a: Int) => a % 2 == 0)
var funcs = Map[String, Any]("add" -> add, "odd" -> odd)
Then I want to access these functions at a later date, without having to know about their types. How would I do this? I can write:
funcs("add").asInstanceOf[(Int, Int) => Int](1, 2)
But that requires me to either
know ahead of time what the type of the function is
do some sort of pattern match that accounts for every possible type.
Is there some way I can find out the type of the object stored as Any and convert it to that type?
Although this certainly is not a good idea, if you really have to do it, you can do it using reflection.
Using PaulP's Invocation utility:
scala> val add: (Int, Int) => Int = _ + _
add: (Int, Int) => Int = <function2>
scala> val isOdd: Int => Boolean = _ % 2 != 0
isOdd: Int => Boolean = <function1>
scala> import Invocation._
import Invocation._
scala> val funcs = Map("add" -> add, "isOdd" -> isOdd)
funcs: scala.collection.immutable.Map[java.lang.String,ScalaObject] = Map(add -> <function2>, isOdd -> <function1>)
scala> funcs("add") o 'apply(3, 4)
res18: Any = 7
scala> funcs("isOdd") o 'apply(11)
res19: Any = true
Is there some way I can find out the type of the object stored as Any and convert it to that type?
This doesn't actually make sense. Lets suppose I could do it, and it looks like this:
val func = funcs(func_name).toAppropriateType
Now what?
func now holds a value of some unknown type. I can call it... but I don't know its signature, so what arguments do I pass it? And the type/signature is going to be different on every invocation (depending on what was pulled out of the map), so the code to call it is going to have to be different for every invocation; I need some way of having different code executed for each possibility of func... but that would be a pattern match! And it would have to account for every possible type, just as match on Any.
In fact, the magical toAppropriateType method, even if it could exist, gains me nothing on top of just using an Any. It's still the case that the only things I can do with func are things you can do with all values of every possible type (i.e. very little).
In general, when you take something out of a collection you have to handle it with code that is valid for anything that the type allows to be put into the collection. The only alternative is to use features such as asInstanceOf, which throws away the guarantees of the type system and puts the responsibility for ensuring that you don't use the wrong type on you; meaning you have to have some other way of knowing what type to expect, outside of the type system.
If you want to have a collection of functions with one of a pre-determined set of signatures then the best way is to construct a type that only allows those signatures, and allows you to tell the difference between them (such as Rex Kerr's suggestion of using Either). Switching to using Any as soon as you find you need to combine things of different types in a collection usually causes more problems than it solves.
You could store them in an Either:
val funcs = Map[String, Either[Int=>Boolean, (Int,Int)=>Int]](
"add" -> Right(add),
"odd" -> Left(odd)
)
Now you can pull them apart again, though pattern matching is finicky here (Right(f) will work, but don't try to put conditions on what f is). I suggest using fold, right, left (and isRight and isLeft if you really must), like so:
def doSomething(s: String) =
funcs(s).fold(
f => { f(4) }, // Left is Int=>Boolean
g => { g(3,5)==8 } // Right is (Int,Int)=>Int
)
Presumably you'd want some way to load appropriate arguments also instead of the dummy values I put in.
If you have many variants of functions, you can define your own either-like hierarchy except with more different cases, or you can nest Eithers.

What's the difference between multiple parameters lists and multiple parameters per list in Scala?

In Scala one can write (curried?) functions like this
def curriedFunc(arg1: Int) (arg2: String) = { ... }
What is the difference between the above curriedFunc function definition with two parameters lists and functions with multiple parameters in a single parameter list:
def curriedFunc(arg1: Int, arg2: String) = { ... }
From a mathematical point of view this is (curriedFunc(x))(y) and curriedFunc(x,y) but I can write def sum(x) (y) = x + y and the same will be def sum2(x, y) = x + y
I know only one difference - this is partially applied functions. But both ways are equivalent for me.
Are there any other differences?
Strictly speaking, this is not a curried function, but a method with multiple argument lists, although admittedly it looks like a function.
As you said, the multiple arguments lists allow the method to be used in the place of a partially applied function. (Sorry for the generally silly examples I use)
object NonCurr {
def tabulate[A](n: Int, fun: Int => A) = IndexedSeq.tabulate(n)(fun)
}
NonCurr.tabulate[Double](10, _) // not possible
val x = IndexedSeq.tabulate[Double](10) _ // possible. x is Function1 now
x(math.exp(_)) // complete the application
Another benefit is that you can use curly braces instead of parenthesis which looks nice if the second argument list consists of a single function, or thunk. E.g.
NonCurr.tabulate(10, { i => val j = util.Random.nextInt(i + 1); i - i % 2 })
versus
IndexedSeq.tabulate(10) { i =>
val j = util.Random.nextInt(i + 1)
i - i % 2
}
Or for the thunk:
IndexedSeq.fill(10) {
println("debug: operating the random number generator")
util.Random.nextInt(99)
}
Another advantage is, you can refer to arguments of a previous argument list for defining default argument values (although you could also say it's a disadvantage that you cannot do that in single list :)
// again I'm not very creative with the example, so forgive me
def doSomething(f: java.io.File)(modDate: Long = f.lastModified) = ???
Finally, there are three other application in an answer to related post Why does Scala provide both multiple parameters lists and multiple parameters per list? . I will just copy them here, but the credit goes to Knut Arne Vedaa, Kevin Wright, and extempore.
First: you can have multiple var args:
def foo(as: Int*)(bs: Int*)(cs: Int*) = as.sum * bs.sum * cs.sum
...which would not be possible in a single argument list.
Second, it aids the type inference:
def foo[T](a: T, b: T)(op: (T,T) => T) = op(a, b)
foo(1, 2){_ + _} // compiler can infer the type of the op function
def foo2[T](a: T, b: T, op: (T,T) => T) = op(a, b)
foo2(1, 2, _ + _) // compiler too stupid, unfortunately
And last, this is the only way you can have implicit and non implicit args, as implicit is a modifier for a whole argument list:
def gaga [A](x: A)(implicit mf: Manifest[A]) = ??? // ok
def gaga2[A](x: A, implicit mf: Manifest[A]) = ??? // not possible
There's another difference that was not covered by 0__'s excellent answer: default parameters. A parameter from one parameter list can be used when computing the default in another parameter list, but not in the same one.
For example:
def f(x: Int, y: Int = x * 2) = x + y // not valid
def g(x: Int)(y: Int = x * 2) = x + y // valid
That's the whole point, is that the curried and uncurried forms are equivalent! As others have pointed out, one or the other form can be syntactically more convenient to work with depending on the situation, and that is the only reason to prefer one over the other.
It's important to understand that even if Scala didn't have special syntax for declaring curried functions, you could still construct them; this is just a mathematical inevitability once you have the ability to create functions which return functions.
To demonstrate this, imagine that the def foo(a)(b)(c) = {...} syntax didn't exist. Then you could still achieve the exact same thing like so: def foo(a) = (b) => (c) => {...}.
Like many features in Scala, this is just a syntactic convenience for doing something that would be possible anyway, but with slightly more verbosity.
The two forms are isomorphic. The main difference is that curried functions are easier to apply partially, while non-curried functions have slightly nicer syntax, at least in Scala.