Im looking to extended the iterator to create a new method takeWhileInclusive, which will operate like takeWhile but include the last element.
My issue is what is best practice to extend the iterator to return a new iterator which I would like to be lazy evaluated. Coming from a C# background I normal use IEnumerable and use the yield keyword, but such an option doesn't appear to exist in Scala.
for example I could have
List(0,1,2,3,4,5,6,7).iterator.map(complex time consuming algorithm).takeWhileInclusive(_ < 6)
so in this case the takeWhileInclusive would only have resolve the predicate on the values until I get the a result greater than 6, and it will include this first result
so far I have:
object ImplicitIterator {
implicit def extendIterator(i : Iterator[Any]) = new IteratorExtension(i)
}
class IteratorExtension[T <: Any](i : Iterator[T]) {
def takeWhileInclusive(predicate:(T) => Boolean) = ?
}
You can use the span method of Iterator to do this pretty cleanly:
class IteratorExtension[A](i : Iterator[A]) {
def takeWhileInclusive(p: A => Boolean) = {
val (a, b) = i.span(p)
a ++ (if (b.hasNext) Some(b.next) else None)
}
}
object ImplicitIterator {
implicit def extendIterator[A](i : Iterator[A]) = new IteratorExtension(i)
}
import ImplicitIterator._
Now (0 until 10).toIterator.takeWhileInclusive(_ < 4).toList gives List(0, 1, 2, 3, 4), for example.
This is one case where I find the mutable solution superior:
class InclusiveIterator[A](ia: Iterator[A]) {
def takeWhileInclusive(p: A => Boolean) = {
var done = false
val p2 = (a: A) => !done && { if (!p(a)) done=true; true }
ia.takeWhile(p2)
}
}
implicit def iterator_can_include[A](ia: Iterator[A]) = new InclusiveIterator(ia)
The following requires scalaz to get fold on a tuple (A, B)
scala> implicit def Iterator_Is_TWI[A](itr: Iterator[A]) = new {
| def takeWhileIncl(p: A => Boolean)
| = itr span p fold (_ ++ _.toStream.headOption)
| }
Iterator_Is_TWI: [A](itr: Iterator[A])java.lang.Object{def takeWhileIncl(p: A => Boolean): Iterator[A]}
Here it is at work:
scala> List(1, 2, 3, 4, 5).iterator takeWhileIncl (_ < 4)
res0: Iterator[Int] = non-empty iterator
scala> res0.toList
res1: List[Int] = List(1, 2, 3, 4)
You can roll your own fold over a pair like this:
scala> implicit def Pair_Is_Foldable[A, B](pair: (A, B)) = new {
| def fold[C](f: (A, B) => C): C = f.tupled(pair)
| }
Pair_Is_Foldable: [A, B](pair: (A, B))java.lang.Object{def fold[C](f: (A, B) => C): C}
class IteratorExtension[T](i : Iterator[T]) {
def takeWhileInclusive(predicate:(T) => Boolean) = new Iterator[T] {
val it = i
var isLastRead = false
def hasNext = it.hasNext && !isLastRead
def next = {
val res = it.next
isLastRead = !predicate(res)
res
}
}
}
And there's an error in your implicit. Here it is fixed:
object ImplicitIterator {
implicit def extendIterator[T](i : Iterator[T]) = new IteratorExtension(i)
}
scala> List(0,1,2,3,4,5,6,7).toStream.filter (_ < 6).take(2)
res8: scala.collection.immutable.Stream[Int] = Stream(0, ?)
scala> res8.toList
res9: List[Int] = List(0, 1)
After your update:
scala> def timeConsumeDummy (n: Int): Int = {
| println ("Time flies like an arrow ...")
| n }
timeConsumeDummy: (n: Int)Int
scala> List(0,1,2,3,4,5,6,7).toStream.filter (x => timeConsumeDummy (x) < 6)
Time flies like an arrow ...
res14: scala.collection.immutable.Stream[Int] = Stream(0, ?)
scala> res14.take (4).toList
Time flies like an arrow ...
Time flies like an arrow ...
Time flies like an arrow ...
res15: List[Int] = List(0, 1, 2, 3)
timeConsumeDummy is called 4 times. Am I missing something?
Related
How is it easier to implement function that find and immutable remove the first occurrence in Scala collection:
case class A(a: Int, b: Int)
val s = Seq(A(1,5), A(4,6), A(2,3), A(5,1), A(2,7))
val (s1, r) = s.findAndRemove(_.a == 2)
Result: s1 = Seq(A(1,5), A(4,6), A(5,1), A(2,7)) , r = Some(A(2,3))
It finds the first element that match, and keeps order. It can be improved with List instead of Seq.
case class A(a: Int, b: Int)
val s = Seq(A(1,5), A(4,6), A(2,3), A(5,1), A(2,7))
val (s1, r) = s.findAndRemove(_.a == 2)
println(s1)
println(r)
implicit class SeqOps[T](s:Seq[T]) {
def findAndRemove(f:T => Boolean):(Seq[T], Option[T]) = {
s.foldLeft((Seq.empty[T], Option.empty[T])) {
case ((l, None), elem) => if(f(elem)) (l, Option(elem)) else (l :+ elem, None)
case ((l, x), elem) => (l :+ elem, x)
}
}
}
Yeah, a little late to the party, but I thought I'd throw this in.
Minimum invocations of the predicate.
Works with most popular collection types: Seq, List, Array, Vector. Even Set and Map (but for those the collection has no order to preserve and there's no telling which element the predicate will find first). Doesn't work for Iterator or String.
-
import scala.collection.generic.CanBuildFrom
import scala.language.higherKinds
implicit class CollectionOps[U, C[_]](xs :C[U]) {
def findAndRemove(p :U=>Boolean
)(implicit bf :CanBuildFrom[C[U], U, C[U]]
,ev :C[U] => collection.TraversableLike[U, C[U]]
) :(C[U], Option[U]) = {
val (before, after) = xs.span(!p(_))
before ++ after.drop(1) -> after.headOption
}
}
usage:
case class A(a: Int, b: Int)
val (as, a) = Seq(A(1,5), A(4,6), A(2,3), A(5,1), A(2,7)).findAndRemove(_.a==2)
//as: Seq[A] = List(A(1,5), A(4,6), A(5,1), A(2,7))
//a: Option[A] = Some(A(2,3))
val (cs, c) = Array('g','t','e','y','b','e').findAndRemove(_<'f')
//cs: Array[Char] = Array(g, t, y, b, e)
//c: Option[Char] = Some(e)
val (ns, n) = Stream.from(9).findAndRemove(_ > 10)
//ns: Stream[Int] = Stream(9, ?)
//n: Option[Int] = Some(11)
ns.take(5).toList //List[Int] = List(9, 10, 12, 13, 14)
Try something like this
def findAndRemove(as: Seq[A])(fn: A => Boolean): (Seq[A], Option[A]) = {
val index = as.indexWhere(fn)
if(index == -1) as -> None
else as.patch(index, Nil, 1) -> as.lift(index)
}
val (s1, r) = findAndRemove(s)(_.a == 2)
My version:
def findAndRemove(s:Seq[A])(p:A => Boolean):(Seq[A], Option[A])={
val i = s.indexWhere(p)
if(i > 0){
val (l1, l2) = s.splitAt(i)
(l1++l2.tail, Some(l2.head))
}else{
(s, None)
}
}
I have two partial functions returning unit (f1, f2). For instance, something like that:
val f1 = {
case s: arg => //do some
//etc... lots of cases
}
val f2 = {
case s: anotherArg => //do some
//lots of cases
}
Is there a concise way to compose this to partial functions the way as that if
f(x) = {f1(x); f2(x)} iff f1.isDefinedAt(x) && f2.isDefinedAt(x)
f(x) = f1(x); iff f1.isDefinedAt(x) && !f2.isDefinedAt(x)
f(x) = f2(x); iff !f1.isDefinedAt(x) && f2.isDefinedAt(x)
orElse
f1 orElse f2
Scala REPL
scala> val f: PartialFunction[Int, Int] = { case 1 => 1 }
f: PartialFunction[Int,Int] = <function1>
scala> val g: PartialFunction[Int, Int] = { case 2 => 2 }
g: PartialFunction[Int,Int] = <function1>
scala> val h = f orElse g
h: PartialFunction[Int,Int] = <function1>
scala> h(1)
res3: Int = 1
scala> h(2)
res4: Int = 2
scala> h.isDefinedAt(1)
res6: Boolean = true
scala> h.isDefinedAt(2)
res7: Boolean = true
Both both functions to execute on common cases
Using List of partial functions and foldLeft
Scala REPL
scala> val f: PartialFunction[Int, Int] = { case 1 => 1 case 3 => 3}
f: PartialFunction[Int,Int] = <function1>
scala> val g: PartialFunction[Int, Int] = { case 2 => 2 case 3 => 3}
g: PartialFunction[Int,Int] = <function1>
scala> val h = f orElse g
h: PartialFunction[Int,Int] = <function1>
scala> h(3)
res10: Int = 3
scala> h(3)
res11: Int = 3
scala> val h = List(f, g)
h: List[PartialFunction[Int,Int]] = List(<function1>, <function1>)
scala> def i(arg: Int) = h.foldLeft(0){(result, f) => if (f.isDefinedAt(arg)) result + f(arg) else result }
i: (arg: Int)Int
scala> i(3)
res12: Int = 6
Although pamu's answer is good, I don't like the fact that it is bound to specific Int type. Unfortunately you didn't specify result type well enough, so I see 3 alternatives:
You want to get list of all results of all defined functions and you don't care about which function produced which result. In this case something like this would work:
def callAll[A, B](funcs: List[PartialFunction[A, B]], a: A): List[B] = funcs.foldRight(List.empty[B])((f, acc) => if (f.isDefinedAt(a)) f.apply(a) :: acc else acc)
if order of elements is not important you may use
def callAll[A, B](funcs: List[PartialFunction[A, B]], a: A): List[B] = funcs.foldLeft(List.empty[B])((f, acc) => if (f.isDefinedAt(a)) f.apply(a) :: acc else acc)
which probably will be a bit faster
You want to get Option with Some in case corresponding function is defined at the point or None otherwise. In such case something like this would work:
def callAllOption[A, B](funcs: List[PartialFunction[A, B]], a: A): List[Option[B]] = funcs.map(f => f.lift.apply(a))
If you don't want to create List explicitly, you can use varargs such as:
def callAllOptionVarArg[A, B](a: A, funcs: PartialFunction[A, B]*): List[Option[B]] = funcs.map(f => f.lift.apply(a)).toList
or such curried version to specify value after functions:
def callAllOptionVarArg2[A, B](funcs: PartialFunction[A, B]*)(a: A): List[Option[B]] = funcs.map(f => f.lift.apply(a)).toList
You call functions purely for side effects and return value is not important, in which case you can safely use second (a bit faster) callAll definition
Examples:
val f: PartialFunction[Int, Int] = {
case 1 => 1
case 3 => 3
}
val g: PartialFunction[Int, Int] = {
case 2 => 2
case 3 => 4
}
val fl = List(f, g)
println(callAll(fl, 1))
println(callAll(fl, 3))
println(callAllOption(fl, 2))
println(callAllOptionVarArg(1, f, g))
println(callAllOptionVarArg2(f, g)(3))
List(1)
List(3, 4)
List(None, Some(2))
List(Some(1), None)
List(Some(3), Some(4))
I have a trait like the following
private class SeqConverter[T](implicit val conv : Converter[T]) extends Converter[Seq[T]] {
def toJs(x: Seq[T]): JsAny = {
x.foldLeft(JsArray[JsAny]()) { (acc, next) =>
acc.+:(conv.toJs(next))
}
}
def toScala(x: JsAny): Seq[T] = {
val arr = x.asInstanceOf[JsArray[JsObject]]
var lst = List[T]()
arr foreach { x =>
lst = conv.toScala(x) :: lst
}
lst
}
}
I want to have something more like this
private class SeqConverter[T, F <: Seq[T]](implicit val conv : Converter[T]) extends Converter[F] {
def toJs(x: F): JsAny = {
x.foldLeft(JsArray[JsAny]()) { (acc, next) =>
acc.+:(conv.toJs(next))
}
}
def toScala(x: JsAny): Seq[T] = {
//need to construct empty F here to build it
}
}
But the problem is I have no way to get a member of F in order to start preforming construction of it. Is there any way I could get this to exist? It seems like there should be some kind of way to construct an empty member of F so so that I could use +: in order to convert from 1 kind of sequence to another. Does anything like that exist?
UPDATE: if you want to avoid depending on Scalaz, you can define your own type class and instances thereof:
import scala.language.higherKinds
trait Coll[TS[_], T] {
def zero: TS[T]
def append(a: TS[T], b: TS[T]): TS[T]
def point(x: T): TS[T]
}
object Coll {
implicit def listOfTIsColl[T] = new Coll[List, T] {
def zero = Nil
def append(a: List[T], b: List[T]) = a ++ b
def point(x: T) = List(x)
}
implicit def vectorOfTIsColl[T] = new Coll[Vector, T] {
def zero = Vector.empty
def append(a: Vector[T], b: Vector[T]) = a ++ b
def point(x: T) = Vector(x)
}
}
def foo[T, U, TS[_]](xs: TS[T], x: U)(implicit
coll: Coll[TS, T],
ev1: TS[T] <:< Seq[T],
ev2: U =:= T
) = {
(coll.zero, coll.append(coll.zero, coll.point(x)))
}
assert(foo(Vector(1, 2, 3), 4) == (Vector(), Vector(4)))
// foo(Vector(1, 2, 3), 4.4) -- error: Cannot prove that Double =:= Int
// foo(Vector(1, 2, 3), "hello") -- error: Cannot prove that String =:= Int
Note that it's necessary for T and U to be separate type parameters; with def foo[T, TS[_]](xs: TS[T], x: T) ..., you'd be able to use foo as expected, but things like foo(Vector(1, 2, 3), "hello") would work and the type inferencer would infer a type like Vector[Any]. However, with the above, stricter definition of foo, this won't be allowed, which is, at least in idiomatic functional code, desirable.
Scalaz based solution:
Scalaz Monoid and Applicative will help you:
import scalaz._
import Scalaz._
scala> Monoid[List[Int]].zero
res0: List[Int] = List()
scala> Monoid[Vector[Int]].zero
res1: Vector[Int] = Vector()
scala> Monoid[Vector[Int]].append(Vector(1, 2), Vector(3, 4))
res2: Vector[Int] = Vector(1, 2, 3, 4)
and
scala> Applicative[Vector].point(1)
res0: Vector[Int] = Vector(1)
Then, combining Monoid and Applicative will give you all of zero, append, and point/pure:
def foo[T, TS[_], U](xs: TS[T], x: U)(implicit
monoid: Monoid[TS[T]],
applic: Applicative[TS],
ev1: TS[T] <:< Seq[T],
ev2: U =:= T
) = {
(monoid.zero,
monoid.append(monoid.zero, applic.point(x)))
}
then:
> foo(Vector(1, 2, 3), 4)
res1 = (Vector(),Vector(4))
I'm not confident there aren't any conciser solutions, e.g. one that relies on just one type class, but this one seems to work correctly.
Here is my attempt:
case class A(val a: A, val b: Int){
override def toString() = b.toString
}
lazy val x: A = A(y, 0)
lazy val y: A = A(z, 1)
lazy val z: A = A(x, 2)
The problem comes when trying to do anything with x; causing x to be evaluated starts off a circular evaluation going through x, y, z and ends in a stack overflow. Is there a way of specifying that val a should be computed lazily?
You could use Stream like this:
lazy val stream: Stream[Int] = 0 #:: 1 #:: 2 #:: stream
stream.take(10).toList
// List(0, 1, 2, 0, 1, 2, 0, 1, 2, 0)
In general you should use call-by-name parameters:
class A(_a: => A, val b: Int) {
lazy val a = _a
override def toString() = s"A($b)"
}
Usage:
scala> :paste
// Entering paste mode (ctrl-D to finish)
lazy val x: A = new A(y, 0)
lazy val y: A = new A(z, 1)
lazy val z: A = new A(x, 2)
// Exiting paste mode, now interpreting.
x: A = <lazy>
y: A = <lazy>
z: A = <lazy>
scala> z.a.a.a.a.a
res0: A = A(1)
You need to make A.a itself lazy.
You can do it by turning it into a by name parameter that is used to initialize a lazy field:
class A(a0: => A, val b: Int){
lazy val a = a0
override def toString() = b.toString
}
object A {
def apply( a0: => A, b: Int ) = new A( a0, b )
}
You could also do the same using a helper class Lazy:
implicit class Lazy[T]( getValue: => T ) extends Proxy {
def apply(): T = value
lazy val value = getValue
def self = value
}
It has the advantage that you code is pretty much unchanged except for changing a: A into a: Lazy[A]:
case class A(val a: Lazy[A], val b: Int){
override def toString() = b.toString
}
Note that to access the actual value wrapped in Lazy, you can either use apply or value (as in x.a() or x.a.value)
You can define a lazy circular list using the Stream data type:
lazy val circular: Stream[Int] = 1 #:: 2 #:: 3 #:: circular
You can do the same trick on your own with by-name parameters:
class A(head: Int, tail: => A)
lazy val x = new A(0, y)
lazy val y = new A(1, z)
lazy val z = new A(2, x)
Note that this does not work with case classes.
You could use a by-name parameter.
class A(__a: => A, val b: Int) {
def a = __a
override def toString() = b.toString
}
object A {
def apply(a: => A, b: Int) = new A(a, b)
}
I have this logic that a data file needs to go through a series of operations, but whether or not an operation is needed is controlled by some boolean. Basically the data array goes through the process loop and yields some result.
I wonder if there is an elegant way to code this, hopefully not using vars and lots of if/else statements?
def op1(data): Seq[int]
def op2(data): Seq[int]
def op3(data): Seq[int]
def process(data: Seq[int], b1: boolean, b2: boolean, b3: boolean) = {
//NOT working code, some thing does the following:
var temp: Seq[int] = data
if (b1)
temp = op1(temp)
if(b2)
temp = op2(temp)
if(b3)
temp = op3(temp)
temp
}
In this case I actually prefer your solution, but this is a more functional alternative. I replaced the Seq with Strings, because they are easier to use for examples, but that shouldn't matter.
object SequenceOfOperations {
def op1(data: String) = data + "A" //> op1: (data: String)java.lang.String
def op2(data: String) = data + "B" //> op2: (data: String)java.lang.String
def op3(data: String) = data + "C" //> op3: (data: String)java.lang.String
def process(data: String, b1: Boolean, b2: Boolean, b3: Boolean) = {
val ops =Seq((b1 , op1(_)),(b2 , op2(_)),(b3 , op3(_)))
val filteredOps = ops.filter( _._1).map (_._2)
filteredOps.foldLeft(data)((l : String,o : String => String) => o(l))
} //> process: (data: String, b1: Boolean, b2: Boolean, b3: Boolean)String
process("Z", true, false, true) //> res0: String = ZAC
process("Y", true, true, false) //> res1: String = YAB
process("X", false, false, true) //> res2: String = XC
}
This looks like a typical fold, which you could wrap in the following function:
def maybeDo[A](bs: List[Boolean], fs: List[A => A], x: A) =
(bs zip fs).foldLeft(x) {
case (x, (b, f)) => if (b) f(x) else x
}
Use it for example as follows
> val bs = List(true, false, true)
> val fs: List[Int => Int] = List(_+1, _*3, _+2)
> maybeDo(bs, fs, 10)
res0: Int = 13
In your example it would be something like
val temp = maybeFold(List(b1, b2, b3), List(op1 _, op2 _, op3 _), data)
Assuming you want the process signature not to change...
// continuing from the ops psuedocode
def process(data: Seq[Int], b1:Boolean, b2:Boolean, b3:Boolean): Seq[Int] = {
#tailrec
def loop (acc: Seq[Int], ops: List[Seq[Int] => Seq[Int]]): Seq[Int] = {
ops match {
case List () => acc
case head :: tail => loop (head(acc), tail)
}
}
loop (data, List(( b1,op1 _), (b2,op2 _),(b3,op3 _)).filter{ _._1 }.map{ _._2 })
}
The solution is to pair the op with the correct Boolean, in a List, filter out the pairs with untrue Booleans, map the filtered pairs to a list of ops (basically dropping the boolean part of each surviving pair), Then accumulate your transformations recursively over your input data.
Here's what it results with some simple operators:
import scala.annotations.tailrec
def op1(s: Seq[Int]) = s map {_ + 1}
def op2(s: Seq[Int]) = s map {_ * 2}
def op3(s: Seq[Int]) = s map {_ - 5}
def process(data: Seq[Int], b1:Boolean, b2:Boolean, b3:Boolean): Seq[Int] = {
#tailrec
def loop (acc: Seq[Int], ops: List[Seq[Int] => Seq[Int]]): Seq[Int] = {
ops match {
case List () => acc
case head :: tail => loop (head(acc), tail)
}
}
loop (data, List(( b1,op1 _), (b2,op2 _),(b3,op3 _)).filter{ _._1 }.map{ _._2 })
}
process(Seq(1,2,3), true, false, true) // Seq[Int] = List(-3, -2, -1)
process(Seq(1,2,3), true, false, false) // Seq[Int] = List(2, 3, 4)
process(Seq(1,2,3), false, true, false) // Seq[Int] = List(2, 4, 6)
There are many ways you can achieve this..
One possible way can be..
def op1(data: Seq[Int]) = data.map(_ + 2) //your actual operation here..
def op2(data: Seq[Int]) = data.map(_ - 2) //..returning Seq[Int]
def op3(data: Seq[Int]) = data.map(_ * 2) //
implicit class SeqOps(val data: Seq[Int]) extends AnyVal {
def op(op: Seq[Int] => Seq[Int], b: Boolean) = if (b) op(data) else data
}
And then def process can be written as..
def process(data: Seq[Int], b1: Boolean, b2: Boolean, b3: Boolean) = {
data op (op1, b1) op (op2, b2) op (op3, b3)
}