Let's say I have a list of functions returning Option[Int] and I want to return the result of the first one returning Some(…), and not compute the rest of the functions after it. For example:
val list = List(
() => { println("a"); None },
() => { println("b"); Some(1) },
() => { println("c"); Some(2) },
() => { println("d"); None }
)
In this case, the result will be Some(1), and it will print only a and b (since the rest is not computed).
My solution was
list.foldLeft(Option.empty[Int]) { (a, b) => a orElse b() }
The question if there's a more elegant/concise way of doing it, or maybe some library?
list.view.flatMap(_()).headOption
a and b are only called once. c and d are never invoked or even iterated over. Returns None if there are no Some() values.
The .view wouldn't be needed if list was type LazyList.
Related
I am still learning the basics of Scala, therefore I am asking for your understanding. Is it any possible way to use fold method to print only names beginning with "A"
Object Scala {
val names: List[String] = List("Adam", "Mick", "Ann");
def main(args: Array[String]) {
println(names.foldLeft("my list of items starting with A: ")(_+_));
}
}
}
Have a look at the signature of foldLeft
def foldLeft[B](z: B)(op: (B, A) => B): B
where
z is the initial value
op is a function taking two arguments, namely accumulated result so far B, and the next element to be processed A
returns the accumulated result B
Now consider this concrete implementation
val names: List[String] = List("Adam", "Mick", "Ann")
val predicate: String => Boolean = str => str.startsWith("A")
names.foldLeft(List.empty[String]) { (accumulated: List[String], next: String) =>
if (predicate(next)) accumulated.prepended(next) else accumulated
}
here
z = List.empty[String]
op = (accumulated: List[String], next: String) => if (predicate(next)) accumulated.prepended(next) else accumulated
Usually we would write this inlined and rely on type inference so we do not have two write out full types all the time, so it becomes
names.foldLeft(List.empty[String]) { (acc, next) =>
if (next.startsWith("A")) next :: acc else acc
}
// val res1: List[String] = List(Ann, Adam)
On of the key ideas when working with List is to always prepend an element instead of append
names.foldLeft(List.empty[String]) { (accumulated: List[String], next: String) =>
if (predicate(next)) accumulated.appended(next) else accumulated
}
because prepending is much more efficient. However note how this makes the accumulated result in reverse order, so
List(Ann, Adam)
instead of perhaps required
List(Adam, Ann)
so often-times we perform one last traversal by calling reverse like so
names.foldLeft(List.empty[String]) { (acc, next) =>
if (next.startsWith("A")) next :: acc else acc
}.reverse
// val res1: List[String] = List(Adam, Ann)
The answer from #Mario Galic is a good one and should be accepted. (It's the polite thing to do).
Here's a slightly different way to filter for starts-with-A strings.
val names: List[String] = List("Adam", "Mick", "Ann")
println(names.foldLeft("my list of items starting with A: "){
case (acc, s"A$nme") => acc + s"A$nme "
case (acc, _ ) => acc
})
//output: "my list of items starting with A: Adam Ann"
I have to transform the following function into a curried function:
def findAllUsed(t: List[Task]): List[String] = {
t.flatMap(x => x.resources.map(x => x.FIELD_TO_SEARCH)).distinct
}
So I did this:
def findAllUsed(t: List[Task], f: Resource => String): List[String] = {
t.flatMap(x => x.resources.map(f)).distinct
}
findAllUsed(taskSchedules, ((x: Resource) => { x.id }))
findAllUsed(taskSchedules, ((x: Resource) => { x.kind }))
The problem is that it seems to me that I am confusing currying with higher order functions.
Can anyone if I am doing it right and if not, how could I manage to do it right?
I'm assuming the exercise meant something like this:
// separate into two argument lists
def findAllUsed(t: List[Task])(f: Resource => String): List[String] = {
t.flatMap(x => x.resources.map(f)).distinct
}
// apply the first argument list once,
// getting a curried function as a result
val curried = findAllUsed(taskSchedules)
// now you can use it twice with different inputs for the second argument list:
curried(x => x.id)
curried(x => x.kind)
The benefit here (if there is any), is the removal of the duplication passing taskSchedules to your function: since it has "it's own" argument list, you can pass it once, assign the result into a value (curried), and then reuse it over and over;
p.s. the type of curried is (Resource => String) => List[String] - it's a function from a Resource => String (which is another function...) to a list of strings.
I there, I'm trying to combine the Command and Chain of responsibility patterns with Scala style.
Basically, I would like to have one Executor who pass the command trough the chain and return the result. A command is anything that return a T :
class class Invoker {
type Command[T] = () => T
val handlers = new mutable.ListBuffer[PartialFunction[() => T, T]]
def invoke[T](command: => T): Future[T] = Future {
handlers.find(_.isDefinedAt(command)).map(_.apply(command))
}
}
But, because I'm a scala beginner, I have problems with the generic types for the list of handlers. I cannot figure how to define T in the declaration of handlers so that the invoke command return the correct type (wich should be T)
Can someone help me to implement this pattern ?
There are several sketchy places, but I think the closest you'll get to what you want would be (Though, it will not work, see below):
import scala.collection.mutable
import scala.concurrent.Future
object Invoker {
val handlers = new mutable.ListBuffer[PartialFunction[Any, Any]]
def invoke[T](command: () => T): Future[T] = Future {
handlers.collectFirst {
case pf if pf.isDefinedAt(command) => pf(command)
}.fold(throw new Exception("failure")) {
_.asInstanceOf[T]
}
}
}
However,
It will not work because, the partial functions or more specifically pattern matching will most certainly not work as you expect for Function0
You loose most of your type information through erasure and have to rely upon what you know about the partial functions.
In scala, the need to call asInstanceOf is a good indicator that something can be done better.
#1
When you define a list of partial functions that match on Function0 like for example this:
val T1: () => Int = () => 1
val T2: () => Int = () => 2
val T3: () => Int = () => 3
val pfs: Seq[PartialFunction[Any, Any]] = Seq(
PartialFunction[Any, Any] {
case T1 => T1()
},
PartialFunction[Any, Any] {
case T2 => T2()
},
PartialFunction[Any, Any] {
case T3 => T3()
}
)
Trying to find a match for any function literal will lead to a MatchError:
def invoke[T](c: () => T): T = {
pfs.collectFirst {
case pf if pf.isDefinedAt(c) => pf(c)
}.fold(throw new Exception("failure")) {
_.asInstanceOf[T]
}
}
invoke(() => 1) |-> scala.MatchError: <function0> (of class abc.A$A290$A$A290$$anonfun$ti1$1)
This would only work if you define Constants for allowed functions and only use those constants, when you call invoke.
You could define them with the Invoker object:
object Invoker {
val SomeCommand = () => 5 + 5
val AnotherCommand = () => 5 * 5
}
But that would utterly eliminate any flexibility.
FINALLY:
If you want to be able to perform any Command then why maintain a list of handlers anyway?
object Invoker {
def invoke[T](command: () => T): Future[T] = Future {
command()
}
}
should be sufficient for that.
I have the following data structure
val list = List(1,2,
List(3,4),
List(5,6,7)
)
I want to get this as a result
List(
List(1,2,3,5), List(1,2,3,6), List(1,2,3,7),
List(1,2,4,5), List(1,2,4,6), List(1,2,4,7)
)
Number of sub-lists in the input and number of elements in them can vary
P.S.
I'm trying to use this as a first step
list.map{
case x => List(x)
case list:List => list
}
and some for comprehension, but it won't work because I don't know how many elements each sublist of the result will have
Types like List[Any] are most often avoided in Scala – so much of the power of the language comes from its smart type system, and this kind of type impedes this. So your instinct to turn the list into a normalized List[List[Int]] is spot on:
val normalizedList = list.map {
case x: Int => List(x)
case list: List[Int #unchecked] => list
}
Note that this will eventually throw a runtime exception if list includes a List of some type other than Int, such as List[String], due to type erasure. This is exactly the kind of problem that arises when failing to use strong types! You can read more about strategies for dealing with type erasure here.
Once you have a normalized List[List[Int]], then you can use foldLeft to build the combinations. You are also correct in seeing that a for comprehension can work well here:
normalizedList.foldLeft(List(List.empty[Int])) { (acc, next) =>
for {
combo <- acc
num <- next
} yield (combo :+ num)
}
In each iteration of the foldLeft, we consider one more sublist (next) from the normalizedList. We look at each combination thus far constructed (each combo in acc), and then for each number num in next, we make a new combination by appending it to combo.
As you might now, for comprehensions are really syntactic sugar for map, flatMap, and filter operations. So we can also express this with those more primitive methods:
normalizedList.foldLeft(List(List.empty[Int])) { (acc, next) =>
acc.flatMap { combo =>
next.map { num => combo :+ num }
}
}
You can even use the (somewhat silly) :/ alias for foldLeft, switch the order of the maps, and use underscore syntax for ultimate brevity:
(List(List[Int]()) /: normalizedList) { (acc, next) => next.flatMap { num => acc.map(_ :+ num) } }
val list = List(1,2,
List(3,4),
List(5,6,7)
)
def getAllCombinations(list: List[Any]) : List[List[Int]] ={
//normalize head so it is always a List
val headList: List[Int] = list.head match {
case i:Int => List(i)
case l:List[Int] => l
}
if(list.tail.nonEmpty){
// recursion for tail combinations
val tailCombinations : List[List[Int]] = getAllCombinations(list.tail)
//combine head combinations with tail combinations
headList.flatMap(
{i:Int => tailCombinations.map(
{l=>List(i).++(l)}
)
}
)
}
else{
headList.map(List(_))
}
}
print(getAllCombinations(list))
This can be achieved with the use of a foldLeft, as well. In the code below, each item of the outer List is folded into the List of List's by combining each current list with each new item.
val list = List(1,2, List(3,4), List(5,6,7) )
val lxl0 = List( List[Int]() ) //start value for foldLeft
val lxl = list.foldLeft( lxl0 )( (lxl, i) => {
i match {
case i:Int => for( l <- lxl ) yield l :+ i
case newl:List[Int] => for( l <- lxl;
i <- newl ) yield l :+ i
}
})
lxl.map( _.mkString(",") ).foreach( println(_))
While I didn't use the map that you desired, I do believe that the code may be changed to do the map and make all elements List[Int]. Then, that may simplify the foldLeft to simply do the for-comprehension. I was not able to get that to work immediately, though ;)
I'd like to implement validation for a sequence of operations that all return Either[Error,Item]
It should be fail-fast (in my initial need), I mean, returning Either[Error,Seq[Item]].
If there is an error, it's obvious i do not want the following operations to be performed.
But in the future i may want to collect all the errors instead of returning only the first one.
I know Scalaz can do the job but for now I quite don't understand all parts of Scalaz and I'm pretty sure there's a simpler way to do it without using Scalaz, but using by-name parameters for exemple.
Is there a way to store by-name parameters in a sequence?
So that i can create a sequence of by-name values that represent my operations?
I mean, some kind of type Seq[=> Either[Error,Item]]
Then I could do something like calling takeWhile or collectFirst or something somilar, without all the operations being performed before the creation of the sequence?
I would expect the operations to be performed only when iterating on the sequence.
Thanks
You can indeed use a Seq[() => Either[Error, Item]] to defer the computation at collection creation time. So for example
val doSomething1: () => Either[Error, Item] = () => { println(1); Right(1) }
val doSomething2: () => Either[Error, Item] = () => { println(2); Right(2) }
val doSomething3: () => Either[Error, Item] = () => { println(3); Left("error") }
val doSomething4: () => Either[Error, Item] = () => { println(4); Right(3) }
val doSomething5: () => Either[Error, Item] = () => { println(5); Left("second error") }
val l = Seq(doSomething1, doSomething2, doSomething3, doSomething4, doSomething5)
(Items are Ints in the example and Errors are Strings)
Then you can process them lazily stopping at first failure using the following recursive function:
def processUntilFailure(l: Seq[() => Either[Error, Item]]): Either[Error, Seq[Item]] = {
l.headOption.map(_.apply() match {
case Left(error) => Left(error)
case Right(item) => processUntilFailure(l.tail).right.map(_ :+ item)
}).getOrElse(Right(Nil))
}
So now when I run processUntilFailure(l)
scala> processUntilFailure(l)
1
2
3
res1: Either[Error,Seq[Item]] = Left(error)
If you wanted to generate a Either[Seq[String], Seq[Int]] (processing all the operations). You could do it with a little change:
def processAll(l: Seq[() => Either[Error, Item]]): Either[Seq[Error], Seq[Item]] = {
l.headOption.map(_.apply() match {
case Left(error) => processAll(l.tail) match {
case Right(_) => Left(Seq(error))
case Left(previousErrors) => Left(previousErrors :+ error)
}
case Right(item) => processAll(l.tail).right.map(_ :+ item)
}).getOrElse(Right(Nil))
}
The only change as you can see is the Left case in the pattern match. Running this one:
scala> processAll(l)
1
2
3
4
5
res0: Either[Seq[Error],Seq[Item]] = Left(List(second error, error))
processAll can be replaced with a generic foldLeft on l
val zero: Either[Seq[Error], Seq[Item]] = Right(Seq[Item]())
l.foldLeft(zero) { (errorsOrItems: Either[Seq[Error], Seq[Item]], computation: () => Either[String, Int]) =>
computation.apply().fold(
{ (error: String) => Left(errorsOrItems.left.toOption.map(_ :+ error).getOrElse(Seq(error))) },
{ (int: Int) => errorsOrItems.right.map(_ :+ int) })
}
processUntilFailure can as well but not easily. Since aborting early from a fold is tricky. Here's a good answer about other possible approaches when you find yourself needing to do that.
You should be able to pull this off with the type Seq[Function0[Either[Error, Item]]]. Function0 is, obviously, a zero-argument function. The rest should be self-explanatory.
Scalaz provides the type IO for exactly this purpose, so you could actually use that as well. You may not want to yet, however, if you're just beginning to work with Scalaz.