Here is my code
class AuthAction(callbackUri:String) extends ActionBuilder[UserRequest] with ActionRefiner[Request,UserRequest]{
override def refine[A](request: Request[A]): Future[Either[Result,UserRequest[A]]] = {
val redirectUri = routes.Application.callback(None, None).absoluteURL(request)
getUser(request) match {
case Some(user) => Future.successful(Right(new UserRequest(user,request)))
case _ => Future.successful(Left(oauthLogin(callbackUri,redirectUri)(request)))
}
}
}
When i try to compile this code, i get the following error
[error] (secure: Boolean)(implicit request: play.api.mvc.RequestHeader)String <and>
[error] (x$1: play.mvc.Http.Request)String
[error] cannot be applied to (play.api.mvc.Request[A])
[error] val redirectUri = routes.Application.callback(None, None).absoluteURL(request)
is this something to do with implicit params? whats happening here?
It wants play.mvc.Http.Request, and you are trying to pass in play.api.mvc.Request. They are not compatible.
Edit: To answer the question you are asking in the comment ...
Well, I am not sure which parameter you are talking about. There are two flavors of this function:
The one, that it seems like you are trying to call -
absoluteURL(request: play.mvc.Http.Request) - does not take any implicit params, it just needs the request of the right type.
The other one - absoluteURL(secure: Boolean)(implicit request: play.api.mvc.RequestHeader) - does have an implicit parameter, which is also of a different type from what you have (RequestHeader, not Request).
If you declare a variable holding this requestHeader as implicit, and it is in scope, you can call the latter function without specifying it explicitly:
implicit val requestHeader = createMyRequestHeader()
routes.Application.callback(None, None).absoluteURL(true)
or you can still pass it in explicitly like you would do with a regular parameter (in this case you don't need it to be declared as implicit):
routes.Application.callback(None, None).absoluteURL(true)(requestHeader)
Related
Short form: I have a method with the same signature as Future.recover. Passing a partial function to Future's version works. Passing the same PF to my version results in a missing parameter type for expanded function. The argument types of an anonymous function must be fully known. (SLS 8.5) error. What's the difference?
Longer form:
I'm trying to implement the TracingFuture class discussed here in an attempt to trace errors across future boundaries. The basic technique is to wrap the Future in another class, TracingFuture, while adding a pseudo-stacktrace.
The code given in the blog post is missing the recover method from Future, so I've added it with the same signature:
class TracingFuture[+T](underlying: Future[T], val trace: Vector[FutureTraceElement]) extends Future[T] {
def recover[U >: T](pf: PartialFunction[Throwable, U]
)(implicit ec: ExecutionContext, enclosing: sourcecode.Enclosing, file: sourcecode.File,
line: sourcecode.Line): TracingFuture[U] = {
val recovered = underlying.recover(pf)
new TracingFuture[U](recovered, trace :+ FutureTraceElement(enclosing.value, "recover", file.value, line.value))
}
}
For comparison, here's the equivalent chunk of code out of Future. Note that aside from the extra implicit parameters the signatures are the same.
trait Future[+T] extends Awaitable[T] {
def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] =
transform { _ recover pf }
}
Finally, my code that produces the compile error:
val x: TracingFuture[Vector[Maintainer]] = ... // code producing a TracingFuture
val fMaintainers = x.recover {
case err: Throwable ⇒
logger.error("Failed to get list of user maintainers.", err)
Vector.empty[Maintainer]
}
And the error message:
[error] /Users/bwbecker/oat/src/oat3/modules/wapp/app/oat/wapp/dao/CronJobDAO.scala:273: missing parameter type for expanded function
[error] The argument types of an anonymous function must be fully known. (SLS 8.5)
[error] Expected type was: ?
[error] val fMaintainers = x.recover {
[error] ^
Once again, this code works with the Future.recover but I get a compile error with TracingFuture.recover. I don't understand why.
This SO question explains that the compiler knows the argument to the partial function must be a supertype of T but can't guarantee that. But why doesn't it run into that issue with Future.recover?
And, of course, I'd like to know if there's anything I do about it other than rewriting the anonymous partial function to make the types explicit.
The problem is that TracingFuture has two overloaded recover methods: the one you added and the one you inherited from Future. When you only have one, it provides the expected type which is crucial for type inference, but with overloaded methods it doesn't work, as you see from Expected type was: ?.
You may think the compiler should notice types of function parameters are the same and so can still provide the expected type. And you would be right, but it was only fixed in Scala 2.12.
Of course, then you'll run into trouble that the compiler has no way to tell which overload you want when only the implicit arguments are different.
Try to replace
val fMaintainers = x.recover {
case err: Throwable ⇒
logger.error("Failed to get list of user maintainers.", err)
Vector.empty[Maintainer]
}
with
val fMaintainers = x.recover(PartialFunction[Throwable, Vector[Maintainer]] {
case err: Throwable ⇒
logger.error("Failed to get list of user maintainers.", err)
Vector.empty[Maintainer]
})
Why do I get a "missing parameter for expanded function" in one case and not the other?
I'm writing a function that looks like this:
def func(str: String, logFunction: String => Unit) = {
logFunction(s"message is: $str")
}
When I try to pass Logger.info from Play framework, I get this error:
type mismatch;
[error] found : (message: => String, error: => Throwable)Unit <and> (message: => String)Unit
[error] required: String => Unit
It seems like it found the function with two parameters, and tried to pass that to my function. How do I specify the one-parameter Logger.info to be passed to my function?
As you mentioned, there are two overloaded Logger.info methods in Play. To turn that method into a function and to choose the overload you want, you can explicitly specify the type and add an underscore after the function. The underscore turns a method into a function, which is sometimes done automatically, but in the case can be done explicitly. See also how to get a function from an overloaded method.
In this specific case try
val logger: String => Unit = Logger.info _
I have one controller action implemented like this:
def doChangePassword = deadbolt.Restrict(List(Array(Application.USER_ROLE_KEY)))()
{ request => // <<<<<<<<<<<< here is the request
Future {
val context = JavaHelpers.createJavaContext(request)
com.feth.play.module.pa.controllers.AuthenticateBase.noCache(context.response())
val filledForm = Account.PasswordChangeForm.bindFromRequest
// compilation error here, it can't see the request ^^^^^^^
if (filledForm.hasErrors) {
// User did not select whether to link or not link
BadRequest(views.html.account.password_change(userService, filledForm))
} else {
val Some(user: UserRow) = userService.getUser(context.session)
val newPassword = filledForm.get.password
userService.changePassword(user, new MyUsernamePasswordAuthUser(newPassword), true)
Redirect(routes.Application.profile).flashing(
Application.FLASH_MESSAGE_KEY -> messagesApi.preferred(request)("playauthenticate.change_password.success")
)
}
}
}
the implementation above leads to the compilation error:
[error] /home/bravegag/code/play-authenticate-usage-scala/app/controllers/Account.scala:74: Cannot find any HTTP Request here
[error] val filledForm = Account.PasswordChangeForm.bindFromRequest
[error] ^
[error] one error found
However, if I change line 2 from:
{ request => // <<<<<<<<<<<< here is the request
to
{ implicit request => // <<<<<<<<<<<< here is the request
then it compiles ... but why?
What you are looking for are Implicit Parameters. In short:
Implicit Parameters can be passed just like regular or explicit parameters. In case you do not provide an implicit parameter explicitly, then the compiler will try to pass one for you. Implicits can come from various places. From the FAQ Where does Scala look for implicits?:
First look in current scope
Implicits defined in current scope
Explicit imports
wildcard imports
Now look at associated types in
Companion objects of a type
Implicit scope of an argument’s type (2.9.1)
Implicit scope of type arguments (2.8.0)
Outer objects for nested types
Other dimensions
Implicits under number 1. take precedence over those under number 2.
By marking request as implicit in your example, you are declaring an "Implicit defined in current scope". You need to have an implicit request in place because bindFormRequest "asks" you to pass one. See its signature:
bindFromRequest()(implicit request: Request[_]): Form[T]
Now that you have an implicit request in scope, the compiler will automatically pass it to bindFormRequerst.
As I mentioned in the beginning, you could also pass request explicitly:
val filledForm = Account.PasswordChangeForm.bindFromRequest()(request)
In the latter case there is no need to declare request as implicit as you are obviously passing request explicitly. Both variants are equal. It's up to you which one you prefer.
you need an implicit request in scope, like this: https://github.com/pedrorijo91/play-slick3-steps/blob/master/app/controllers/ApplicationController.scala#L11
i've been getting beat up attempting to match on an overloaded method.
i'm new to scala and specs2, so that is likely one factor ;)
so i have a mock of this SchedulerDriver class
and i'm trying to verify the content of the arguments that are being
passed to the signature of this launchTasks method:
http://mesos.apache.org/api/latest/java/org/apache/mesos/SchedulerDriver.html#launchTasks(java.util.Collection,%20java.util.Collection)
i have tried the answers style like so:
val mockSchedulerDriver = mock[SchedulerDriver]
mockSchedulerDriver.launchTasks(haveInterface[Collection[OfferID]], haveInterface[Collection[TaskInfo]]) answers { i => System.out.println(s"i=$i") }
and get
ambiguous reference to overloaded definition, both method launchTasks in trait SchedulerDriver of type (x$1: org.apache.mesos.Protos.OfferID, x$2: java.util.Collection[org.apache.mesos.Protos.TaskInfo])org.apache.mesos.Protos.Status and method launchTasks in trait SchedulerDriver of type (x$1: java.util.Collection[org.apache.mesos.Protos.OfferID], x$2: java.util.Collection[org.apache.mesos.Protos.TaskInfo])org.apache.mesos.Protos.Status match argument types (org.specs2.matcher.Matcher[Any],org.specs2.matcher.Matcher[Any])
and i have tried the capture style like so:
val mockSchedulerDriver = mock[SchedulerDriver]
val offerIdCollectionCaptor = capture[Collection[OfferID]]
val taskInfoCollectionCaptor = capture[Collection[TaskInfo]]
there was one(mockSchedulerDriver).launchTasks(offerIdCollectionCaptor, taskInfoCollectionCaptor)
and get:
overloaded method value launchTasks with alternatives: (x$1: org.apache.mesos.Protos.OfferID,x$2: java.util.Collection[org.apache.mesos.Protos.TaskInfo])org.apache.mesos.Protos.Status <and> (x$1: java.util.Collection[org.apache.mesos.Protos.OfferID],x$2: java.util.Collection[org.apache.mesos.Protos.TaskInfo])org.apache.mesos.Protos.Status cannot be applied to (org.specs2.mock.mockito.ArgumentCapture[java.util.Collection[mesosphere.mesos.protos.OfferID]], org.specs2.mock.mockito.ArgumentCapture[java.util.Collection[org.apache.mesos.Protos.TaskInfo]])
any guidance or suggestions on how to approach this appreciated...!
best,
tony.
You can use the any matcher in that case:
val mockSchedulerDriver = mock[SchedulerDriver]
mockSchedulerDriver.launchTasks(
any[Collection[OfferID]],
any[Collection[TaskInfo]]) answers { i => System.out.println(s"i=$i")
The difference is that any[T] is a Matcher[T] and the overloading resolution works in that case (whereas haveInterface is a Matcher[AnyRef] so it can't direct the overloading resolution).
I don't understand why the first alternative didn't work, but the second alternative isn't working because scala doesn't consider implicit functions when resolving which overloaded method to call, and the magic that lets you use a capture as though it were the thing you captured depends on an implicit function call.
So what if you make it explicit?
val mockSchedulerDriver = mock[SchedulerDriver]
val offerIdCollectionCaptor = capture[Collection[OfferID]]
val taskInfoCollectionCaptor = capture[Collection[TaskInfo]]
there was one(mockSchedulerDriver).launchTasks(
offerIdCollectionCaptor.capture, taskInfoCollectionCaptor.capture)
I was making my way through the Scala playframework tutorial and I came across this snippet of code which had me puzzled:
def newTask = Action { implicit request =>
taskForm.bindFromRequest.fold(
errors => BadRequest(views.html.index(Task.all(), errors)),
label => {
Task.create(label)
Redirect(routes.Application.tasks())
}
)
}
So I decided to investigate and came across this post.
I still don't get it.
What is the difference between this:
implicit def double2Int(d : Double) : Int = d.toInt
and
def double2IntNonImplicit(d : Double) : Int = d.toInt
other than the obvious fact they have different method names.
When should I use implicit and why?
I'll explain the main use cases of implicits below, but for more detail see the relevant chapter of Programming in Scala.
Implicit parameters
The final parameter list on a method can be marked implicit, which means the values will be taken from the context in which they are called. If there is no implicit value of the right type in scope, it will not compile. Since the implicit value must resolve to a single value and to avoid clashes, it's a good idea to make the type specific to its purpose, e.g. don't require your methods to find an implicit Int!
example:
// probably in a library
class Prefixer(val prefix: String)
def addPrefix(s: String)(implicit p: Prefixer) = p.prefix + s
// then probably in your application
implicit val myImplicitPrefixer = new Prefixer("***")
addPrefix("abc") // returns "***abc"
Implicit conversions
When the compiler finds an expression of the wrong type for the context, it will look for an implicit Function value of a type that will allow it to typecheck. So if an A is required and it finds a B, it will look for an implicit value of type B => A in scope (it also checks some other places like in the B and A companion objects, if they exist). Since defs can be "eta-expanded" into Function objects, an implicit def xyz(arg: B): A will do as well.
So the difference between your methods is that the one marked implicit will be inserted for you by the compiler when a Double is found but an Int is required.
implicit def doubleToInt(d: Double) = d.toInt
val x: Int = 42.0
will work the same as
def doubleToInt(d: Double) = d.toInt
val x: Int = doubleToInt(42.0)
In the second we've inserted the conversion manually; in the first the compiler did the same automatically. The conversion is required because of the type annotation on the left hand side.
Regarding your first snippet from Play:
Actions are explained on this page from the Play documentation (see also API docs). You are using
apply(block: (Request[AnyContent]) ⇒ Result): Action[AnyContent]
on the Action object (which is the companion to the trait of the same name).
So we need to supply a Function as the argument, which can be written as a literal in the form
request => ...
In a function literal, the part before the => is a value declaration, and can be marked implicit if you want, just like in any other val declaration. Here, request doesn't have to be marked implicit for this to type check, but by doing so it will be available as an implicit value for any methods that might need it within the function (and of course, it can be used explicitly as well). In this particular case, this has been done because the bindFromRequest method on the Form class requires an implicit Request argument.
WARNING: contains sarcasm judiciously! YMMV...
Luigi's answer is complete and correct. This one is only to extend it a bit with an example of how you can gloriously overuse implicits, as it happens quite often in Scala projects. Actually so often, you can probably even find it in one of the "Best Practice" guides.
object HelloWorld {
case class Text(content: String)
case class Prefix(text: String)
implicit def String2Text(content: String)(implicit prefix: Prefix) = {
Text(prefix.text + " " + content)
}
def printText(text: Text): Unit = {
println(text.content)
}
def main(args: Array[String]): Unit = {
printText("World!")
}
// Best to hide this line somewhere below a pile of completely unrelated code.
// Better yet, import its package from another distant place.
implicit val prefixLOL = Prefix("Hello")
}
In scala implicit works as:
Converter
Parameter value injector
Extension method
There are some uses of Implicit
Implicitly type conversion : It converts the error producing assignment into intended type
val x :String = "1"
val y:Int = x
String is not the sub type of Int , so error happens in line 2. To resolve the error the compiler will look for such a method in the scope which has implicit keyword and takes a String as argument and returns an Int .
so
implicit def z(a:String):Int = 2
val x :String = "1"
val y:Int = x // compiler will use z here like val y:Int=z(x)
println(y) // result 2 & no error!
Implicitly receiver conversion: We generally by receiver call object's properties, eg. methods or variables . So to call any property by a receiver the property must be the member of that receiver's class/object.
class Mahadi{
val haveCar:String ="BMW"
}
class Johnny{
val haveTv:String = "Sony"
}
val mahadi = new Mahadi
mahadi.haveTv // Error happening
Here mahadi.haveTv will produce an error. Because scala compiler will first look for the haveTv property to mahadi receiver. It will not find. Second it will look for a method in scope having implicit keyword which take Mahadi object as argument and returns Johnny object. But it does not have here. So it will create error. But the following is okay.
class Mahadi{
val haveCar:String ="BMW"
}
class Johnny{
val haveTv:String = "Sony"
}
val mahadi = new Mahadi
implicit def z(a:Mahadi):Johnny = new Johnny
mahadi.haveTv // compiler will use z here like new Johnny().haveTv
println(mahadi.haveTv)// result Sony & no error
Implicitly parameter injection: If we call a method and do not pass its parameter value, it will cause an error. The scala compiler works like this - first will try to pass value, but it will get no direct value for the parameter.
def x(a:Int)= a
x // ERROR happening
Second if the parameter has any implicit keyword it will look for any val in the scope which have the same type of value. If not get it will cause error.
def x(implicit a:Int)= a
x // error happening here
To slove this problem compiler will look for a implicit val having the type of Int because the parameter a has implicit keyword.
def x(implicit a:Int)=a
implicit val z:Int =10
x // compiler will use implicit like this x(z)
println(x) // will result 10 & no error.
Another example:
def l(implicit b:Int)
def x(implicit a:Int)= l(a)
we can also write it like-
def x(implicit a:Int)= l
Because l has a implicit parameter and in scope of method x's body, there is an implicit local variable(parameters are local variables) a which is the parameter of x, so in the body of x method the method-signature l's implicit argument value is filed by the x method's local implicit variable(parameter) a implicitly.
So
def x(implicit a:Int)= l
will be in compiler like this
def x(implicit a:Int)= l(a)
Another example:
def c(implicit k:Int):String = k.toString
def x(a:Int => String):String =a
x{
x => c
}
it will cause error, because c in x{x=>c} needs explicitly-value-passing in argument or implicit val in scope.
So we can make the function literal's parameter explicitly implicit when we call the method x
x{
implicit x => c // the compiler will set the parameter of c like this c(x)
}
This has been used in action method of Play-Framework
in view folder of app the template is declared like
#()(implicit requestHreader:RequestHeader)
in controller action is like
def index = Action{
implicit request =>
Ok(views.html.formpage())
}
if you do not mention request parameter as implicit explicitly then you must have been written-
def index = Action{
request =>
Ok(views.html.formpage()(request))
}
Extension Method
Think, we want to add new method with Integer object. The name of the method will be meterToCm,
> 1 .meterToCm
res0 100
to do this we need to create an implicit class within a object/class/trait . This class can not be a case class.
object Extensions{
implicit class MeterToCm(meter:Int){
def meterToCm={
meter*100
}
}
}
Note the implicit class will only take one constructor parameter.
Now import the implicit class in the scope you are wanting to use
import Extensions._
2.meterToCm // result 200
Why and when you should mark the request parameter as implicit:
Some methods that you will make use of in the body of your action have an implicit parameter list like, for example, Form.scala defines a method:
def bindFromRequest()(implicit request: play.api.mvc.Request[_]): Form[T] = { ... }
You don't necessarily notice this as you would just call myForm.bindFromRequest() You don't have to provide the implicit arguments explicitly. No, you leave the compiler to look for any valid candidate object to pass in every time it comes across a method call that requires an instance of the request. Since you do have a request available, all you need to do is to mark it as implicit.
You explicitly mark it as available for implicit use.
You hint the compiler that it's "OK" to use the request object sent in by the Play framework (that we gave the name "request" but could have used just "r" or "req") wherever required, "on the sly".
myForm.bindFromRequest()
see it? it's not there, but it is there!
It just happens without your having to slot it in manually in every place it's needed (but you can pass it explicitly, if you so wish, no matter if it's marked implicit or not):
myForm.bindFromRequest()(request)
Without marking it as implicit, you would have to do the above. Marking it as implicit you don't have to.
When should you mark the request as implicit? You only really need to if you are making use of methods that declare an implicit parameter list expecting an instance of the Request. But to keep it simple, you could just get into the habit of marking the request implicit always. That way you can just write beautiful terse code.
Also, in the above case there should be only one implicit function whose type is double => Int. Otherwise, the compiler gets confused and won't compile properly.
//this won't compile
implicit def doubleToInt(d: Double) = d.toInt
implicit def doubleToIntSecond(d: Double) = d.toInt
val x: Int = 42.0
I had the exact same question as you had and I think I should share how I started to understand it by a few really simple examples (note that it only covers the common use cases).
There are two common use cases in Scala using implicit.
Using it on a variable
Using it on a function
Examples are as follows
Using it on a variable. As you can see, if the implicit keyword is used in the last parameter list, then the closest variable will be used.
// Here I define a class and initiated an instance of this class
case class Person(val name: String)
val charles: Person = Person("Charles")
// Here I define a function
def greeting(words: String)(implicit person: Person) = person match {
case Person(name: String) if name != "" => s"$name, $words"
case _ => "$words"
}
greeting("Good morning") // Charles, Good moring
val charles: Person = Person("")
greeting("Good morning") // Good moring
Using it on a function. As you can see, if the implicit is used on the function, then the closest type conversion method will be used.
val num = 10 // num: Int (of course)
// Here I define a implicit function
implicit def intToString(num: Int) = s"$num -- I am a String now!"
val num = 10 // num: Int (of course). Nothing happens yet.. Compiler believes you want 10 to be an Int
// Util...
val num: String = 10 // Compiler trust you first, and it thinks you have `implicitly` told it that you had a way to covert the type from Int to String, which the function `intToString` can do!
// So num is now actually "10 -- I am a String now!"
// console will print this -> val num: String = 10 -- I am a String now!
Hope this can help.
A very basic example of Implicits in scala.
Implicit parameters:
val value = 10
implicit val multiplier = 3
def multiply(implicit by: Int) = value * by
val result = multiply // implicit parameter wiil be passed here
println(result) // It will print 30 as a result
Note: Here multiplier will be implicitly passed into the function multiply. Missing parameters to the function call are looked up by type in the current scope meaning that code will not compile if there is no implicit variable of type Int in the scope.
Implicit conversions:
implicit def convert(a: Double): Int = a.toInt
val res = multiply(2.0) // Type conversions with implicit functions
println(res) // It will print 20 as a result
Note: When we call multiply function passing a double value, the compiler will try to find the conversion implicit function in the current scope, which converts Int to Double (As function multiply accept Int parameter). If there is no implicit convert function then the compiler will not compile the code.