I have a Play 2.5 template which starts from the following declaration:
#(title: String)(content: Html)(menu:Html = HtmlFormat.empty)(implicit request:Request[AnyContent])
So the second parameter is declared having a default value.
Now in the controller I have this action generator:
def document(title:String) = Action.async{implicit request =>
documentService.findByTitle(title).map{
case Some(d) => Ok(views.html.document(d))
case None => Ok(main("No document found")(content = Html("There is no such document")))
}
}
So I do not pass the value of the menu parameter to the template invocation and I expect this to compile and work in accordance with the default parameter values semantics, but I am getting this compilation error:
[error] D:\Projects\feed\app\controllers\MainController.scala:28: missing arguments for method apply in class main;
[error] follow this method with `_' if you want to treat it as a partially applied function
[error] case None => Ok(main("No document found")(content = Html("There is no such document")))
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
Could you explain what is wrong here?
Add one more pair of parenthesis.
Ok(main("No document found")(content = Html("There is no such document")()))
Without last parenthesis - it's just a function that waits for one more argument. You can check type of function you call. I'll show on my examples:
def foo(a: Int = 3) = 41
val one = foo //wan't compile
val two: (Int) => Int = foo
val three: Int = foo()
Related
I'm trying to deploy RegInit in a module with parametrized data types. Normally, for a simple port in Chisel I'd do the following:
val myReg = RegInit (0.U(32.W))
In my code, I have the following:
import dsptools._
import dsptools.numbers._
class Acc[A <: Data:Ring, B <: Data:Ring] (inType:A, outType:B,
mulPipeLen:Int = 1, addPipeLen:Int = 1) extends Module {
...
def zero = dsptools.numbers.Ring[B].zero
val mres = Reg(outType.cloneType) // this works, no initialization
val ares = RegInit(zero(outType.cloneType.getWidth.W)) // this fails trying to zero init in the parametrized Ring
...
}
which return a compile error:
[error] Acc.scala:43:27: B does not take parameters
[error] val mres = RegInit(zero(outType.cloneType.cloneType.getWidth.W))
How do I fix this? Thank you!
When I tried the above, I got 3 errors:
[error] /Users/jack/work/chisel3-raw/src/main/scala/RegInit.scala:10:13: inferred type arguments [Object] do not conform to method apply's type parameter bounds [T <: chisel3.core.Data]
[error] val reg = RegInit(0.U, (32.W))
[error] ^
[error] /Users/jack/work/chisel3-raw/src/main/scala/RegInit.scala:10:23: type mismatch;
[error] found : chisel3.core.UInt
[error] required: T
[error] val reg = RegInit(0.U, (32.W))
[error] ^
[error] /Users/jack/work/chisel3-raw/src/main/scala/RegInit.scala:10:30: type mismatch;
[error] found : chisel3.internal.firrtl.Width
[error] required: T
[error] val reg = RegInit(0.U, (32.W))
[error] ^
RegInit has two flavors, documented here: https://chisel.eecs.berkeley.edu/api/latest/chisel3/core/RegInit$.html
In short, if just 1 argument, it is the initialization value. If the initialization value has a defined width (0.U(32.W) vs. 0.U) then it will adopt the width (and type) of the initializing value.
val reg = RegInit(0.U(32.W))
Otherwise, you can give 2 arguments, the first defining the type, the second defining the initialization value
val reg2 = RegInit(UInt(32.W), 0.U)
Response to Edited post
I don't know much about the dsptools, but I don't think Ring has much to do with the concept of zero. You can set the type of ares to be the same as outType and then try casting 0 to the same type as the init value, eg.
val ares = RegInit(outType.cloneType, 0.U.asTypeOf(outType.cloneType))
Or perhaps you can cast 0 and also set the width:
val ares = RegInit(0.U(outType.getWidth.W).asTypeOf(outType.cloneType))
I'm not sure if these will work, but they might
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 _
import scala.slick.driver.MySQLDriver.simple._
class RichTable[T](tag: Tag, name: String) extends Table[T](tag, name) {
case class QueryExt[B](q: Query[RichTable.this.type, B]) {
def whereEq[C](col: RichTable.this.type => Column[C], c: C) = {
q.filter { fields =>
col(fields) === c
}
}
}
}
Then it complains
[error] /home/jilen/workspace/play-slick/src/main/scala/play/slick/SlickQueryExtension.scala:10: value === is not a member of slick.driver.MySQLDriver.simple.Column[C]
[error] col(fields) === c
[error] ^
[error] /home/jilen/workspace/play-slick/src/main/scala/play/slick/SlickQueryExtension.scala:9: ambiguous implicit values:
[error] both value BooleanColumnCanBeQueryCondition in object CanBeQueryCondition of type => scala.slick.lifted.CanBeQueryCondition[scala.slick.lifted.Column[Boolean]]
[error] and value BooleanOptionColumnCanBeQueryCondition in object CanBeQueryCondition of type => scala.slick.lifted.CanBeQueryCondition[scala.slick.lifted.Column[Option[Boolean]]]
[error] match expected type scala.slick.lifted.CanBeQueryCondition[Nothing]
[error] q.filter { fields =>
[error] ^
[error] two errors found
[error] (compile:compile) Compilation failed
[error] Total time: 0 s, completed Mar 6, 2014 1:21:48 AM
There have been questions about this, but the answers did not work for 2.0
How to parametrize Scala Slick queries by WHERE clause conditions?
Slick doesn't have any information about C, so it doesn't know if it can and how it should map it to a database value and if it can use === on it. So you get a type error. You will have to use Scala's type system to restrict the type to one for which Slick knows how to map it. You can do this by providing a so-called Context Bound, in this case :BaseColumnType.
def whereEq[C:BaseColumnType](col: RichTable.this.type => Column[C], c: C) = {
q.filter { fields =>
col(fields) === c
}
}
BaseColumnType is provided by Slick and using it in this way basically tells the Scala compiler to look for an implicit value of type BaseColumnType[C] in scope, where you call whereEq. Because then it is usually known what C will actually be. Slick comes with BaseColumnType[Int], BaseColumnType[String], etc. so at the call site, the Scala compiler can find one when your C is really an Int or String in that particular call and this way pass the info further to Slick.
Same for LiuTiger's question. abstract class Crud[..., PK:BaseColumnType] should do the trick, a trait doesn't work with context bounds. When implementing an abstract DAO be prepared to face a lot of challenges and get to the edges of your Scala type system skills and learn quite a bit about type inference order, implicit parameters, etc.
Straight forward problem that I don't see what I'm doing wrong in - some type mismatch somewhere. Basically trying to set a default datatype of Long on parameters that are coming in from a web request. Here's the code:
val startTs:Long = params.getOrElse("start_ts", DateTime.yesterdayAsEpoch).toLong
val endTs:Long = params.getOrElse("end_ts", DateTime.todayAsEpoch).toLong
My DateTime helper code:
def todayAsEpoch: Long = {
val c = Calendar.getInstance(TimeZone.getTimeZone("EST"))
c.setTime(new java.util.Date())
c.set(c.get(Calendar.YEAR),c.get(Calendar.MONTH),c.get(Calendar.DAY_OF_MONTH),0,0,0)
c.getTimeInMillis / 1000L
}
def yesterdayAsEpoch: Long = {
val c = Calendar.getInstance(TimeZone.getTimeZone("EST"))
c.setTime(new java.util.Date())
c.set(c.get(Calendar.YEAR),c.get(Calendar.MONTH),c.get(Calendar.DAY_OF_MONTH),0,0,0)
((c.getTimeInMillis / 1000L) - 86400)
}
And finally, the error:
value toLong is not a member of Any
[error] val startTs:Long = params.getOrElse("start_ts", DateTime.yesterdayAsEpoch).toLong
[error] ^
[error] /vagrant/src/main/scala/com/myapp/api/controllers/FooController.scala:437: value toLong is not a member of Any
[error] val endTs:Long = params.getOrElse("end_ts", DateTime.todayAsEpoch).toLong
[error] ^
[error] two errors found
[error] (compile:compile) Compilation failed
You did not say what params is. It looks like it might be a Map[String, X] with some type X. params.getOrElse(key, someLong) will considered to have the best common supertype of X and Long which happens to be Any, according to the error message, and which has no toLong method. As your default value happens to be Long already, and so don't need to be converted, I guess there is a toLong method on X.
If it is so, then you should convert the value retrieved from params to Long (when there is such a value), before providing the default value. That would be :
params.get("key").map(_.toLong).getOrElse(defaultValue)
I'm guessing params is a Map[String, Something], and that Something isn't always a numeric type. (String?) In any case, when you call params.getOrElse, it's inferring a common type between Something and Long, and finding Any, which is why you can't call toLong on it.
I changed one function from:
def submit = Action { request =>
signupForm.bindFromRequest()(request).fold(
// Form has errors
errors => BadRequest(html.signup.form(errors)),
// We got a valid User value, display the summary
user => {
// intensive computation involving database
Ok("okay")
}
)
}
to
def submit = Action { request =>
val result = Akka.future {
signupForm.bindFromRequest()(request).fold(
// Form has errors
errors => BadRequest(html.signup.form(errors)),
// We got a valid User value, display the summary
user => {
// intensive computation involving database
Ok("okay")
}
)
}
Async {
result
}
}
and I get the compilation error of:
[error] found : play.api.mvc.SimpleResult[_ >: java.lang.String with play.api.templates.Html <: java.io.Serializable]
[error] required: play.api.mvc.SimpleResult[_1(in value result)] where type _1(in value result) >: java.lang.String with play.api.templates.Html <: java.io.Serializable
[error] Note: java.io.Serializable >: _1, but class SimpleResult is invariant in type A.
[error] You may wish to define A as -A instead. (SLS 4.5)
[error] signupForm.bindFromRequest()(request).fold(
[error] ^
[error] one error found
The error message seem like it has something to do with variance. Does anyone understand what's going on?
BadRequest is returning the type SimpleResult[Html]
Ok is returning the type SimpleResult[String]
If you make BadRequest and Ok return the same type then it would work.
Try doing Ok(Html("ok")) - or actually render a page.