Pattern match empty ArrayBuffer - scala

Is there any special case class for representing an empty ArrayBuffer that can be used in pattern matching similar to Nil for lists?
Also why this works:
scala> collection.mutable.ArrayBuffer.empty == Nil
res11: Boolean = true
While this does not:
scala> collection.mutable.ArrayBuffer() match { case Nil => 1 }
<console>:8: error: pattern type is incompatible with expected type;
found : scala.collection.immutable.Nil.type
required: scala.collection.mutable.ArrayBuffer[Nothing]
UPDATE
After giving it some thought I presume there is no such a case class. While existence of Nil is vital for List to work, no special structure of this kind is needed for arrays.
I've found a workaround for empty match check that might work in most cases:
collection.mutable.ArrayBuffer(2) match {
case collection.mutable.ArrayBuffer(v, _*) => v * 2
case _ => 0
}
I first check if array has at least one element and otherwise it should be empty.
Also as it turns out I could just use ArrayBuffer.isEmpty instead of pattern match.

Jasper-M provided a good answer to your second question (why == works but pattern matching fails).
As to your first, there is no equivalent to Nil for ArrayBuffer. The reason is that List is defined using scala's notion of Algebraic Data Types (ADT), while ArrayBuffer is not.
Take a look at the source for ArrayBuffer. It's implemented as a regular class, whereas List is implemented as an abstract class with two subclasses: a case object Nil, and a case class ::.
These case classes are what allow you to pattern match on List. Since there's no equivalent for ArrayBuffer, you cannot pattern match.

scala> collection.mutable.ArrayBuffer.empty == Nil
res11: Boolean = true
The reason this is true can be found by looking at the documentation of the equals method:
true if that is a sequence that has the same elements as this sequence
in the same order, false otherwise
For instance:
scala> val buffer = collection.mutable.ArrayBuffer.empty[Int]
buffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
scala> buffer.append(4)
scala> buffer == List(4)
res1: Boolean = true
So that has nothing to do with pattern matching.

After giving it some thought I presume there is no such a case class. While existence of Nil is vital for List to work, no special structure of this kind is needed for arrays.
I've found a workaround for empty match check that might work in most cases:
collection.mutable.ArrayBuffer(2) match {
case collection.mutable.ArrayBuffer(v, _*) => v * 2
case _ => 0
}
I first check if array has at least one element and otherwise it should be empty.

Related

Is this pattern match redundant?

I recently fell over a scala pattern match, that looked more or less like this:
def func (li :List[Int]): List[Int] = li match {
case Nil => Nil
case start :+ tail => start
case List() => li
}
Now, what these three different cases return is not so much what I am in interesed about.
I wondering whether a pattern match like this would ever have any effect? Is there any case at all, where third case could ever reached?
My initial thought is no, since all lists with more than 0 elements will always match on the first case, and therefore the second case could never be reached
You can read the post: Scala: Nil vs List(). From the point of view of pattern matching, they are the same. The third case will never hit.
In Scala source code you can find that case object Nil extends List[Nothing], and that empty list is Nil.
The third case is redundant, because as far as I know, an empty list can only ever be Nil. List is sealed, so there won't be classes other than :: and the object Nil extending it.
However, a list with more than 0 elements will always match on the second case. A list with no elements would match the first case (and the third case, if the first were not present).

When is case syntactically significant?

A/a case, not case case.
Apparently case a matches anything and binds it to the name a, while case A looks for an A variable and matches anything == considers equal to A. This came as quite a surprise to me; while I know Scala is case sensitive, I never expected identifier case to affect the parsing rules.
Is it common for Scala's syntax to care about the case of identifiers, or is there only a small number of contexts in which this happens? If there's only a small number of such contexts, what are they? I couldn't find anything on Google; all I got were results about pattern matching.
There is one more that is similar in nature, called a type pattern. In a type pattern, a simple identifier that starts with a lower case letter is a type variable, and all others are attempt to match actual types (except _).
For example:
val a: Any = List(1, 2, 3)
val c = 1
// z is a type variable
a match { case b: List[z] => a }
// Type match on `Int`
a match { case b: List[Int] => a }
// type match on the singleton c.type (not a simple lower case identifier)
// (doesn't actually compile because c.type will never conform)
a match { case b: List[c.type] => a }
Type matching like the the first example is lesser-known because, well, it's hardly used.

Scala Syntactic Sugar for converting to `Option`

When working in Scala, I often want to parse a field of type [A] and convert it to a Option[A], with a single case (for example, "NA" or "") being converted to None, and the other cases being wrapped in some.
Right now, I'm using the following matching syntax.
match {
case "" => None
case s: String => Some(s)
}
// converts an empty String to None, and otherwise wraps it in a Some.
Is there any more concise / idiomatic way to write this?
There are a more concise ways. One of:
Option(x).filter(_ != "")
Option(x).filterNot(_ == "")
will do the trick, though it's a bit less efficient since it creates an Option and then may throw it away.
If you do this a lot, you probably want to create an extension method (or just a method, if you don't mind having the method name first):
implicit class ToOptionWithDefault[A](private val underlying: A) extends AnyVal {
def optNot(not: A) = if (underlying == not) None else Some(underlying)
}
Now you can
scala> 47.toString optNot ""
res1: Option[String] = Some(47)
(And, of course, you can always create a method whose body is your match solution, or an equivalent one with if, so you can reuse it for that particular case.)
I'd probably use filterNot here:
scala> Option("hey").filterNot(_ == "NA")
res0: Option[String] = Some(hey)
scala> Option("NA").filterNot(_ == "NA")
res1: Option[String] = None
It requires you to think of Option as a collection with one or zero elements, but if you get into that habit it's reasonably clear.
A simple and intuitive approach includes this expression,
if (s.isEmpty) None else Some(s)
This assumes s labels the value to be otherwise matched (thanks to #RexKerr for the note).

scala Nil type matchs against arraybuffer

I found a strange working construct in scala:
(ArrayBuffer[Int]():Seq[Int]) match {
case Nil => "whoo"
case _ => "nayyy"
}
which returns
"whoo"
Apparently this already works partially for Vectors, but not pattern matching. can someone explain me that? Nil does not have any method named unapply. How is this possible?
With objects, unapply is not involved (that would be the case if you had used the hypothetical case Nil() => ...). Instead, the equality is checked using the equals method.
Equality for collections is defined in terms of their elements. E.g.
List(1,2,3) == Vector(1,2,3) // true!
The same happens with Nil which equals any empty sequence:
Vector() == Nil // true
collection.mutable.ArrayBuffer() == Nil // true

Why Some(null) isn't considered None?

I am curious:
scala> Some(null) == None
res10: Boolean = false
Why isn't Some(null) transformed to None?
You should use Option(null) to reach the desired effect and return None.
Some(null) just creates a new Option with a defined value (hence Some) which is actually null, and there are few valid reasons to ever create one like this in real code.
Unfortunately, null is a valid value for any AnyRef type -- a consequence of Scala's interoperability with Java. So a method that takes an object of type A and, internally, store it inside an Option, might well need to store a null inside that option.
For example, let's say you have a method that takes the head of a list, checks if that head correspond to a key in a store, and then return true if it is. One might implement it like this:
def isFirstAcceptable(list: List[String], keys: Set[String]): Boolean =
list.headOption map keys getOrElse false
So, here's the thing... if the that inside list and keys come from some Java API, they both may well contain null! If Some(null) wasn't possible, then isFirstAcceptable(List[String](null), Set[String](null)) would return false instead of true.
I think the others in the thread do a good job explaining why Some(null) "should" exist, but if you happen to be getting Some(null) somewhere and want a quick way to turn it into None, I've done this before:
scala> val x: Option[String] = Some(null)
x: Option[String] = Some(null)
scala> x.flatMap(Option(_))
res8: Option[String] = None
And when the starting Option is a legit non-null value things work as you probably want:
scala> val y: Option[String] = Some("asdf")
y: Option[String] = Some(asdf)
scala> y.flatMap(Option(_))
res9: Option[String] = Some(asdf)
Much of Scala's WTFs can be attributed to its need for compatibility with Java. null is often used in Java as a value, indicating, perhaps the absence of a value. For example hashMap.get(key) will return null if the key is not matched.
With this in mind, consider the following possible values from wrapping a null returning method in an Option:
if (b) Some(hashMap.get(key)) else None
// becomes -->
None // the method was not invoked;
Some(value) // the method was invoked and a value returned; or
Some(null) // the method was invoked and null was returned.
Some(null) seems sufficiently distinct from None in this case to warrant allowing it in the language.
Of course if this is not desirable in your case then simply use:
if (b) Option(hashMap.get(key)) else None
// becomes -->
None // the method was not invoked or the mapped value was null; or
Some(value) // the method was invoked and a value returned
As a simple thought experiment, consider two lists of Strings, one of length 5 and one of length 20.
Because we're running on the JVM, it's possible to insert null as a valid element into one of these lists - so put that in the long list as element #10
What, then, should the difference be in the values returned from the two following expressions?
EDIT: Exchanged get for lift, I was thinking of maps...
shortList.lift(10) //this element doesn't exist
longList.lift(10) //this element exists, and contains null
Because Option is considered to be a Functor and being a Functor means:
Has unit function (apply or just Option("blah") in Scala)
Has map function which transforms value from T=>B but not a context
Obeys 2 Functor laws - identity law and associative law
In this topic the main part is #2 - Option(1).map(t=>null) can not transform context. Some should remain. Otherwise it brakes associative law!
Just consider the following laws example:
def identity[T](v: T) = v
def f1(v: String) = v.toUpperCase
def f2(v: String) = v + v
def fNull(v: String): String = null
val opt = Option("hello")
//identity law
opt.map(identity) == opt //Some(hello) == Some(hello)
//associative law
opt.map(f1 _ andThen f2) == opt.map(f1).map(f2) //Some(HELLOHELLO) == Some(HELLOHELLO)
opt.map(fNull _ andThen f2) == opt.map(fNull).map(f2) //Some(nullnull) == Some(nullnull)
But what if Option("hello").map(t=>null) produced None? Associative law would be broken:
opt.map(fNull _ andThen f2) == opt.map(fNull).map(f2) //Some(nullnull) != None
That is my thought, might be wrong