Scala case classes and tail recursion best practices - scala

I'm fairly new to scala from java and also pretty new to pattern matching. One of the things I'm trying to get my head around is when to use it and what it's costs/benefits are. For example this
def myThing(a: Int): Int = a match {
case a: Int if a > 0 => a
case _ => myThing(a + 1)
}
Does the same thing as this (unless I've really misunderstood something)
def myThing(a: Int): Int = {
if (a > 0) a
else myThing(a + 1)
}
So my actual question:
But do they run the same way? Is my pattern matched example tail recursive? And if not, then why not when it is in the second example?
Are there any other things I should worry about, like resources? Or should I pretty much always try to use pattern matching?
I've searched around for these answers but haven't found any "best practices" for this!
Edit: I'm aware that the example used is a bit contrived - I've just added it to be clear about the question below it - thanks!

Yes they do run the same. Best practice for every syntactic sugar is the same: use it whenever it provides more readable or flexible code. In your examples in case of if statement you may omit braces and write just
def myThing(a: Int): Int = if (a > 0) a else myThing(a + 1)
Which is definitely more handy than pattern matching. Pattern matching is handy in situations where:
You have 3 or more alternatives
You should unpack\check values through extractors (check this question)
You should check the types
Also to ensure you function is tail-recursive you could use the #tailrec annotation

Another 'Scala' way to do it would be to define an extractor for a positive number
def myThing(a: Int): Int = a match {
case PositiveNum(positive) => positive
case negative => myThing(negative + 1)
}
object PositiveNum {
def unapply(n: Int): Option[Int] = if (n > 0) Some(n) else None
}

Yet another way to pattern-match against the evaluated predicate (condition),
def myThing(a: Int): Int = a > 0 match {
case true => a
case _ => myThing(a + 1)
}
where matches include no (additional) guards or type declarations.

Related

How to handle Option in recursive functions in functional programming within Scala?

I recently picked up interests in functional programming, and I'm working with some toy script.
One example is, taking a list of integers, adding them up in sequence, and get the index when the rolling sum reaches a certain value, say -1.
This is what I have now:
#tailrec
def someFunc(currentSum: Int, list: List[Int], index: Int): Int = {
if (currentSum == -1) return index
// Return -1 if the value is never reached
if (index >= list.length) return -1
val value = list(index)
someFunc(currentSum + value, list, index + 1)
}
This works, and if the rolling sum never reaches -1, function will return -1.
I'm not exactly happy with returning -1 in this case, after some readings, I was introduced to the concept of Option, basically I could have Some value or None. I figured this might be the proper solution in this scenario, so I changed my code to this:
#tailrec
def someFunc(currentSum: Int, list: List[Int], index: Int): Option[Int] = {
if (currentSum == -1) return Some(index)
if (index >= list.length) return None
val value = list(index)
someFunc(currentSum + value, list, index + 1)
}
Now my question is, is there anything I can do to avoid adding Some(index) in the 3rd line? In this case it seems trivial, but for more complex situation, it seems a bit unnecessary to add Some everywhere down in the chain.
Also I'm also wondering if this is the proper functional way to handle this type of situation?
What you are asking is this: ""I should just be able type return index instead of typing return Some(index), and scala-compiler should understand that since this function returns a Option, so I actually mean the latter"".
it seems a bit unnecessary to add Some everywhere
It is not unnecessary. If what you ask is fulfilled, this will result in ambiguity. Consider this scenario:
def hypotheticalFunction(....): Option[Option[Int]]: = {
if (some-condition ) return None --> ambigious
// more code
}
Does the return None mean return Some(None) or return None? We have no way of knowing.
==========================================
Also I'm also wondering if this is the proper functional way to handle this type of situation?
I can think of at least 2 improvements:
Generally return statements are discouraged, code-readability can take a setback by arbitrary breaking of function flow by a return. You can use this:
if (condition) Some(index)
else if (condition) None
else {
}
Since earlier parts of list is not needed in recursive calls, you can only send the tail of the the list to the recursive function. In this way, you won't have to iterate the list by calling list(index). Some snippet:
#tailrec
def someFunc(currentSum: Int, list: List[Int], index: Int): Option[Int] = {
if (currentSum == -1) Some(index)
else if (list.isEmpty) None
else {
val value = list.head
someFunc(currentSum + value, list.tail, index + 1)
}
}
Not sure what you mean by "everywhere down the chain". There are pretty much just two cases - either Some or None. And yeah, you have to specify which is which.
A pattern match can make this case separation a bit clearer (it also fixes a problem with your implementation making it quadratic: List is a link list, and list(index) is linear, don't do that):
def someFunc(
list: List[Int],
currentSum: Int = 0,
index: Int=0
): Option[Int] = list match {
case _ if currentSum == -1 => Some(index)
case Nil => None
case head :: tail => someFunc(tail, currentSum + head, index+1)
}

Is it possible to decompose Scala match statements using partial functions?

I have a match statement like this:
i match {
case x if x == 0 ⇒
romanNumeral
case x if x >= 1000 ⇒
this.roman(i - 1000, s"${romanNumeral}M")
case x if x >= 900 ⇒
this.roman(i - 900, s"${romanNumeral}CM")
// etc.
Depending on how this is formatted, it could be about 30 lines of redundant code.
So I'm wondering whether it is possible to make this code more dry.
So I created a partial function:
private def toRoman(upperGuard: Int, token: String, romanNumeral: String): String = {
case value: Int if value >= upperGuard ⇒
this.roman(upperGuard - 1, s"$romanNumeral$token")
}
which I then tried to include into the above matcher like:
i match {
case x if x == 0 ⇒
romanNumeral
toRoman(1000, "M", romanNumeral)
toRoman(900, "CM", romanNumeral)
// etc.
... But this won't work because Scala's compiler doesn't recognize these functions are the case statements it is looking for.
Is there any way to make this work?
You could create your cases as partial functions:
private def toRoman(upperGuard: Int, token: String, romanNumeral: String): PartialFunction[Int, String] = {
case value if value >= upperGuard =>
this.roman(upperGuard - 1, s"$romanNumeral$token")
}
val firstCase: PartialFunction[Int, String] = {
case x if x == 0 => romanNumeral
}
And then compose it like this:
val toRomanPartialFunction = firstCase
.orElse(toRoman(1000, "M", romanNumeral))
.orElse(toRoman(900, "CM", romanNumeral))
After that you could use it like regular function:
toRomanPartialFunction.apply(443)
toRomanPartialFunction(443)
So you basically want to make the code less repetitive, first things first:
Scala´s compiler doesn't recognise these functions as case statements because they are functions;
Second thing, that function is not actually a partial function;
Finally, those matches are ok to be like that, if you find a way of reducing lines of code by grouping in some kind of function like you did great but I don't find them redundant, unless you can redo it with a function like I said.
Ps: That function don't do the some thing as the case
You don't have a pattern matching expression, you are just writing an if else statement. If you want to return a function, you would write: x => this.something(x,"foo-bar") You have no need for case x. If you are only having one expression on the LHS case x you have no need for pattern matching, and can just use if else. Pattern matching without a class hierarchy doesn't make sense.

Combine multiple extractor objects to use in one match statement

Is it possible to run multiple extractors in one match statement?
object CoolStuff {
def unapply(thing: Thing): Option[SomeInfo] = ...
}
object NeatStuff {
def unapply(thing: Thing): Option[OtherInfo] = ...
}
// is there some syntax similar to this?
thing match {
case t # CoolStuff(someInfo) # NeatStuff(otherInfo) => process(someInfo, otherInfo)
case _ => // neither Cool nor Neat
}
The intent here being that there are two extractors, and I don't have to do something like this:
object CoolNeatStuff {
def unapply(thing: Thing): Option[(SomeInfo, OtherInfo)] = thing match {
case CoolStuff(someInfo) => thing match {
case NeatStuff(otherInfo) => Some(someInfo -> otherInfo)
case _ => None // Cool, but not Neat
case _ => None// neither Cool nor Neat
}
}
Can try
object ~ {
def unapply[T](that: T): Option[(T,T)] = Some(that -> that)
}
def too(t: Thing) = t match {
case CoolStuff(a) ~ NeatStuff(b) => ???
}
I've come up with a very similar solution, but I was a bit too slow, so I didn't post it as an answer. However, since #userunknown asks to explain how it works, I'll dump my similar code here anyway, and add a few comments. Maybe someone finds it a valuable addition to cchantep's minimalistic solution (it looks... calligraphic? for some reason, in a good sense).
So, here is my similar, aesthetically less pleasing proposal:
object && {
def unapply[A](a: A) = Some((a, a))
}
// added some definitions to make your question-code work
type Thing = String
type SomeInfo = String
type OtherInfo = String
object CoolStuff {
def unapply(thing: Thing): Option[SomeInfo] = Some(thing.toLowerCase)
}
object NeatStuff {
def unapply(thing: Thing): Option[OtherInfo] = Some(thing.toUpperCase)
}
def process(a: SomeInfo, b: OtherInfo) = s"[$a, $b]"
val res = "helloworld" match {
case CoolStuff(someInfo) && NeatStuff(otherInfo) =>
process(someInfo, otherInfo)
case _ =>
}
println(res)
This prints
[helloworld, HELLOWORLD]
The idea is that identifiers (in particular, && and ~ in cchantep's code) can be used as infix operators in patterns. Therefore, the match-case
case CoolStuff(someInfo) && NeatStuff(otherInfo) =>
will be desugared into
case &&(CoolStuff(someInfo), NeatStuff(otherInfo)) =>
and then the unapply method method of && will be invoked which simply duplicates its input.
In my code, the duplication is achieved by a straightforward Some((a, a)). In cchantep's code, it is done with fewer parentheses: Some(t -> t). The arrow -> comes from ArrowAssoc, which in turn is provided as an implicit conversion in Predef. This is just a quick way to create pairs, usually used in maps:
Map("hello" -> 42, "world" -> 58)
Another remark: notice that && can be used multiple times:
case Foo(a) && Bar(b) && Baz(c) => ...
So... I don't know whether it's an answer or an extended comment to cchantep's answer, but maybe someone finds it useful.
For those who might miss the details on how this magic actually works, just want to expand the answer by #cchantep anf #Andrey Tyukin (comment section does not allow me to do that).
Running scalac with -Xprint:parser option will give something along those lines (scalac 2.11.12)
def too(t: String) = t match {
case $tilde(CoolStuff((a # _)), NeatStuff((b # _))) => $qmark$qmark$qmark
}
This basically shows you the initial steps compiler does while parsing source into AST.
Important Note here is that the rules why compiler makes this transformation are described in Infix Operation Patterns and Extractor Patterns. In particular, this allows you to use any object as long as it has unapply method, like for example CoolStuff(a) AndAlso NeatStuff(b). In previous answers && and ~ were picked up as also possible but not the only available valid identifiers.
If running scalac with option -Xprint:patmat which is a special phase for translating pattern matching one can see something similar to this
def too(t: String): Nothing = {
case <synthetic> val x1: String = t;
case9(){
<synthetic> val o13: Option[(String, String)] = main.this.~.unapply[String](x1);
if (o13.isEmpty.unary_!)
{
<synthetic> val p3: String = o13.get._1;
<synthetic> val p4: String = o13.get._2;
{
<synthetic> val o12: Option[String] = main.this.CoolStuff.unapply(p3);
if (o12.isEmpty.unary_!)
{
<synthetic> val o11: Option[String] = main.this.NeatStuff.unapply(p4);
if (o11.isEmpty.unary_!)
matchEnd8(scala.this.Predef.???)
Here ~.unapply will be called on input parameter t which will produce Some((t,t)). The tuple values will be extracted into variables p3 and p4. Then, CoolStuff.unapply(p3) will be called and if the result is not None NeatStuff.unapply(p4) will be called and also checked if it is not empty. If both are not empty then according to Variable Patterns a and b will be bound to returned results inside corresponding Some.

Scala: how to write a tail-recursive function more idiomatically

I have the following:
case class Node(parent: Option[Node], etc:Any)
#tailrec
def getAncestor(numGens:Int, node:Node): Option[Node] =
if(numGens <= 0) Some(node)
else node.parent match {
case Some(parent) => getAncestor(numGens-1, parent)
case None => None
}
I don't like the case None => None. It gives me the impression that there should be a more elegant way. However, if I replace the else with:
else node.parent.flatMap(p => getAncestor(numGens-1, p))
then the function is no longer tail-recursive. Is there a more idiomatic way of writing this function?
I don't think there is a way. Your approach is already concise enough. Here are two other options:
// 1. changing argument type
#tailrec
def getAncestor(numGens:Int, node: Option[Node]): Option[Node] =
if(numGens <= 0) node else getAncestor(numGens -1, node.flatMap(_.parent))
// 2. removing if
#tailrec
def getAncestor(numGens:Int, node:Node): Option[Node] =
node.parent match {
case _ if numGens <= 0 => Some(node)
case Some(parent) => getAncestor(numGens-1, parent)
case _ => None
}
#tailrec
def getAncestor(numGens:Int, node:Node): Option[Node] = {
node.parent match {
case Some(parent) if numGens > 0 => getAncestor(numGens - 1, parent)
case Some(_) | None if numGens == 0 => Some(node)
case _ => None
}
}
This case class doesn't seem very useful. Since each node has only one parent, what you have done is recreate List[Any] without any of the useful methods.
If you put your etc objects into a List, then getAncestor(i, n) simply becomes
ns drop i
The result will either be a shorter list with the desired node at the top or an empty list. No memory will be wasted because Scala's immutable list is a persistent data structure. You can retrieve the contents of the new head node with
ns.drop(i).headOption
No stackoverflows, no ugliness caused by trying to make a recursive function tail recursive (useful explicitly recursive functions almost always end up ugly when made tail recursive). Much more idiomatic Scala because it is using the right type for the job.
If you are trying to build some more complex kind of structure with your nodes, then you would do better to build a proper Algebraic Data Type using case classes extending a sealed trait (or sealed abstract base class). Need more information about your intentions before expanding on that idea, though.

Scala: short form of pattern matching that returns Boolean

I found myself writing something like this quite often:
a match {
case `b` => // do stuff
case _ => // do nothing
}
Is there a shorter way to check if some value matches a pattern? I mean, in this case I could just write if (a == b) // do stuff, but what if the pattern is more complex? Like when matching against a list or any pattern of arbitrary complexity. I'd like to be able to write something like this:
if (a matches b) // do stuff
I'm relatively new to Scala, so please pardon, if I'm missing something big :)
This is exactly why I wrote these functions, which are apparently impressively obscure since nobody has mentioned them.
scala> import PartialFunction._
import PartialFunction._
scala> cond("abc") { case "def" => true }
res0: Boolean = false
scala> condOpt("abc") { case x if x.length == 3 => x + x }
res1: Option[java.lang.String] = Some(abcabc)
scala> condOpt("abc") { case x if x.length == 4 => x + x }
res2: Option[java.lang.String] = None
The match operator in Scala is most powerful when used in functional style. This means, rather than "doing something" in the case statements, you would return a useful value. Here is an example for an imperative style:
var value:Int = 23
val command:String = ... // we get this from somewhere
command match {
case "duplicate" => value = value * 2
case "negate" => value = -value
case "increment" => value = value + 1
// etc.
case _ => // do nothing
}
println("Result: " + value)
It is very understandable that the "do nothing" above hurts a little, because it seems superflous. However, this is due to the fact that the above is written in imperative style. While constructs like these may sometimes be necessary, in many cases you can refactor your code to functional style:
val value:Int = 23
val command:String = ... // we get this from somewhere
val result:Int = command match {
case "duplicate" => value * 2
case "negate" => -value
case "increment" => value + 1
// etc.
case _ => value
}
println("Result: " + result)
In this case, you use the whole match statement as a value that you can, for example, assign to a variable. And it is also much more obvious that the match statement must return a value in any case; if the last case would be missing, the compiler could not just make something up.
It is a question of taste, but some developers consider this style to be more transparent and easier to handle in more real-world examples. I would bet that the inventors of the Scala programming language had a more functional use in mind for match, and indeed the if statement makes more sense if you only need to decide whether or not a certain action needs to be taken. (On the other hand, you can also use if in the functional way, because it also has a return value...)
This might help:
class Matches(m: Any) {
def matches[R](f: PartialFunction[Any, R]) { if (f.isDefinedAt(m)) f(m) }
}
implicit def any2matches(m: Any) = new Matches(m)
scala> 'c' matches { case x: Int => println("Int") }
scala> 2 matches { case x: Int => println("Int") }
Int
Now, some explanation on the general nature of the problem.
Where may a match happen?
There are three places where pattern matching might happen: val, case and for. The rules for them are:
// throws an exception if it fails
val pattern = value
// filters for pattern, but pattern cannot be "identifier: Type",
// though that can be replaced by "id1 # (id2: Type)" for the same effect
for (pattern <- object providing map/flatMap/filter/withFilter/foreach) ...
// throws an exception if none of the cases match
value match { case ... => ... }
There is, however, another situation where case might appear, which is function and partial function literals. For example:
val f: Any => Unit = { case i: Int => println(i) }
val pf: PartialFunction[Any, Unit] = { case i: Int => println(i) }
Both functions and partial functions will throw an exception if called with an argument that doesn't match any of the case statements. However, partial functions also provide a method called isDefinedAt which can test whether a match can be made or not, as well as a method called lift, which will turn a PartialFunction[T, R] into a Function[T, Option[R]], which means non-matching values will result in None instead of throwing an exception.
What is a match?
A match is a combination of many different tests:
// assign anything to x
case x
// only accepts values of type X
case x: X
// only accepts values matches by pattern
case x # pattern
// only accepts a value equal to the value X (upper case here makes a difference)
case X
// only accepts a value equal to the value of x
case `x`
// only accept a tuple of the same arity
case (x, y, ..., z)
// only accepts if extractor(value) returns true of Some(Seq()) (some empty sequence)
case extractor()
// only accepts if extractor(value) returns Some something
case extractor(x)
// only accepts if extractor(value) returns Some Seq or Tuple of the same arity
case extractor(x, y, ..., z)
// only accepts if extractor(value) returns Some Tuple2 or Some Seq with arity 2
case x extractor y
// accepts if any of the patterns is accepted (patterns may not contain assignable identifiers)
case x | y | ... | z
Now, extractors are the methods unapply or unapplySeq, the first returning Boolean or Option[T], and the second returning Option[Seq[T]], where None means no match is made, and Some(result) will try to match result as described above.
So there are all kinds of syntactic alternatives here, which just aren't possible without the use of one of the three constructions where pattern matches may happen. You may able to emulate some of the features, like value equality and extractors, but not all of them.
Patterns can also be used in for expressions. Your code sample
a match {
case b => // do stuff
case _ => // do nothing
}
can then be expressed as
for(b <- Some(a)) //do stuff
The trick is to wrap a to make it a valid enumerator. E.g. List(a) would also work, but I think Some(a) is closest to your intended meaning.
The best I can come up with is this:
def matches[A](a:A)(f:PartialFunction[A, Unit]) = f.isDefinedAt(a)
if (matches(a){case ... =>}) {
//do stuff
}
This won't win you any style points though.
Kim's answer can be “improved” to better match your requirement:
class AnyWrapper[A](wrapped: A) {
def matches(f: PartialFunction[A, Unit]) = f.isDefinedAt(wrapped)
}
implicit def any2wrapper[A](wrapped: A) = new AnyWrapper(wrapped)
then:
val a = "a" :: Nil
if (a matches { case "a" :: Nil => }) {
println("match")
}
I wouldn't do it, however. The => }) { sequence is really ugly here, and the whole code looks much less clear than a normal match. Plus, you get the compile-time overhead of looking up the implicit conversion, and the run-time overhead of wrapping the match in a PartialFunction (not counting the conflicts you could get with other, already defined matches methods, like the one in String).
To look a little bit better (and be less verbose), you could add this def to AnyWrapper:
def ifMatch(f: PartialFunction[A, Unit]): Unit = if (f.isDefinedAt(wrapped)) f(wrapped)
and use it like this:
a ifMatch { case "a" :: Nil => println("match") }
which saves you your case _ => line, but requires double braces if you want a block instead of a single statement... Not so nice.
Note that this construct is not really in the spirit of functional programming, as it can only be used to execute something that has side effects. We can't easily use it to return a value (therefore the Unit return value), as the function is partial — we'd need a default value, or we could return an Option instance. But here again, we would probably unwrap it with a match, so we'd gain nothing.
Frankly, you're better off getting used to seeing and using those match frequently, and moving away from this kind of imperative-style constructs (following Madoc's nice explanation).