How can I take any function as input for my Scala wrapper method? - scala

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
}

Related

MVar tryPut returns true and isEmpty also returns true

I wrote simple callback(handler) function which i pass to async api and i want to wait for result:
object Handlers {
val logger: Logger = Logger("Handlers")
implicit val cs: ContextShift[IO] =
IO.contextShift(ExecutionContext.Implicits.global)
class DefaultHandler[A] {
val response: IO[MVar[IO, A]] = MVar.empty[IO, A]
def onResult(obj: Any): Unit = {
obj match {
case obj: A =>
println(response.flatMap(_.tryPut(obj)).unsafeRunSync())
println(response.flatMap(_.isEmpty).unsafeRunSync())
case _ => logger.error("Wrong expected type")
}
}
def getResponse: A = {
response.flatMap(_.take).unsafeRunSync()
}
}
But for some reason both tryPut and isEmpty(when i'd manually call onResult method) returns true, therefore when i calling getResponse it sleeps forever.
This is the my test:
class HandlersTest extends FunSuite {
test("DefaultHandler.test") {
val handler = new DefaultHandler[Int]
handler.onResult(3)
val response = handler.getResponse
assert(response != 0)
}
}
Can somebody explain why tryPut returns true, but nothing puts. And what is the right way to use Mvar/channels in scala?
IO[X] means that you have the recipe to create some X. So on your example, yuo are putting in one MVar and then asking in another.
Here is how I would do it.
object Handlers {
trait DefaultHandler[A] {
def onResult(obj: Any): IO[Unit]
def getResponse: IO[A]
}
object DefaultHandler {
def apply[A : ClassTag]: IO[DefaultHandler[A]] =
MVar.empty[IO, A].map { response =>
new DefaultHandler[A] {
override def onResult(obj: Any): IO[Unit] = obj match {
case obj: A =>
for {
r1 <- response.tryPut(obj)
_ <- IO(println(r1))
r2 <- response.isEmpty
_ <- IO(println(r2))
} yield ()
case _ =>
IO(logger.error("Wrong expected type"))
}
override def getResponse: IO[A] =
response.take
}
}
}
}
The "unsafe" is sort of a hint, but every time you call unsafeRunSync, you should basically think of it as an entire new universe. Before you make the call, you can only describe instructions for what will happen, you can't actually change anything. During the call is when all the changes occur. Once the call completes, that universe is destroyed, and you can read the result but no longer change anything. What happens in one unsafeRunSync universe doesn't affect another.
You need to call it exactly once in your test code. That means your test code needs to look something like:
val test = for {
handler <- TestHandler.DefaultHandler[Int]
_ <- handler.onResult(3)
response <- handler.getResponse
} yield response
assert test.unsafeRunSync() == 3
Note this doesn't really buy you much over just using the MVar directly. I think you're trying to mix side effects inside IO and outside it, but that doesn't work. All the side effects need to be inside.

How to pass method of String as callable parameter?

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)
}
}
}

Scala Lifting to a thunk

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)

surrounding function for adding context

I am trying to write a function which can add a context to those functions given in parameters.
The idea is here
object example {
def withOne(f : => T) = {
val a = 1 //some context
f
}
def foo() = withOne {
println(a)
}
}
I think the context could be passed in implicit.
The idea is to not have the content of f constraint by the surrounding function f should be able to use the context or not.
For now the only way i seen to do that is like that
object example {
def withOne(f : => Int => T) = {
val a = 1 //some context
f(a)
}
def foo() = withOne { a =>
println(a)
}
}
But this forces to declare a 'a' witch is not obvious for others devs :x
I'm afraid you cannot work around this, since you cannot inject an implicit into a function.
There's a proposal to add this feature in the typelevel/scala fork, but it seems hard to achieve as of today.
My suggestion here is to use proper naming, so that you won't surprise your users. For instance if you provide a method like:
def withConnection[A](f: Connection => A): A = {
try {
val conn = ???
f(conn)
} finally {
conn.close()
}
}
it won't surprise me to do:
withConnection { implicit c =>
// db stuff
}

Implement transaction aspect in Scala

I would like to implement utility function/monad/aspect for managing hibernate transactions in scala, and looking for advice about best approach.
First I tried to create currying function like following:
def session() = sessionFactory.getCurrentSession()
def transaction() = session().getTransaction()
def tx[A, B](f: A => B)(a: A): B = {
try {
session().beginTransaction()
val r = f(a)
transaction().commit()
return r
} catch {
case e:
Throwable =>
transaction().rollback()
throw e
} finally {
session.close()
}
}
The idea was that I can do following with this function:
def saveMyEntity() {
session().save(new MyEntity)
}
tx(saveMyEntity)()
and saveMyEntity call will be wrapped into transaction.
Unfortunately I get following error with this code:
[error] found : () => Unit
[error] required: ? => ?
[error] tx(saveMyEntity)()
I still learning scala, and looking for advice to improve my approach. Maybe I can modify my function somehow to achieve better results? Or add another Unit type specific function? Or choose another path?
Any ideas?
Any scala canonical way to implement this?
Thanks.
Method tx accepts function of 1 argument as parameter and method saveMyEntity accepts no arguments, so you can't use it as A => B (function of 1 argument).
You are not using a and f separately, so there is no need in a. You could use by-name parameters here:
def tx[B](f: => B): B = {
If you want to use a saveMyEntity as Unit => Unit you should create function explicitly:
tx[Unit, Unit](_ => saveMyEntity)(())
I guess some changes may improve your code readability:
import util.control.Exception.allCatch
def withSession[T](f: Session => T):T = {
val session = ??? // start session here
allCatch.anfFinally{
session.close()
} apply { f(session) }
}
def inTransaction[T](f: => T): T =
withSession{ session =>
session().beginTransaction()
try {
val r = f(a)
transaction().commit()
r
} catch {
case e: Throwable =>
transaction().rollback()
throw e
}
}
inTransaction{saveMyEntity}
object TestTransaction
{
def executeInTransaction(f: => Unit)={
println("begin")
f
println("end")
}
executeInTransaction {
println("action!")
}
}
produces:
begin
action!
end