I'm confused with scala pattern matching behaviour, see code below:
import java.util.concurrent.atomic.AtomicLong
object LongPatternMatching {
def main(args: Array[String]): Unit = {
useJavaLong
useScalaLong
useComplexJavaLong
}
def useScalaLong: Unit = {
val aLong: Long = Long.MaxValue
aLong match {
case v if v == Long.MinValue => println("min")
case v if v == Long.MaxValue => println("max")
}
}
def useJavaLong: Unit = {
val aLong: java.lang.Long = java.lang.Long.MAX_VALUE
aLong match {
case v if v == java.lang.Long.MIN_VALUE => println("min")
case v if v == java.lang.Long.MAX_VALUE => println("max")
}
}
def useComplexJavaLong: Unit = {
val counter: AtomicLong = new AtomicLong(0)
counter.incrementAndGet() match {
case count if count % 1000 == 0 => println(count)
}
}
}
First two functions are ok, but third(useComplexJavaLong) throws scala.MatchError: 1 (of class java.lang.Long)
useComplexJavaLong only matches a single case where the remainder of the modolu operation is 0. What happens if the remainder isn't equal to 0? You get a MatchError since there is no case which handles that. In the case of your example, 1 % 1000 is equal to 1, not 0, and thus the pattern match blows up. You'll need an additional case:
def useComplexJavaLong: Unit = {
val counter: AtomicLong = new AtomicLong(0)
counter.incrementAndGet() match {
case count if count % 1000 == 0 => println(count)
case count => println(s"Remainder equals: ${count % 1000}")
}
}
Because the pattern matching in the method useCompleJavaLong is not complete. You can change it to
def useComplexJavaLong: Unit = {
val counter: AtomicLong = new AtomicLong(0)
counter.incrementAndGet() match {
case count if count % 1000 == 0 => println(count)
case other => println(other)
}
}
Related
I'm trying to figure out how to create an Akka Streams source that generates many Seq[Int].
Basically, given an int n I want to generate all of the Seq[Int] of 1 to n
Here's some code that does this:
def combinations(n: Int): Seq[Seq[Int]] = {
def loop(acc: (Seq[Int], Seq[Seq[Int]]),
remaining: Seq[Int]): Seq[Seq[Int]] = {
remaining match {
case s if s.size == 1 => {
val total: Seq[Seq[Int]] = acc._2
val current: Seq[Int] = acc._1
total :+ (current :+ s.head)
}
case _ => {
for {
x <- remaining
comb <- loop((acc._1 :+ x, acc._2), remaining.filter(_ != x))
} yield comb
}
}
}
loop((Seq(), Seq()), (1 to n))
}
This works fine up to 10... then it blows up because it runs out of memory. Since I just want to process each of them and don't need to keep them all in memory, I thought... Akka Streams. But I'm at a loss for how to turn this into a Source that produces each combination so I can process them. Basically there where it's appending to total I would produce another item onto the stream.
Here is a solution that uses the Johnson-Trotter algorithm for permutations. tcopermutations creates a LazyList that can be evaluated as needed. For more permutations, just pass a different value to printNIterations.
The reason for using the Johnson-Trotter algorithm is that it breaks the recursive structure of the permutation finding algorithm. That's important for being able to evaluate successive instances of the permutation and storing them in some kind of lazy list or stream.
object PermutationsTest {
def main(args: Array[String]) = {
printNIterations(50, tcopermutations(5).iterator)
}
def printNIterations(n: Int, it: Iterator[Seq[Int]]): Unit = {
if (n<=0) ()
else {
if (it.hasNext) {
println(it.next())
printNIterations(n - 1, it)
} else ()
}
}
def naivepermutations(n: Int): Seq[Seq[Int]] = {
def loop(acc: Seq[Int], remaining: Seq[Int]): Seq[Seq[Int]] = {
remaining match {
case s if s.size == 1 => {
val current: Seq[Int] = acc
Seq((current :+ s.head))
}
case _ => {
for {
x <- remaining
comb <- loop(acc :+ x, remaining.filter(_ != x))
} yield comb
}
}
}
loop(Seq(), (1 to n))
}
def tcopermutations(n: Int): LazyList[Seq[Int]] = {
val start = (1 to n).map(Element(_, Left))
def loop(v: Seq[Element]): LazyList[Seq[Element]] = {
johnsonTrotter(v) match {
case Some(s) => v #:: loop(s)
case None => LazyList(v)
}
}
loop(start).map(_.map(_.i))
}
def checkIfMobile(seq: Seq[Element], i: Int): Boolean = {
val e = seq(i)
def getAdjacent(s: Seq[Element], d: Direction, j: Int): Int = {
val adjacentIndex = d match {
case Left => j - 1
case Right => j + 1
}
s(adjacentIndex).i
}
if (e.direction == Left && i == 0) false
else if (e.direction == Right && i == seq.size - 1) false
else if (getAdjacent(seq, e.direction, i) < e.i) true
else false
}
def findLargestMobile(seq: Seq[Element]): Option[Int] = {
val mobiles = (0 until seq.size).filter{j => checkIfMobile(seq, j)}
if (mobiles.isEmpty) None
else {
val folded = mobiles.map(x=>(x,seq(x).i)).foldLeft(None: Option[(Int, Int)]){ case (acc, elem) =>
acc match {
case None => Some(elem)
case Some((i, value)) => if (value > elem._2) Some((i, value)) else Some(elem)
}
}
folded.map(_._1)
}
}
def swapLargestMobile(seq: Seq[Element], index: Int): (Seq[Element], Int) = {
val dir = seq(index).direction
val value = seq(index).i
dir match {
case Right =>
val folded = seq.foldLeft((None, Seq()): (Option[Element], Seq[Element])){(acc, elem) =>
val matched = elem.i == value
val newAccOpt = if (matched) Some(elem) else None
val newAccSeq = acc._1 match {
case Some(swapMe) => acc._2 :+ elem :+ swapMe
case None => if (matched) acc._2 else acc._2 :+ elem
}
(newAccOpt, newAccSeq)
}
(folded._2, index + 1)
case Left =>
val folded = seq.foldRight((None, Seq()): (Option[Element], Seq[Element])){(elem, acc) =>
val matched = elem.i == value
val newAccOpt = if (matched) Some(elem) else None
val newAccSeq = acc._1 match {
case Some(swapMe) => swapMe +: elem +: acc._2
case None => if (matched) acc._2 else elem +: acc._2
}
(newAccOpt, newAccSeq)
}
(folded._2, index - 1)
}
}
def revDirLargerThanMobile(seq: Seq[Element], mobile: Int) = {
def reverse(e: Element) = {
e.direction match {
case Left => Element(e.i, Right)
case Right => Element(e.i, Left)
}
}
seq.map{ elem =>
if (elem.i > seq(mobile).i) reverse(elem)
else elem
}
}
def johnsonTrotter(curr: Seq[Element]): Option[Seq[Element]] = {
findLargestMobile(curr).map { m =>
val (swapped, newMobile) = swapLargestMobile(curr, m)
revDirLargerThanMobile(swapped, newMobile)
}
}
trait Direction
case object Left extends Direction
case object Right extends Direction
case class Element(i: Int, direction: Direction)
}
I learned about extractors from the stairway book:
object Twice {
def apply(x: Int) = x * 2
def unapply(x: Int) = if(x % 2 == 0) Some(x / 2) else None
}
// outside pattern mathcing, Twice.apply(21) is called
val x = Twice(21)
x match {
// inside pattern matching, Twice.unapply(x) is called,
// the result Some(21) is matched against y,
// y gets the value 21
case Twice(y) => println(x + " is twice " + y)
case _ => println(x + " is odd.")
}
That's pretty straight forward. But today I read from some book on Play framework this code:
trait RequestExtractors extends AcceptExtractors {
//Convenient extractor allowing to apply two extractors.
object & {
def unapply(request: RequestHeader): Option[(RequestHeader, RequestHeader)] = Some((request, request))
}
}
//Define a set of extractors allowing to pattern match on the Accept HTTP header of a request
trait AcceptExtractors {
//Common extractors to check if a request accepts JSON, Html, etc.
object Accepts {
import play.api.http.MimeTypes
val Json = Accepting(MimeTypes.JSON)
val Html = Accepting(MimeTypes.HTML)
val Xml = Accepting(MimeTypes.XML)
val JavaScript = Accepting(MimeTypes.JAVASCRIPT)
}
}
//Convenient class to generate extractors checking if a given mime type matches the Accept header of a request.
case class Accepting(val mimeType: String) {
def unapply(request: RequestHeader): Boolean = request.accepts(mimeType)
def unapply(mediaRange: play.api.http.MediaRange): Boolean = mediaRange.accepts(mimeType)
}
def fooBar = Action {
implicit request =>
val xmlResponse: Node = <metadata>
<company>TinySensors</company>
<batch>md2907</batch>
</metadata>
val jsonResponse = Json.obj("metadata" -> Json.arr(
Json.obj("company" -> "TinySensors"),
Json.obj("batch" -> "md2907"))
)
render {
case Accepts.Xml() => Ok(xmlResponse)
case Accepts.Json() & Accepts.JavaScript() => Ok(jsonResponse)
}
}
How does the extractor work when the unapply function returns Boolean instead of Option? How do &, Accepts.Xml work here?
I can really tell you about the play framework, but if used in pattern matching an extractor returning a boolean signifies if the pattern matches. Thus if an extractor return true it means that the pattern matches the value. This is a good link about extractors and also covers this case:
http://danielwestheide.com/blog/2012/11/21/the-neophytes-guide-to-scala-part-1-extractors.html
Generally you use extractors for two use cases:
1) Destructing an object, which means returning one or more values which represent the state of given object
2) You can also use extractors to turn an object into an object of another kind during pattern matching. I made a small example for this case:
class Division(val number: Int) {
}
object Division {
def unapply(divider: Division): Boolean = divider.number != 0
def unapply(divider: Int): Option[Division] = if (divider != 0) Some(new Division(divider)) else None
}
val divident = 15
val divider = 5
val y = divider match {
case Division(notZero) => divident / notZero.number //notZero is of type Division
case _ => throw new IllegalArgumentException()
}
Ok, I found a way to figure this out by making a minimal example:
object Unapply {
case class DividedBy(val number: Int) {
def unapply(divider: Int): Boolean = number % divider == 0
def unapply(divider: Double): Boolean = number % divider.toInt == 0
}
val x = DividedBy(15)
// y should be true
val y = 5 match {
// case DividedBy(15)() => true
case x() => true
case _ => false
}
}
The weird thing is that when you use DividedBy(15)() (commented out above), the code won't compile.
Update:
object Unapply {
case class Division(val number: Int) {
// def unapply(divider: Int): Boolean = number % divider == 0
def unapply(divider: Int): Option[(Int, Int)] = if (number % divider == 0) Some(number/divider, 0) else None
def unapply(divider: Double): Boolean = number % divider.toInt == 0
}
object Division {
def apply(number: Int) = new Division(number)
}
val divisionOf15 = Division(15)
// y should be true
val y = 5 match {
// case DividedBy(15)() => true
case divisionOf15(z, w) => s"$z, $w"
case _ => s"Not divisible"
}
val z = 5.0 match {
case divisionOf15() => "Divisible"
case _ => "Not divisible"
}
}
After some reading some old notes on the stairway book now I have a clearer understanding of this. The case class is a extractor factory.
I want to return an integer type from an if block like in this sample code:
def a {
val res = if (1 == 1) {
val x = 1
b(x)
}
}
def b(x:Int) = {
20
}
Here the type of res is val res: AnyVal
How can I change it to Int?
If you don't have a default value to return, then you could return an Option[Int] instead, and combine this with getOrElse:
def a(n: Int): Option[Int] = {
if (n < 100) {
Some(n * 2)
} else {
None
}
}
a(10).getOrElse("Something else")
Another possibility is to use partial functions, because in your case your first function does not cover all cases, and you want to have a fallback:
val a: PartialFunction[Int, Int] = {
case n if n < 100 =>
n * 2
}
val b: PartialFunction[Int, String] = {
case _ =>
"Something else"
}
Then you can use applyOrElse:
// If function a is not defined for the input, then call function b
val result = a.applyOrElse(10, b)
or combine both partial functions into another function, and call that one:
// Combine a and b
val cf = a.orElse(b)
// Call
val result = cf(10)
You have to add else alternative, for example:
def a {
val res = if (1 == 1) {
val x = 1
b(x)
} else 0
}
This happens because for absent else case compiler uses Unit. And nearest common type for Int and Unit is AnyVal.
The reason you didn't get a determined int is that: your if block miss some code path. So if you change to:
val res = if (i == 1) {
val x = 1
b(x)
} else {
0 // some default value
}
That will be fine.
To have an immutable value val res well-defined with an if-else expression, both parts of the expression need be declared, as aforementioned. Even in the case of a mutable variable
var res: Int = _
the compiler instantiates it to a default 0. Thereafter it is valid for instance to
if (1 == 1) res = 20
without having to define the else part.
I have this code and I want to let Stream to stop iteration and also get the accumulated result. Basically, the iteration is based on errorLimit number
sealed trait Ele
case class FailureEle() extends Ele
case class SuccessEle() extends Ele
type EitherResult = Either[IndexedSeq[Ele], Seq[FailureEle]]
def parse(process: Process[Task, Ele], errorLimit: Int): EitherResult = {
val errorAccumulator = new ListBuffer[FailureEle]
val taskProcess = process.map(t => {
t match {
case x: FailureEle => errorAccumulator += x
case _ =>
}
t
}).takeWhile(_ => !(errorAccumulator.size == errorLimit))
val voSeq = taskProcess.runLog.run
if (errorAccumulator.isEmpty) {
Left(voSeq)
} else {
Right(errorAccumulator)
}
}
val result = Seq(FailureEle(), SuccessEle(), FailureEle(), SuccessEle(), SuccessEle(), FailureEle(), SuccessEle())
val adaptor = new SeqAdaptor[Ele](result)
val process: Process[Task, Ele] = Process
.repeatEval(Task {adaptor.next()}).takeWhile(t => !t.shouldStop).map(_.get)
parse(process, 1).isRight //no SuccessEle will be iterated
parse(process, 2).isRight //only one SuccessEle will be iterated
parse(process, 3).isRight //the last one SuccessEle will not be iterated
It is working, but there are several issues that I want to refactor the parse method to be more functional:
ListBuffer is an imperative way
takeWhile condition has no logic to check current element, it is still using ListBuffer result
so I wonder is there a tail recursion way to replace the imperative way by using ListBuffer.
scan may not be better enough, but works
sealed trait Ele
case class FailureEle(e: Throwable) extends Ele
case class SuccessEle(r: String) extends Ele
def parse(p: Process[Task, Ele], error: Int): Process[Task, (Seq[SuccessEle], Seq[FailureEle])] = {
p.scan(Seq[SuccessEle]() -> Seq[FailureEle]()) { (r, e) =>
val (s, f) = r
e match {
case fail: FailureEle =>
s -> (f :+ fail)
case succ: SuccessEle =>
(s :+ succ) -> f
}
}.dropWhile { case (succ, fail) => fail.size < error }.take(1)
}
def test() {
def randomFail = {
val nInt = scala.util.Random.nextInt()
println("getting" + nInt)
if(nInt % 5 == 0 )
FailureEle(new Exception("fooo"))
else
SuccessEle(nInt.toString)
}
val infinite = Process.repeatEval(Task.delay(randomFail))
val r = parse(infinite, 3).runLast.run
println(r)
}
I am Peter Pilgrim. I watched Martin Odersky create a control abstraction in Scala. However I can not yet seem to repeat it inside IntelliJ IDEA 9. Is it the IDE?
package demo
class Control {
def repeatLoop ( body: => Unit ) = new Until( body )
class Until( body: => Unit ) {
def until( cond: => Boolean ) {
body;
val value: Boolean = cond;
println("value="+value)
if ( value ) repeatLoop(body).until(cond)
// if (cond) until(cond)
}
}
def doTest2(): Unit = {
var y: Int = 1
println("testing ... repeatUntil() control structure")
repeatLoop {
println("found y="+y)
y = y + 1
}
{ until ( y < 10 ) }
}
}
The error message reads:
Information:Compilation completed with 1 error and 0 warnings
Information:1 error
Information:0 warnings
C:\Users\Peter\IdeaProjects\HelloWord\src\demo\Control.scala
Error:Error:line (57)error: Control.this.repeatLoop({
scala.this.Predef.println("found y=".+(y));
y = y.+(1)
}) of type Control.this.Until does not take parameters
repeatLoop {
In the curried function the body can be thought to return an expression (the value of y+1) however the declaration body parameter of repeatUntil clearly says this can be ignored or not?
What does the error mean?
Here is a solution without the StackOverflowError.
scala> class ConditionIsTrueException extends RuntimeException
defined class ConditionIsTrueException
scala> def repeat(body: => Unit) = new {
| def until(condition: => Boolean) = {
| try {
| while(true) {
| body
| if (condition) throw new ConditionIsTrueException
| }
| } catch {
| case e: ConditionIsTrueException =>
| }
|
| }
| }
repeat: (body: => Unit)java.lang.Object{def until(condition: => Boolean): Unit}
scala> var i = 0
i: Int = 0
scala> repeat { println(i); i += 1 } until(i == 3)
0
1
2
scala> repeat { i += 1 } until(i == 100000)
scala> repeat { i += 1 } until(i == 1000000)
scala> repeat { i += 1 } until(i == 10000000)
scala> repeat { i += 1 } until(i == 100000000)
scala>
According to Jesper and Rex Kerr here is a solution without the Exception.
def repeat(body: => Unit) = new {
def until(condition: => Boolean) = {
do {
body
} while (!condition)
}
}
You don't need the 2nd pair of braces, the usage should be:
repeatLoop (x) until (cond) //or...
repeatLoop {x} until {cond}
And not:
repeatLoop {x} { until(cond) } //EXTRA PAIR OF BRACES
The error means that Scala thinks you are trying to call a method with a signature something like:
def repeatLoop(x: => Unit)(something: X) //2 parameter lists
And can find no such method. It is saying "repeatLoop(body)" does not take parameters. A full code listing for the solution probably looks something a bit more like:
object Control0 {
def repeatLoop(body: => Unit) = new Until(body)
class Until(body: => Unit) {
def until(cond: => Boolean) {
body;
val value: Boolean = cond;
if (value) repeatLoop(body).until(cond)
}
}
def main(args: Array[String]) {
var y: Int = 1
println("testing ... repeatUntil() control structure")
repeatLoop {
println("found y=" + y)
y += 1
}.until(y < 10)
}
}
There are two useful observations to make here:
The solution is not tail-recursive and will result in a StackOverflowError for long iterations (try while (y < 10000))
The until seems the wrong way round to me (it would be more natural to stop when the condition becomes true, not carry on while it is true).
How about a one liner for repeat until.
def repeat(b: => Unit) = new AnyRef {def until(c: => Boolean) {b; while (! c) b}}
Which, for example, gives:-
scala> repeat {
| println("i = "+i)
| i+=1
| } until (i >= 10)
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
As above yet recursive :)
def repeat(b: => Unit) = new {def until(c: => Boolean) = { b; if (c) until(c) }}
var i = 0
repeat {
println(i)
i+=1
} until (i < 10)
It's #tailrec optimized too.
Llove scala :)