Use same variable multiple times within one pattern - scala

I'd like to be able to use a single variable multiple times within one pattern, so that it will only match if the same value is present in all places, such as
list match {
case x :: x :: xs => // recurse
}
which would match List(1,1,2) but would not match List(1,2,1). But this does not compile with error: x is already defined as value x.
In researching this question, I found out that I can also include a guard in the case clause, so I can do
list match {
case x1 :: x2 :: xs if x1==x2 => // recurse
}
which seems to work the same way (it does, right?). This is good, but it wouldn't look as clean if I wanted the same value in many places, like
list match {
case x1::x2::x3::x4::xs if x1==x2 && x2==x3 && x3==x4 => // recurse
}
Is there any more elegant way I can do this?
A few notes: Yes, I am just learning scala, if that wasn't clear, so I'm not sure this is something I'd ever really want to do, but I'm just interested in what's possible. In that regard, I'm not really looking for a completely different solution, like takeWhile or filter or something, but more so am specifically interested in pattern matching.

Scala doesn't provide quite that much flexibility with its matches (which may be a good thing, as one has to be aware of errors arising from unintentional variable re-use).
If you have a large number of identical items, you might want to consider a nested match (but note that you won't fail out of the inner match to be completed later down the outer match, so you have to handle everything locally):
list match {
case x :: rest => rest match {
case `x` :: `x` :: `x` :: xs => println("Four of the same")
case _ => println("Well, nonempty at least")
}
case _ => println("Boring, there's nothing here!")
}
Note the backticks which mean "we've already got this variable, check against it, don't set it!".
Alternatively, if you have specialized functionality that you use repeatedly, you can create a custom matcher:
object FourOf {
def unapplySeq(xs: List[Int]): Option[(Int, List[Int])] = xs match {
case x :: y :: z :: a :: rest if x==y && y==z && z==a => Some((x,rest))
case _ => None
}
}
and then use it whenever you need that complicated pattern:
list match {
case FourOf(x,rest) => println("four of the same")
case x :: more => println("Nonempty")
case _ => println("Yawn")
}
Neither of these are quite as tidy and flexible as what you were apparently hoping for, but then again, I'm not sure flipping between assigning and testing the same variable in a match statement is a good way to write clear code anyway.

For many repeats you might use stable identifiers to do a comparison (instead of catching a value):
val x = list.head
list match {
case `x`::`x`::`x`::`x`::xs => ....
}
But note that this won't work on empty list (you just cannot get head of it).

I think Rex's answer rocks. I am a fan of unapplySeq. But here's a not-so-clever-and-maybe-wasteful alternative, if your main bother is just with the sequence of =='s in each guard.
So in the TMTOWTDI spirit:
def same[A](xs: A*) = xs forall (xs.head==)
// Then in your pattern match,
list match {
// case x1::x2::x3::x4::xs if x1==x2 && x2==x3 && x3==x4 => // recurse
case x1::x2::x3::x4::xs if same(x1,x2,x3,x4) => // recurse
}
I like Om's answer as well, so here's an adaptation:
list.headOption map (x => list match {
case `x`::`x`::`x`::`x`::xs => //...;
case _ => // ...
}) getOrElse {
// do what you'd have done for an empty list...
}

Related

Scala - combine list of items into object

Say I have the following:
trait PropType
case class PropTypeA(String value) extends PropType
case class PropTypeB(String value) extends PropType
case class Item(
propTypeA: PropTypeA,
propTypeB: PropTypeB
)
and that I'm given a List[PropType]. How would I go with combining this into a List[Item]?
That is (and assuming we only have PropTypeA(name: String) and PropTypeB(name: String) to make this shorter / easier to follow hopefully) given this:
List[PropType](
PropTypeA("item1-propTypeA"),
PropTypeB("item1-propTypeB"),
PropTypeA("item2-propTypeA"),
PropTypeB("item2-propTypeB")
]
I'd like to get the equivalent of:
List[Item](
Item(PropTypeA("item1-propTypeA"), PropTypeB("item1-propTypeB")),
Item(PropTypeA("item2-propTypeA"), PropTypeB("item2-propTypeB"))
)
Kind of table building from linearized rows across columns, if that makes sense.
Note that in general there might be incomplete "rows", e.g. this:
List[PropType](
PropTypeA("item1-propTypeA"),
PropTypeB("item1-propTypeB"),
PropTypeB("itemPartialXXX-propTypeB"),
PropTypeA("itemPartialYYY-propTypeA"),
PropTypeA("item2-propTypeA"),
PropTypeB("item2-propTypeB")
]
should generate the same output as the above, with the logic being that PropTypeA always marks the start of a new row and thus everything "unused" is discarded.
How should I approach this?
Something like this will work with examples you mentioned.
list.grouped(2).collect { case Seq(a: PropTypeA, b: PropTypeB) => Item(a,b) }.toList
However it is unclear from your question what other cases you want to handle and how. For example, how exactly do you define the "partial" occurrence. Are there always two elements in reverse order? Can there be just one, or three? Can there be two As in a row? Or three? Or two Bs?
For example, A, A, A, A, B or B, B, A, A, B or just A?
Depending on how you answer those question, you'll need to somehow "pre-filter" the list before hand.
Here is an implementation based on the last phrase in your question: "PropTypeA always marks the start of a new row and thus everything "unused" is discarded." It only looks for instances where an A is immediately followed by B and discards everything else:
list.foldLeft(List.empty[PropType]) {
case ((a: PropTypeA) :: tail, b: PropTypeB) => b :: a :: tail
case ((b: PropTypeB) :: tail, a: PropTypeA) => a :: b :: tail
case (Nil, a: PropTypeA) => a :: Nil
case (_ :: tail, a: PropTypeA) => a :: tail
case (list, _) => list
}.reverse.grouped(2).collect {
case Seq(a: PropTypeA, b: PropTypeB) => Item(a,b)
}.toList
If you have more than just two types, then there are even more questions: what happens if stuff after A comes in wrong order for example? Like what do you do with A,B,C,A,C,B?
But basically, it would be the same idea as above: if next element is of the type you expect in the the sequence, add it to the result, otherwise discard sequence and keep going.
we can use the tail recursion function to generate the list of a new type.
def transformType(proptypes: List[PropType]): List[Item] =
{
// tail recursion function defined
#tailrec
def transform(proptypes: List[PropType], items: List[Item]): List[Item]=
{
proptypes match {
case (first:PropTypeA) :: (second:PropTypeB) :: tail=> transform(tail, items :+ Item(first, second))
case (first:PropTypeA) :: (second:PropTypeA) :: tail => transform(second :: tail, items :+ Item(first, PropTypeB("")))
case (first:PropTypeB) :: tail => transform(tail, items :+ Item(PropTypeA(""), first))
case (first:PropTypeA) :: tail => transform(tail, items :+ Item(first, PropTypeB("")))
case _ => items
}
}
transform(proptypes, List.empty[Item])
}
you can find the working link here

What should max() return for empty lists?

Got java.util.NoSuchElementException: head of empty list so I tried to check for that. But now I get [info] - max of a few numbers *** FAILED ***
[info] 0 did not equal 7 (ListsSuite.scala:128)
def max(xs: List[Int]): Int = {
if xs.isEmpty 0 // What can I do?
else if (xs.head > max(xs.tail)) max(xs.tail)
else max(xs.tail)
}
edit:
The test case failed because my test was wrong.
For my classmates, a reminder of the Coursera honor code:
I will register for only one account. My answers to homework, quizzes
and exams will be my own work (except for assignments that explicitly
permit collaboration).
I will not make solutions to homework, quizzes
or exams available to anyone else. This includes both solutions
written by me, as well as any official solutions provided by the
course staff.
I will not engage in any other activities that will
dishonestly improve my results or dishonestly improve/hurt the
results of others.
In the general case, you can't return anything but None because an empty sequence in general has no meaningful default max value. That, however, is not necessarily the case all the time; for example you might want to find the maximum salary in a list of people, in which case it would make sense to say it's 0 if the list is empty; however, there is no trivial way to implement such default value logic generically (you'd have to use stuff like type classes and wrapped values); your best bet now is to simply use Option[Int]:
def max(xs: List[Int]): Option[Int] = xs match {
case Nil => None
case x :: Nil => Some(x)
case x :: xs => Some(x max max(xs))
}
Then, you can easily fall back to a default value at the call site:
val posOrNeg = List(-5, -2, 1, 4, 10)
max(posOrNeg) // => Some(10)
val posOrNeg = List.empty[Int]
max(posOrNeg) // => None
val onlyPos = List(1, 2, 3)
max(onlyPos).getOrElse(0) // => 3
val onlyPos = List.empty[Int]
max(onlyPos).getOrElse(0) // => 0
Bonus: Also, you can make your max work on any list of numeric values:
def max[T: Numeric](xs: List[T]): Option[T] = xs match {
case Nil => None
case x :: Nil => Some(x)
case x :: xs => Some(x max max(xs))
}
or in fact any suitable data structure made up of numeric values by using a type more general than List, but I'll leave that up to you.
But keep in mind: no matter which solution you opt for, always try to avoid try and exceptions in general — exceptions are not in the spirit of idiomatic functional programming (even though even some library functions use them occasionally for various reasons).
I'd go with Option.
def max(xs: List[Int]) =
if xs.isEmpty None
else if (xs.head > max(xs.tail)) Some( max(xs.tail) )
else Some( max(xs.tail))
The Option-Monad can either be Some( result ), meaning there is a result or None, meaning there is no result. If you wrap something in Some you say it's is a result and everything is fine.
As an alternative you solution you could wrap everything in a Try which would be the best because an empty list has no max and it's the right thing to get an error for that but now you can handle it in a functional way.
def max(xs: List[Int]) = Try( if (xs.head > max(xs.tail)) max(xs.tail) else xs.tail )
It doesn't make sense to define a max element for an empty collection, so you should either return a sentinel value, or throw an exception (e.g. IllegalArgumentException).
Also, you should make a few changes to your code (if you want to implement it yourself, and not use the built-in stuff):
def max(list: List[Int]): Option[Int] = {
list match {
// List has no elements, so we return None
case Nil => None
// Only one element, that is the maximum
case x :: Nil => Some(x)
// Compute max(list.tail).
// If defined, it will return the greater of list.tail and list.head
case head :: tail => max(tail).map(_ max head)
}
}

Idiomatic "do until" collection updating

Scenario:
val col: IndexedSeq[Array[Char]] = for (i <- 1 to n) yield {
val x = for (j <- 1 to m) yield 'x'
x.toArray
}
This is a fairly simple char matrix. toArray used to allow updating.
var west = last.x - 1
while (west >= 0 && arr(last.y)(west) == '.') {
arr(last.y)(west) = ch;
west -= 1;
}
This is updating all . to ch until a non-dot char is found.
Generically, update until stop condition is met, unknown number of steps.
What is the idiomatic equivalent of it?
Conclusion
It's doable, but the trade-off isn't worth it, a lot of performance is lost to expressive syntax when the collection allows updating.
Your wish for a "cleaner, more idiomatic" solution is of course a little fuzzy, because it leaves a lot of room for subjectivity. In general, I'd consider a tail-recursive updating routine more idiomatic, but it might not be "cleaner" if you're more familiar with a non-functional programming style. I came up with this:
#tailrec
def update(arr:List[Char], replace:Char, replacement:Char, result:List[Char] = Nil):List[Char] = arr match {
case `replace` :: tail =>
update(tail, replace, replacement, replacement :: result)
case _ => result.reverse ::: arr
}
This takes one of the inner sequences (assuming a List for easier pattern matching, since Arrays are trivially convertible to lists), and replaces the replace char with the replacement recursively.
You can then use map to update the outer sequence, like so:
col.map { x => update(x, '.', ch) }
Another more reusable alternative is writing your own mapUntil, or using one which is implemented in a supplemental library (Scalaz probably has something like it). The one I came up with looks like this:
def mapUntil[T](input:List[T])(f:(T => Option[T])) = {
#tailrec
def inner(xs:List[T], result:List[T]):List[T] = xs match {
case Nil => Nil
case head :: tail => f(head) match {
case None => (head :: result).reverse ::: tail
case Some(x) => inner(tail, x :: result)
}
}
inner(input, Nil)
}
It does the same as a regular map invocation, except that it stops as soon as the passed function returns None, e.g.
mapUntil(List(1,2,3,4)) {
case x if x >= 3 => None
case x => Some(x-1)
}
Will result in
List[Int] = List(0, 1, 3, 4)
If you want to look at Scalaz, this answer might be a good place to start.
x3ro's answer is the right answer, esp. if you care about performance or are going to be using this operation in multiple places. I would like to add simple solution using only what you find in the collections API:
col.map { a =>
val (l, r) = a.span(_ == '.')
l.map {
case '.' => ch
case x => x
} ++ r
}

Processing Scala Option[T]

I have a Scala Option[T]. If the value is Some(x) I want to process it with a a process that does not return a value (Unit), but if it is None, I want to print an error.
I can use the following code to do this, but I understand that the more idiomatic way is to treat the Option[T] as a sequence and use map, foreach, etc. How do I do this?
opt match {
case Some(x) => // process x with no return value, e.g. write x to a file
case None => // print error message
}
I think explicit pattern matching suits your use case best.
Scala's Option is, sadly, missing a method to do exactly this. I add one:
class OptionWrapper[A](o: Option[A]) {
def fold[Z](default: => Z)(action: A => Z) = o.map(action).getOrElse(default)
}
implicit def option_has_utility[A](o: Option[A]) = new OptionWrapper(o)
which has the slightly nicer (in my view) usage
op.fold{ println("Empty!") }{ x => doStuffWith(x) }
You can see from how it's defined that map/getOrElse can be used instead of pattern matching.
Alternatively, Either already has a fold method. So you can
op.toRight(()).fold{ _ => println("Empty!") }{ x => doStuffWith(x) }
but this is a little clumsy given that you have to provide the left value (here (), i.e. Unit) and then define a function on that, rather than just stating what you want to happen on None.
The pattern match isn't bad either, especially for longer blocks of code. For short ones, the overhead of the match starts getting in the way of the point. For example:
op.fold{ printError }{ saveUserInput }
has a lot less syntactic overhead than
op match {
case Some(x) => saveUserInput(x)
case None => printError
}
and therefore, once you expect it, is a lot easier to comprehend.
I'd recommend to simply and safely use opt.get which itself throws a NoSuchElementException exception if opt is None. Or if you want to throw your own exception, you can do this:
val x = opt.getOrElse(throw new Exception("Your error message"))
// x is of type T
as #missingfaktor says, you are in the exact scenario where pattern matching is giving the most readable results.
If Option has a value you want to do something, if not you want to do something else.
While there are various ways to use map and other functional constructs on Option types, they are generally useful when:
you want to use the Some case and ignore the None case e.g. in your case
opt.map(writeToFile(_)) //(...if None just do nothing)
or you want to chain the operations on more than one option and give a result only when all of them are Some. For instance, one way of doing this is:
val concatThreeOptions =
for {
n1 <- opt1
n2 <- opt2
n3 <- opt3
} yield n1 + n2 + n3 // this will be None if any of the three is None
// we will either write them all to a file or none of them
but none of these seem to be your case
Pattern matching is the best choice here.
However, if you want to treat Option as a sequence and to map over it, you can do it, because Unit is a value:
opt map { v =>
println(v) // process v (result type is Unit)
} getOrElse {
println("error")
}
By the way, printing an error is some kind of "anti-pattern", so it's better to throw an exception anyway:
opt.getOrElse(throw new SomeException)

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).