I have a case where I want to call a method n times, where n is an Int. Is there a good way to do this in a "functional" way in Scala?
case class Event(name: String, quantity: Int, value: Option[BigDecimal])
// a list of events
val lst = List(
Event("supply", 3, Some(new java.math.BigDecimal("39.00"))),
Event("sale", 1, None),
Event("supply", 1, Some(new java.math.BigDecimal("41.00")))
)
// a mutable queue
val queue = new scala.collection.mutable.Queue[BigDecimal]
lst.map { event =>
event.name match {
case "supply" => // call queue.enqueue(event.value) event.quantity times
case "sale" => // call queue.dequeue() event.quantity times
}
}
I think a closure is a good solution for this, but I can't get it working. I have also tried with a for-loop, but it's not a beautiful functional solution.
The simplest solution is to use range, I think:
(1 to n) foreach (x => /* do something */)
But you can also create this small helper function:
implicit def intTimes(i: Int) = new {
def times(fn: => Unit) = (1 to i) foreach (x => fn)
}
10 times println("hello")
this code will print "hello" 10 times. Implicit conversion intTimes makes method times available on all ints. So in your case it should look like this:
event.quantity times queue.enqueue(event.value)
event.quantity times queue.dequeue()
Not quite an answer to your question, but if you had an endomorphism (i.e. a transformation A => A), then using scalaz you could use the natural monoid for Endo[A]
N times func apply target
So that:
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> Endo((_:Int) * 2).multiply(5)
res3: scalaz.Endo[Int] = Endo(<function1>)
scala> res1(3)
res4: Int = 96
A more functional solution would be to use a fold with an immutable queue and Queue's fill and drop methods:
val queue = lst.foldLeft(Queue.empty[Option[BigDecimal]]) { (q, e) =>
e.name match {
case "supply" => q ++ Queue.fill(e.quantity)(e.value)
case "sale" => q.drop(e.quantity)
}
}
Or even better, capture your "supply"/"sale" distinction in subclasses of Event and avoid the awkward Option[BigDecimal] business:
sealed trait Event { def quantity: Int }
case class Supply(quantity: Int, value: BigDecimal) extends Event
case class Sale(quantity: Int) extends Event
val lst = List(
Supply(3, BigDecimal("39.00")),
Sale(1),
Supply(1, BigDecimal("41.00"))
)
val queue = lst.foldLeft(Queue.empty[BigDecimal]) { (q, e) => e match {
case Sale(quantity) => q.drop(quantity)
case Supply(quantity, value) => q ++ Queue.fill(quantity)(value)
}}
This doesn't directly answer your question (how to call a function a specified number of times), but it's definitely more idiomatic.
import List._
fill(10) { println("hello") }
Simple, built-in, and you get a List of Units as a souvenier!
But you'll never need to call a function multiple times if you're programming functionally.
With recursion:
def repeat(n: Int)(f: => Unit) {
if (n > 0) {
f
repeat(n-1)(f)
}
}
repeat(event.quantity) { queue.enqueue(event.value) }
Related
I would like to achieve something akin to the strategy pattern in scala without resorting to pattern matching with a long list of case statements. Here is roughly what I have in mind:
trait HandlerTrait {
def handlerA(...): Unit
def handlerB(...): Unit
}
SomeClass1 extends HandlerTrait {
override def handlerA(...) {...}
override def handlerB(...) {...}
}
SomeClass2 extends HandlerTrait {
override def handlerA(...) {...}
override def handlerB(...) {...}
}
object MyApp extends App {
// 1. define bindings for these implementations
val myBindings = Map(x -> someClass1, y -> someClass2)
// 2. Such that implementation of someMethod targeting handlerA implementations could look like this:
def someMethod(object: ObjectType): Unit = {
myBindings.get(object.x) match {
case Some(entry) => entry.handlerA(object)
case None => ()
}
}
}
A few more things:
I don't know how many SomeClassXXX I will have. I will add as needed
to provide customizations on how to handle A/B/C ...
Given a key, I want to dispatch to the correct class and execute the targeted handler.
Is there a better more concise way of achieving this in scala?
I think one way to reduce boilerplate is to use type system rather than inheritance. For instance, if your handler is of type T => Unit then any function that satisfies this type can be a handler, there is no need to officially declare HandlerTrait and even someMethod.
Whether to use a Map or cases to map from a key to a handler is up to you. Both can be extended to handle new cases.
Here is an example to sum up what I'm proposing:
val currentlyDefinedStrategies: PartialFunction[String, Unit] = {
case "1" => println(1)
case "2" => println(2)
}
val newStrategies: PartialFunction[String, Unit] = {
case "3" => println(3)
}
val defaultStrategy: PartialFunction[String, Unit] = {
case _ => println("default")
}
And usage:
scala> currentlyDefinedStrategies("1")
1
scala> currentlyDefinedStrategies("3")
scala.MatchError: 3 (of class java.lang.String) ...
scala> currentlyDefinedStrategies.orElse(newStrategies)("3")
3
scala> currentlyDefinedStrategies.orElse(newStrategies)("4")
scala.MatchError: 4 (of class java.lang.String)
scala> currentlyDefinedStrategies.orElse(newStrategies).orElse(defaultStrategy)("4")
default
You can achieve similar pattern with Map or using other FP techniques. The main point is to keep the most relevant code and get rid of boilerplate. Of course, HandlerTrait might be useful to you for structuring your code and thinking in terms of classes rather than functions, but the idea is the same.
See also: https://pavelfatin.com/design-patterns-in-scala/#strategy
The above example is a bit simplified and you actually want to pass parameters to handler (println in our case). Here is how:
val currentlyDefinedStrategies: Int => PartialFunction[String, Unit] = (x) => {
case "1" => println("1: " + x)
case "2" => println("2: " + x)
case _ => println("default: " + x)
}
You can fix the argument without choosing a strategy:
scala> val noStrategy = currentlyDefinedStrategies(1)
noStrategy: PartialFunction[String,Unit] = <function1>
... and provide strategy afterwards:
scala> noStrategy("1")
1: 1
Or apply the strategy right away:
scala> currentlyDefinedStrategies(1)("1")
1: 1
You can also decide on your strategy first and then pass an argument:
val currentlyDefinedStrategies: PartialFunction[String, Int => Unit] = {
case "1" => x => println("1: " + x)
case "2" => x => println("2: " + x)
case _ => x => println("default: " + x)
}
scala> val handlerWithChosenStrategy = currentlyDefinedStrategies("1")
handlerWithChosenStrategy: Int => Unit = $anonfun$1$$Lambda$1374/666224848#59a9f3eb
scala> handlerWithChosenStrategy(1)
1: 1
I think the point is that FP is so rich and flexible that strategy pattern is really not a thing. It's basically just some function type that suits your convenience like type Strategy[T, -A, +B] = PartialFunction[T, A => B]. Example:
scala> type Strategy[T, -A, +B] = PartialFunction[T, A => B]
defined type alias Strategy
val currentlyDefinedStrategies: Strategy[String, Int, Unit] = {
case "1" => x => println("1: " + x)
case "2" => x => println("2: " + x)
case _ => x => println("default: " + x)
}
currentlyDefinedStrategies: Strategy[String,Int,Unit] = <function1>
scala> currentlyDefinedStrategies("1")(1)
1: 1
A more advanced concept would be an Expression Problem (here) where you need to extend both the operations you can do on types as well as adding new types.
In scalaz 7.2.6, I want to implement sequence on Disjunction, such that if there is one or more lefts, it returns a list of those, instead of taking only the first one (as in Disjunction.sequenceU):
import scalaz._, Scalaz._
List(1.right, 2.right, 3.right).sequence
res1: \/-(List(1, 2, 3))
List(1.right, "error2".left, "error3".left).sequence
res2: -\/(List(error2, error3))
I've implemented it as follows and it works, but it looks ugly. Is there a getRight method (such as in scala Either class, Right[String, Int](3).right.get)? And how to improve this code?
implicit class RichSequence[L, R](val l: List[\/[L, R]]) {
def getLeft(v: \/[L, R]):L = v match { case -\/(x) => x }
def getRight(v: \/[L, R]):R = v match { case \/-(x) => x }
def sequence: \/[List[L], List[R]] =
if (l.forall(_.isRight)) {
l.map(e => getRight(e)).right
} else {
l.filter(_.isLeft).map(e => getLeft(e)).left
}
}
Playing around I've implemented a recursive function for that, but the best option would be to use separate:
implicit class RichSequence[L, R](val l: List[\/[L, R]]) {
def sequence: \/[List[L], List[R]] = {
def seqLoop(left: List[L], right: List[R], list: List[\/[L, R]]): \/[List[L], List[R]] =
list match {
case (h :: t) =>
h match {
case -\/(e) => seqLoop(left :+ e, right, t)
case \/-(s) => seqLoop(left, right :+ s, t)
}
case Nil =>
if(left.isEmpty) \/-(right)
else -\/(left)
}
seqLoop(List(), List(), l)
}
def sequenceSeparate: \/[List[L], List[R]] = {
val (left, right) = l.separate[\/[L, R], L, R]
if(left.isEmpty) \/-(right)
else -\/(left)
}
}
The first one just collects results and at the end decide what to do with those, the second its basically the same with the exception that the recursive function is much simpler, I didn't think about performance here, I've used :+, if you care use prepend or some other collection.
You may also want to take a look at Validation and ValidationNEL which unlike Disjunction accumulate failures.
I want to update a sequence in Scala, I have this code :
def update(userId: Long): Either[String, Int] = {
Logins.findByUserId(userId) map {
logins: Login => update(login.id,
Seq(NamedParameter("random_date", "prefix-" + logins.randomDate)))
} match {
case sequence : Seq(Nil, Int) => sequence.foldLeft(Right(_) + Right(_))
case _ => Left("error.logins.update")
}
}
Where findByUserId returns a Seq[Logins] and update returns Either[String, Int] where Int is the number of updated rows,
and String would be the description of the error.
What I want to achieve is to return an String if while updating the list an error happenes or an Int with the total number of updated rows.
The code is not working, I think I should do something different in the match, I don't know how I can check if every element in the Seq of Eithers is a Right value.
If you are open to using Scalaz or Cats you can use traverse. An example using Scalaz :
import scalaz.std.either._
import scalaz.std.list._
import scalaz.syntax.traverse._
val logins = Seq(1, 2, 3)
val updateRight: Int => Either[String, Int] = Right(_)
val updateLeft: Int => Either[String, Int] = _ => Left("kaboom")
logins.toList.traverseU(updateLeft).map(_.sum) // Left(kaboom)
logins.toList.traverseU(updateRight).map(_.sum) // Right(6)
Traversing over the logins gives us a Either[String, List[Int]], if we get the sum of the List we get the wanted Either[String, Int].
We use toList because there is no Traverse instance for Seq.
traverse is a combination of map and sequence.
We use traverseU instead of traverse because it infers some of the types for us (otherwise we should have introduced a type alias or a type lambda).
Because we imported scalaz.std.either._ we can use map directly without using a right projection (.right.map).
You shouldn't really use a fold if you want to exit early. A better solution would be to recursively iterate over the list, updating and counting successes, then return the error when you encounter one.
Here's a little example function that shows the technique. You would probably want to modify this to do the update on each login instead of just counting.
val noErrors = List[Either[String,Int]](Right(10), Right(12))
val hasError = List[Either[String,Int]](Right(10), Left("oops"), Right(12))
def checkList(l: List[Either[String,Int]], goodCount: Int): Either[String, Int] = {
l match {
case Left(err) :: xs =>
Left(err)
case Right(_) :: xs =>
checkList(xs, (goodCount + 1))
case Nil =>
Right(goodCount)
}
}
val r1 = checkList(noErrors, 0)
val r2 = checkList(hasError, 0)
// r1: Either[String,Int] = Right(2)
// r2: Either[String,Int] = Left(oops)
You want to stop as soon as an update fails, don't you?
That means that you want to be doing your matching inside the map, not outside. Try is actually a more suitable construct for this purpose, than Either. Something like this, perhaps:
def update(userId: Long): Either[String, Int] = Try {
Logins.findByUserId(userId) map { login =>
update(login.id, whatever) match {
case Right(x) => x
case Left(s) => throw new Exception(s)
}
}.sum
}
.map { n => Right(n) }
.recover { case ex => Left(ex.getMessage) }
BTW, a not-too-widely-known fact about scala is that putting a return statement inside a lambda, actually returns from the enclosing method. So, another, somewhat shorter way to write this would be like this:
def update(userId: Long): Either[String, Int] =
Logins.findByUserId(userId).foldLeft(Right(0)) { (sum,login) =>
update(login.id, whatever) match {
case Right(x) => Right(sum.right + x)
case error#Left(s) => return error
}
}
Also, why in the world does findUserById return a sequence???
I've been trying to enhance my knowledge with scala.
I am trying to implement this function recursively but having difficulty.
My main question IS, how can you accept a list in the parameter that accepts either a list or numbers.
depth(x: Any): Int is the signature you want, then pattern match on x to determine if it's a List[_] or not, where _ indicates you don't care what's in the list. (Using Seq[_] would be the more idiomatic Scala type to use, actually.) Note that the example shown is missing a pair of parens, List(1, 2, List(3))... It also assumes that depth(8) == 0 (for example).
A tricky part is that you shouldn't assume that a nested list will either be the first or last element in the "parent" list, i.e., ...List(1,List(2,3),4)... is possible.
A final bit worth mentioning; if you were building a "production" depth method, it would be worth having a Tree abstraction with Node and Leaf concrete types so you can use a better type signature, depth(tree: Tree[_]): Int, to make it explicitly clear when something represents part of the tree structure vs. data in the tree. Using List here is convenient for the exercise, but a bit ambiguous otherwise, since you could have a tree of stuff where some nodes are actually lists.
I will try to answer this by giving a shot on the recursive solution:
def depth(listOrNum: Any): Int = {
def help(y: Any, c: Int): Int = {
y match {
case y: Int => c
case List(curHead, rest # _*) =>
Math.max(help(curHead, c+1), help(rest, c))
case _ => 0
}
}
help(listOrNum, 0)
}
collect is handy here:
def depth(xs: List[Any]): Int =
1 + xs.collect{case xs: List[_] => depth(xs)}
.foldLeft(0)(_ max _)
P.S. I agree with Dean's comments about the type List[Any] being a poor way to represent trees. List[Any] is a type that should never appear in ordinary Scala code, so I'm sad to see it used in an exercise intended for beginners.
If you are insisting on using for comprehension, I can provide implementation that works with it.
First you define two useful classes
import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Builder
class Folder[T](init : T, step : (T,T) => T) extends Builder[T,T] {
private[this] var state = init
override def += (elem : T) = {
state = step(state, elem)
this
}
override def clear() {
state = init
}
override def result() : T = state
}
class CanBuildFolder[F,T](init : T, step : (T,T) => T) extends CanBuildFrom[F,T,T] {
override def apply() : Builder[T,T] = new Folder(init, step)
override def apply(from : F) : Builder[T,T] = new Folder(init, step)
}
than you can use them with the for comprehension
import scala.math.max
object Test {
val example = List(1, List(2, 3), List( List(4, 5), 6, List(7, List(List(8), 9))))
implicit val maxFolder = new CanBuildFolder[List[Any], Int](0, max)
def depth(source : List[Any]) : Int =
for (x <- source) yield x match {
case l : List[Any] => depth(l) + 1
case _ => 1
}
assert(depth(example) == 5)
}
I'm new to scala and I try to combine several Futures in scala 2.10RC3. The Futures should be executed in sequential order. In the document Scala SIP14 the method andThen is defined in order to execute Futures in sequential order. I used this method to combine several Futures (see example below). My expectation was that it prints 6 but actually the result is 0. What am I doing wrong here? I have two questions:
First, why is the result 0. Second, how can I combine several Futures, so that the execution of the second Future does not start before the first Future has been finished.
val intList = List(1, 2, 3)
val sumOfIntFuture = intList.foldLeft(Future { 0 }) {
case (future, i) => future andThen {
case Success(result) => result + i
case Failure(e) => println(e)
}
}
sumOfIntFuture onSuccess { case x => println(x) }
andThen is for side-effects. It allows you to specify some actions to do after future is completed and before it used for something else.
Use map:
scala> List(1, 2, 3).foldLeft(Future { 0 }) {
| case (future, i) => future map { _ + i }
| } onSuccess { case x => println(x) }
6
I like this generic approach:
trait FutureImplicits {
class SeriallyPimp[T, V](futures: Seq[T]) {
def serially(f: T => Future[V])(implicit ec: ExecutionContext): Future[Seq[V]] = {
val buf = ListBuffer.empty[V]
buf.sizeHint(futures.size)
futures.foldLeft(Future.successful(buf)) { (previousFuture, next) =>
for {
previousResults <- previousFuture
nextResult <- f(next)
} yield previousResults += nextResult
}
}
}
implicit def toSeriallyPimp[T, V](xs: Seq[T]): SeriallyPimp[T, V] =
new SeriallyPimp(xs)
}
Then mix-in the above trait and use it like this:
val elems: Seq[Elem] = ???
val save: Elem => Future[Result] = ???
val f: Future[Seq[Result]] = elems serially save
This code could be improved to preserve the input collection type. See this article for example.