I want to do this, the parameter is lazy and repeatable:
def f(actions: (=> Try[String])*) = {
actions.map{x =>
if(x.isFailure) throw new Exception()
...
}
}
So, I can evaluate parameter with this:
f(Try("a"), Try("b"), Try[String](new Exception()), Try({print("something"); "d"}))
The print("something") never be executed because parameters is lazy.
rather then:
def f(actions: (() => Try[String])*) = ???
f(() => Try("a"),() => Try("b"),() => Try[String](new Exception()), () => Try({print("something"); "d"}))
It just writing feeling boring.
Is Scala support the first one?
Wrap by name parameters as so:
implicit class ByNameWrapper[+A](a: => A) { def get: A = a }
And define your method as
def f(actions: ByNameWrapper[Try[String]]*) {
...
}
Usage is the same as normal by-name parameters:
f(Try { throw new Exception }, Try { println("a"); "b" })
It's coming to dotty. Or it's already in dotty.
https://github.com/lampepfl/dotty/issues/499
Related
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)
}
}
}
case class dummy(val prop:Seq[Test])
case class Test(val s :String)
case class Result(val s :String)
def myFunc:Result = {
val s = "11,22,33"
val t = Test(s)
val list = dummy(Seq(t))
val code = Option("25")
val result = code.exists(p => {
list.prop.exists(d => d.s.split(",").contains(p))
})
if (result) {
Result("found")
} else {
Result("Not Found")
}
}
I am calling function myFunc, but instead of evaluating a boolean using if/else construct.
Any possible ways to avoid using If else construct
There is nothing wrong with using the if/else, but you could do this:
code
.flatMap(c => list.prop.find(_.s.split(",").contains(c)))
.map(_ => Result("Found")).getOrElse(Result("Not Found"))
The idea here is that instead of returning a Boolean at each stage we are passing an Option along. Then at the end if the Option is defined we can map that into a Result("Found"), and if it is not defined the .getOrElse will return a Result("Not Found").
I am looking to rewrite this scala function, but I am new to the language, I understand there is a alternative to using try\catch blocks. How would you guys rewrite this function?
def updateStationPost = Action { implicit request =>
StationForm.bindFromRequest.fold(
errors => { //needs to be revised!!
BadRequest(html.updateStation(errors,
Station(
request.body.asFormUrlEncoded.get("id")(0).toLong,
request.body.asFormUrlEncoded.get("operator")(0).toLong,
request.body.asFormUrlEncoded.get("name")(0),
try {
request.body.asFormUrlEncoded.get("number")(0).toInt
} catch {
case e:Exception => { 0 } //this exception happens when trying to convert the number when there is nothing in the flash scope to convert.
},
request.body.asFormUrlEncoded.get("timezone")(0)
),
Operators.retrieveJustOperators() //ugh... needs to be revised..
)
)
},
{ case(stationFormObj) =>
Stations.update(stationFormObj)
Redirect(routes.StationsController.index)
}
)
}
A general way of managing this is to use Try to wrap code that could throw an exception. Some of the ways of using this are illustrated below:
def unpredictable() = {
Try(Console.readLine("Int please: ").toInt) getOrElse 0
}
If the console read does not contain a parseable integer, then it throws an exception. This code just returns a 0 if there was an error, but you could put other statements there. As an alternative, you could use pattern matching to handle the situation.
def unpredictable() = {
Try(Console.readLine("Int please: ").toInt) match {
case Success(i) => i
case Failure(e) => println(e.getMessage())
}
}
You can also just return a Try and let the caller decide how to handle the failure.
How about:
import scala.util.control.Exception.handling
// Create a val like this as you reuse it over and over
val form: Option[Map[String, Seq[String]]] = request.body.asFormUrlEncoded
// Create some helper functions like this
val nfeHandler = handling(classOf[NumberFormatException]) by (_ => 0)
val intNFEHandler = (str: String) => nfeHandler apply str.toInt
val longNFEHandler = (str: String) => nfeHandler apply str.toLong
// You can use this instead of your try catch.. but this is just a sugar.. perhaps cleaner
intNFEHandler apply form.get("id")(0)
Here if the form was something like: Option(Map("id" -> Seq.empty[String]))
form.get("id")(0) would blow up with java.lang.IndexOutOfBoundsException.
I would suggest to have another helper:
// takes fieldNames and returns Option(fieldValue)
val fieldValueOpt = (fieldName: String) => form.flatMap(_.get(fieldName).flatMap(_.headOption))
Then create a validate method which performs pattern matching on all the fieldValue optionals, extract the values and create your Station object.
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
I have a helper method:
def controlStructure[T <: SomeObject](exceptions: Class[_]*)(body: => T) = {
try {
val tempObject = body
tempObject.callSomeMethod
Some(tempObject)
} catch {
case e if (exceptions.contains(e.getClass)) => None
}
}
called with:
controlStructure[MySomeObject](classOf[Exception]) { getMySomeObjectSomehow }
the main point of which is to call the 'callSomeMethod' on the entity passed in (for example loaded from ORM), it incidentally wraps things up in exception handling too.
I would now like to add a new method which does the same thing but for a collection (java.util.List) of T.
I am unsure of the syntax, and structures to work with a collection of T in the method signature, and abstract type param definitions.
Thanks for your help.
With a scala list, you are wanting something like this (I think):
def controlStructure[T <: SomeObject](exceptions: Class[_]*)(body: => List[T]) = {
try {
val tempObject = body
tempObject.foreach { _.callSomeMethod() }
Some(tempObject)
}
catch {
case e if (exceptions.contains(e.getClass)) => None
}
}
I haven't worked with Java lists in scala, so I'm guessing you could do it with java.util.List like this:
def controlStructure[T <: SomeObject](exceptions: Class[_]*)(body: => java.util.List[T]) = {
import scala.collection.JavaConversions._
try {
val tempObject = body
tempObject foreach { _.callSomeMethod() }
Some(tempObject)
}
catch {
case e if (exceptions.contains(e.getClass)) => None
}
}
There's no pass by name vararg in Scala. You have to pass a function if you want this. See this ticket of an enhancement request to this effect.
Thanks for your help Mitch. It turns out the answer is in this case to specify the return type of the method, as java.util.List[T], as for once Scala is not using its magic type inference to sort everything out.