I need help trying to get my anonymous function to compile in Scala.
See below:
private def mapBlock(helper: Helper): (Any) => Block = {
(original: Any) => {
val block = original.asInstanceOf[Block]
// logic with helper here
return block
}
}
However, when I compile this I get "Expression of type block does not conform to expected"
What am I doing wrong here?
The problem is that you're calling return block which is the returning to the mapBlock function the value block. But your mapBlock expectes a function typed (Any) => Block. To solve this just remove the return and have block.
private def mapBlock(helper: Helper): (Any) => Block = {
(original: Any) => {
val block = original.asInstanceOf[Block]
// logic with helper here
block
}
}
If you want to have a return then you could name your function and return that. Although in Scala we generally omit all returns, so this would not be idiomatic Scala:
private def mapBlock(helper: Helper): (Any) => Block = {
val function = (original: Any) => {
val block = original.asInstanceOf[Block]
// logic with helper here
block
}
return function
}
Related
I get confused when I see a function that looks like this:
def site(req: RequestHeader, emit: ClientEmit) = WebSocket(req) { sri => user =>
Source: here
I want to recreate a very simple function that follows the same pattern to solidify my understanding on what's going on here.
The function calls WebSocket, and then seems to pass another function call in the body of the outer function site.
Where does sri and user come from? They are not in scope?
Block WebSocket(req) { sri => user => in your sample is just call WebSocket method. Your block is equivalent to:
def site(req: RequestHeader, emit: ClientEmit): Response = {
return WebSocket(req)(
new Function1[Sri, Function1[Option[User], Response]]() {
override def apply(sri: Sri): Function1[Option[User], Response] =
new Function1[Option[User], Response]() {
override def apply(user: Option[User]): Response = ???
}
}
)
}
calling WebSocket method here sri => user => *do something* and return Response is a syntaŃtic sugar for two Function1 objects with apply methods creating actually. Short note is a two lambda expressions. Just read a little more about expressions and lambda expressions. If function contains just one expression, curvy braces are not required and you can write only one WebSocket method call and pass to him lambda expression as a function from 1 argument witch creates function from 1 arguments witch creates Response object.
take a look at WebSocket method:
private def WebSocket(req: RequestHeader)(f: Sri => Option[User] => Response): Response =
CSRF.check(req) {
ValidSri(req) { sri => auth(req) flatMap f(sri) }
}
I wrote here his extended version:
private def WebSocket(req: RequestHeader)(f: Sri => Option[User] => Response): Response =
CSRF.check(req) {
new Function0[Response] {
ValidSri(req) {
new Function1[Sri, Response]() {
sri: Sri =>
val futureOptionUser: Future[Option[User]] = auth.apply(req)
futureOptionUser.flatMap {
optionUser: Option[User] =>
val fAppliedToSri: Function1[Option[User], Response] = f.apply(sri)
val response: Response = fAppliedToSri.apply(optionUser)
return response
}
}
}
}
}
in flatMap method function composition occurs and it's not the same as Function of 2 arguments but in this case it's equivalent. Function composition is more flexible pattern then Function of 2 arguments, you can evaluate them not in the same moment. If you want to know more about conversion between Function of 2 arguments and 2 function of 1 argument composition read about Currying .
Assume I have a function like:
private def throwUnlessValid[T](func: (String => T)): T = {
try {
func()
} catch {
case _: Throwable => throw new Error(s"""string: "${s}" is not a numeric""")
}
}
And I want to call it like:
implicit val intParser: TryParser[Int] = (s: String) => {
s.trim.isEmpty match {
case true => 0
case false => throwUnlessValid[Int](s.toInt)
}
}
This will fail as the result of s.toInt, which is the Int. Even though I want to pass in the callable function to be called in the other method.
How can I achieve this?
The syntax is _.toInt, which is a shorthand for s => s.toInt (or without type inference, (s: String) => s.toInt). Generally, search for "scala lambdas" for a lot more information on this.
But the problem is that you call func() without passing a string to it. There's also s in throw new Error(s"""string: "${s}" is not a numeric"""); if s is in your scope, you should have func(s) instead. Or maybe you want
private def throwUnlessValid[T](func: () => T): T = { ... }
throwUnlessValid(() => s.toInt)
Using by-name parameters, you can even write
private def throwUnlessValid[T](func: => T): T = { ... }
throwUnlessValid(s.toInt)
You can pass a callable function by using _.toInt, which is shorthand for the function x => x.toInt.
However this isn't going to help because your throwUnlessValid function doesn't work, for two reasons:
You don't give a String argument to func
You attempt to print s which is not a visible to this function
You have two choices:
Pass s to throwUnlessValid and give it to func
Make func into a => T parameter and remove the references to s from the Error string.
You need to fix your throwUnlessValid function.
Currently it accepts as argument a function which takes a string as argument:
throwUnlessValid[T](func: (String => T))
However then you are trying to call it without any argument: func() which obviously won't work. Besides that you also have reference to nonexisting variable s: ${s} which also should produce error.
In order to fix the throwUnlessValid function you can pass toInt as by-name argument:
private def throwUnlessValid[T](code: => T): T = {
try {
code
} catch {
case ex: Throwable => throw new Error(s"""string: "${ex.getMessage}" is not a numeric""")
}
}
In other words you don't need to change your existing intParser implementation (including throwUnlessValid[Int](s.toInt) call), you only need to change implementation of throwUnlessValid).
If i understant correctly, you are looking for this.
Actually the problem is that you are not passing string to your function (func) hence it's not working.
import scala.util.{Failure, Success, Try}
object Solution1 extends App {
private def throwUnlessValid[T](func: (String => T)): T = {
Try {
func("1")
} match {
case Success(_) => //do Something which return T
case Failure(ex) => throw new Error(s"""string: "${ex}" is not a numeric""")
}
}
implicit val intParser: String => Int = (s: String) => {
if (s.trim.isEmpty) {
0
} else {
throwUnlessValid[Int](_ => s.toInt)
}
}
}
I have a function that wraps the result of another function in a Promise. I wanted to promote this into a lift function so that I could sort of re-use it elsewhere. Here are the original definitions:
val abc = Promise[MyType]()
try {
val suck = abc.success(someOtherFunction(intParam1, intParam2))
} catch {
case ex: Exception => p.failure(ex)
}
So what I eventually did was the following:
def myLiftFunc[X](x: X) (op: => X): Promise[X] = {
val p = Promise[X]()
try {
p.success(op)
} catch {
case NonFatal(ex) =>
p.failure(ex)
}
p
}
How can I re-use this? I mean, the second argument that I pass in should be a thunk so that I could just pass in any function body irrespective of the parameters that function body would require!
When I call the lifted function as:
myLiftFunc(someOtherFunction(intParam1, intParam2))
This is of type Int => Promise[Int], where the someOtherFunction returns an Int. I just want Promise[Int] when I call myLiftFunc!
You might be interested in the Promise.fromTry method. That method uses the Try idiom from scala.util, which is a useful structure that allows you to treat a try...catch statement more like a traditional constructs:
Promise.fromTry { Try { someOtherFunction(intParam1, intParam2) } }
If you wanted to right your own helper (so that the Try part is unnecessary, you could try something like:
def myLiftFunc[X](op: => X): Promise[X] = Promise.fromTry(Try(op))
This would allow you to do:
myLiftFunc { /*arbitrary logic*/ }
myLiftFunc(1 + 4).future.value.get //Success(5)
myLiftFunc(1/0).future.value.get //Failure(java.lang.ArithmeticException: / by zero)
I am building a DSL with Scala and I have such an object:
object block {
def apply(content: String): String = "{\n" + content + "}\n"
def apply(): String = block("empty block")
}
so that later in my DSL I can say:
block {
"good stuff goes here"
}
that's ok, but there is the second apply() method which I want to use to allow the user to write empty blocks, so to fill them later. But the compiler does not allow to call the no-arguments apply() method with curly braces... is there any way around that except using parentheses instead? If no, then why isn't this allowed?
UPDATE: For reference: the two answers should be combined for the full picture.
Instead of an apply method without any parameters, you can let it take a parameter of type Unit that is ignored:
def apply(ignored: Unit) = "{\n}\n"
Then you can write
block {}
FINALLY
object block {
def apply[T](content: => T) = "{\n" +
(content match {
case s: String => s
case u: Unit => ""
case a => a.toString
}) + "}\n"
}
EDIT
To make a block {} working:
object block { def apply(content: => Unit) = "{\n" + content + "}\n" }
I insist on using a by-name parameter, not just a Unit as in another answer. Because => Unit does actually create a function that can be executed by a block.apply() method, and content: Unit just takes as a parameter a block of code that will be executed in-place (before block.apply()).
Let's suppose that block.apply will print "Hoho". Now:
// content: Unit
block { println("Haha") }
// Haha
// Hoho
// content: => Unit
block { println("Haha") }
// Hoho
// Haha
...
Use by-name parameter:
object block { def apply(content: => String) = "{\n" + content + "}\n" }
Let's say I want to make a little wrapper along the lines of:
def wrapper(f: (Any) => Any): Any = {
println("Executing now")
val res = f
println("Execution finished")
res
}
wrapper {
println("2")
}
Does this make sense? My wrapper method is obviously wrong, but I think the spirit of what I want to do is possible. Am I right in thinking so? If so, what's the solution? Thanks!
If you want your wrapper method to execute the wrapped method inside itself, you should change the parameter to be 'by name'. This uses the syntax => ResultType.
def wrapper(f: => Any): Any = {
println("Executing now")
val res = f
println("Execution finished")
res
}
You can now do this,
wrapper {
println("2")
}
and it will print
Executing now
2
Execution finished
If you want to be able to use the return type of the wrapped function, you can make your method generic:
def wrapper[T](f: => T): T = {
println("Executing now")
val res: T = f
println("Execution finished")
res
}
In your case you are already executing the function println and then pass the result to your wrapper while it is expecting a function with one arguments (Any) and that return Any.
Not sure if this answer to your question but you can use a generic type parameter and accept a function with no arguments that return that type:
def wrapper[T](f: () => T) = {
println("Executing now")
val res = f() // call the function
println("Execution finished")
res
}
wrapper {
()=>println("2") // create an anonymous function that will be called
}