Reputation: 1033
I am nearly completely new to Scala, a few months on. I noticed some wild signatures. I have worked through generics with contrapositive/copositive/extensions/invariance, and most of the basics. However, I continue to find some of the method signatures a bit confusing. While I find examples and know what the signatures produce, I am still a bit at a loss as to some of the functionality. Googling my questions has left me with no answers. I do have the general idea that people like to beat the basic CS 1 stuff to death. I have even tried to find answers on the scala website. Perhaps I am phrasing things like "expanded method signature" and "defining function use in scala signature" wrong. Can anyone explain this signature?
futureUsing[I <: Closeable, R](resource: I)(f: I => Future[R])(implicit ec: ExecutionContext):Future[R]
My guess is that after the initial generics and parameter declaration with a parameter of type I, the body is defined and the final portion is any objects specific to the function or that must be looked up in an implicit scope (are they destroyed afterwards?). Can anyone layout an expanded method signature so I know what code I am using? Is there a particular order the last two parts must be in?
Note
After a bunch more searching, I found a few valid responses I can throw together:
-Scala - Currying and default arguments
-why in Scala a function type needs to be passed in separate group of arguments into a function
There is no set ordering just that implicits must be last. Placement is about dependency which flows left to right as someone down the list in one of the above answers pointed out. Why I cannot have implicits first and everything depending on them afterwards is odd since having nothing available causes an error and things will likely depend on a given implicit.
However, I am still a bit confused. When specifying f: I => Future[R], and needing to supply the last argument, lets pretend it would be any implicit, would I need to do something more like:
futureUsing(resourceOfI)({stuff => doStuff(stuff)})(myImplicit)
Is this even correct?
Could I do:
futureUsing(resourceOfI)(myImplicit)({stuff => doStuff(stuff)})
Why? I am really trying to get at the underlying reasons rather than just a binary yes or no.
Final Note
I just found this answer. It appears the order cannot be changed. Please correct me if I am wrong.
Scala: Preference among overloaded methods with implicits, currying and defaults
Upvotes: 2
Views: 171
Reputation: 51271
Can anyone explain this signature?
futureUsing[I <: Closeable, R]
futureUsing
works with two separate types (two type parameters). We don't know exactly what types they are, but we'll call one I
(input), which is a (or derived from) Closable
, and the other R
(result).
(resourse: I)
The 1st curried argument to futureUsing
is of type I
. We'll call it resourse
.
(f: I => Future[R])
The 2nd curried argument, f
, is a function that takes an argument of type I
and returns a Future
that will (eventually) contain something of type R
.
(implicit ec: ExecutionContext)
The 3rd curried argument, ec
, is of type ExecutionContext
. This argument is implicit, meaning if it isn't supplied when futureUsing
is invoked, the compiler will look for an ExecutionContext
in scope that has been declared implicit
and it will pull that in as the 3rd argument.
:Future[R]
futureUsing
returns a Future
that contains the result of type R
.
Is there a specific ordering to this?
Implicit parameters are required to be the last (right most) parameters. Other than that, no, resourse
and f
could have been declared in either order. When invoked, of course, the order of arguments must match the order as declared in the definition.
Do I need ... implicits to drag in?
In the case of ExecutionContext
let the compiler use what's available from import scala.concurrent.ExecutionContext
. Only on rare occasions would you need something different.
...how would Scala use the 2nd curried argument...
In the body of futureUsing
I would expect to see f(resourse)
. f
takes an argument of type I
. resourse
is of type I
. f
returns Future[R]
and so does futureUsing
so the line f(resourse)
might be the last statement in the body of futureUsing
.
Upvotes: 4