Using unapply as constructor in match - scala

Is it good style in Scala to "abuse" the unapply method for pattern matching? What I wanted to do, is matching an object against another, and constructing the other object. Since I am fairly new in Scala, I wound up with the following solution. But it doesnt seem really right to use the unapply methode like this, since it is intended as an extractor. Could someone please give me feedback on this?
object Poker {
def unapply(hand: Hand): Option[Poker] = if(hand.countValueGroups().exists(_._2 == 4)) Some(new Poker(hand)) else None
}
val h = Hand("AC As AH Ad 2h")
h match {
case Poker(han) => println("POKER!!!"+han)
case _ => println("?????")
}

I don't know why this should be bad practice, so I'd say the answer is no, this is normal practice. As one commenter said, the mere purpose of unapply is to be used in pattern matching. While pattern matching is mostly used with the companion object of a case class, the concept is deliberately open to other extractors (example: regular expressions).
The only thing that's weird in your example is to return Option[Poker] with Poker begin a singleton object. Since you can't do much with that, probably you want to use a Boolean instead:
object Poker {
def unapply(hand: Hand): Boolean =
hand.countValueGroups().exists(_._2 == 4)
}
case class Hand(s: String) {
def countValueGroups(): List[(Any, Int)] = List("foo" -> 4) // ???
}
val h = Hand("AC As AH Ad 2h")
h match {
case Poker() => println("POKER!!!")
case _ => println("?????")
}

Related

why scala Map does not implement unapply?

I wrote the following use case in scala:
val wordShortcut = Map("volume" -> "vol", "report" -> "rpt", ...)
object WordShortcutCase {
def unapply(key: String): Option[String] = wordShortcut.get(key)
}
val pluralR = "(.+)s".r
def encodeToken(token: String) = token match {
case WordShortcutCase(short) => short
case pluralR(singular) => singular
case _ => token
}
if scala Map would implement unapply, I wouldn't need the extra WordShortcutCase object (i could use case wordShortcut(short) => short instead`). This seems a common pattern to me.
And so the question is why scala Map does not implement the unapply method?
Map doesn't implement unapply because there is no sensible implementation that has the same characteristics as other collections.
In particular, you seem to want apply and unapply to do basically the same thing. But that's not how other collections work; they bind variables to contents and expect that the list is exhaustive (in the absence of a binding to "the rest"):
val xs = List("fish")
val ys = List("fish", "dish")
def iam(zs: List[String]) = zs match {
case List(x) => println(s"I am a $x")
case _ => println("Who am I??")
}
iam(xs) // Prints 'I am a fish'
iam(ys) // Prints 'Who am I??'
If Map were not a collection it would be free to implement unapply as another way to do an apply, more like regex does (though there, note that the key feature is being able to bind multiple variables to parts of the regex match). But since it is, having a regex-like unapply would be highly confusing because of the difference from other collections; and because maps are unordered and unapplySeq is ordered, having the same unapply as other collections would also be confusing. So it just doesn't have one.

Why does Scalaz \/ type have getOrElse but not get?

As far as I can tell Scalaz's \/ does not have get method. Sometimes I am sure the value contained in \/ is the right value, and I don't want to use getOrElse. I want to get it directly.
("3".right[Int]) getOrElse("123123123") // 3
if (t.isRight) t.get // compilation error, no get method
How can I get the right value directly, if it is guaranteed.
There are two ways I can get the value, but both look a little bit verbose.
1: change to scala Either
val t = "3".right[Int]
val either = t.toEither
if (either.isRight) either.right.get
else either.left.get
2: Use getOrElse
("3".right[Int]) getOrElse("123123123") // but for some cases I don't have this default value
There is no get as get could throw an exception, which isn't cool. Scalaz enforces this by not allowing direct access to the value.
If you provide more information, we can help out with a solution.
t should be safe.
val safe_thing:T = ???
val either: Throwable \/ T = getFromSomewhere
either getOrElse safe_thing
As other answer pointed out, get could throw. But similarly to OP, I also encountered cases when I was sure of a type (in this case \/-), yet the variable in code was of type \/ (super class).
Doing inline pattern matching was very verbose and looked bad.
println(("test".right[String] |> { case \/-(x) => x; case _ => "" }).toUpperCase)
So I wrote this helper:
implicit class ScalazDisjunctionPimps[A, B](e: \/[A, B]) {
def getRight: B = e match {
case \/-(x) => x
case _ => throw new RuntimeException(s"$e is not right.")
}
}
Usage is simple, here's example:
println("test".right.getRight.toUpperCase) // outputs: TEST
If needed getLeft can be constructed in the same way.

Does scala have a "test-if-match" operator? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Scala: short form of pattern matching that returns Boolean
In my scala code I'm finding myself often writing things like the following:
x match{
case Type(params) => doStuffWith(params)
case _ => /* do nothing*/
}
Is there already some predefined operator to do this? I think it would be much clearer if I could write things like:
if( x match Type(params)) {
doStuffWith(params)
}
essentially avoiding the weird otherwise case. I've also had other situations where being able to verify if something matches a pattern in an inline fashion would save me an extra pair of braces.
I know this sort of thing might only be more useful when writing more iterative code, but Scala seems to have so many hidden features I was wondering whether someone has a simple solution for this.
You could lifta partial function from Any to A into a function from Any to Option[A].
To make the syntax nice first define an helper function:
def lifted[A]( pf: PartialFunction[Any,A] ) = pf.lift
Then, make profit:
val f = lifted {
case Type(i) => doStuff(i)
}
scala> f(2)
res15: Option[Int] = None
scala> f(Type(4))
res16: Option[Int] = Some(8)
The doStuff method will be called only if the argument matches. And you can have several case clauses.
The shortest way I can think of is to wrap the value in an option and use the collect method:
Option(x).collect { case Type(params) => doStuffWith(params) }
Using the link that #phant0m gave, to spell it out:
import PartialFunction.condOpt
condOpt(x){ case Type(params) => doStuffWith(params) }
If this pattern appears often in your code, you should consider turning doSomeStuff into a method of Type. Case classes in Scala are normal classes, and you should use the object-oriented features when they make sense.
Otherwise, you could add a method at the top of your hierarchy, assuming all your case classes extend a common trait. For example:
class Base {
def whenType(f: (T1, T2) => Unit): Unit = this match {
case Type(t1, t2) => f(t1, t2)
case _ => ()
}
}
and then you can use x whenType doSomeStuff

Could Scala's “if … else” have been implemented as a library function?

I'm wondering if if … else could have been implemented in Predef with special compiler treatment, in a similar way to what's being done with classOf[A]: the definition is in Predef, the implementation is filled in by the compiler.
Granted, many people would find reassuring to know that an if is always an if, and an else is always an else, no matter the context. However, defining else as a method on the result type of if would remove it from the list of keywords, and allow library designers to define their own else methods. (I know I can use any keyword as an identifier with backticks, but something like `else` just looks awful in code.) Such methods could be useful in cases discusses in situations such as this one, discussed on the mailing list, where people are forced to use otherwise when defining methods that actually should be named else. (Also discussed on SO here and here.)
So:
Would such an approach be possible, even in theory, or does it break some fundamental principle in Scala?
What would the downsides be?
Maybe I don't understand your question, but you can already implement if ... else ... as a library function. Consider this:
class If[A](condition: =>Boolean)(ifBlock: =>A) {
def els(elseBlock: =>A):A = condition match {
case true => ifBlock
case false => elseBlock
}
}
new If(2==3)(
println("equal")
) els (
println("not equal")
)
Of course this doesn't do exactly what if ... else ... does, but with some polishing I think it would. I once implemented a very simple interpreter for a language that had pattern matching built in with if ... else ... being implemented in much the same way I did here.
The short answer is "yes"; branching logic on some predicate can be implemented as a library function.
It's worth pointing out that, as Viktor Klang and others have noted, if/else is essentially folding a boolean. Folding is something we do frequently - sometimes it's clear and explicit, and sometimes not.
// Either#fold is explicit
scala> Left[String, Double]("fail") fold(identity, _ + 1 toString)
res0: java.lang.String = fail
scala> Right[String, Double](4) fold(identity, _ + 1 toString)
res1: java.lang.String = 5.0
Folding an option cannot be done explicitly, but we do it all the time.
// Option has no fold - wont compile!
Some(5) fold(1+, 0)
// .. but the following is equivalent and valid
scala> Some(5) map(1+) getOrElse(0)
res3: Int = 6
Branching logic on a boolean is also a fold, and you can pimp Boolean accordingly. Note the use of by-name parameters to achieve lazy evaluation. Without this feature, such an implementation wouldn't be possible.
// pimped Boolean - evaluates t when true, f when false
class FoldableBoolean(b: Boolean) {
def fold[A](t: => A, f: => A) =
if(b) t else f
}
implicit def b2fb(b: Boolean) = new FoldableBoolean(b)
Now we can fold Booleans:
scala> true fold("true!", "false")
res24: java.lang.String = true!
scala> false fold("true!", "false")
res25: java.lang.String = false
Not just if-else, but any language feature can be overridden in a branch of the language known as "Scala Virtualized"
https://github.com/TiarkRompf/scala-virtualized
This forms the basis of the Delite project at Stanford PPL, and is also at the heart of the research being funded by Scala's EU grant. So you can reasonably expect it to be part of the core language at some point in the future.
Any object-oriented language (or any language with runtime polymorphism) can implement conditionals as a library feature, since method dispatch already is a more general form of conditional anyway. Smalltalk, for example, has absolutely no conditionals whatsoever except for method dispatch.
There is no need for any kind of compiler magic, except maybe for syntactic convenience.
In Scala, it would look maybe a little bit like this:
trait MyBooleanLike {
def iff[T <: AnyRef](thenn: => T): T
def iffElse[T](thenn: => T)(els: => T): T
def &&(other: => MyBoolean): MyBoolean
def ||(other: => MyBoolean): MyBoolean
def nott: MyBoolean
}
trait MyTruthiness extends MyBooleanLike {
def iff[T](thenn: => T) = thenn
def iffElse[T](thenn: => T)(els: => T) = thenn
def &&(other: => MyBoolean) = other
def ||(other: => MyBoolean) = MyTrue
def nott = MyFalse
}
trait MyFalsiness extends MyBooleanLike {
def iff[T](thenn: => T): T = null.asInstanceOf[T]
def iffElse[T](thenn: => T)(els: => T) = els
def &&(other: => MyBoolean) = MyFalse
def ||(other: => MyBoolean) = other
def nott = MyTrue
}
abstract class MyBoolean extends MyBooleanLike
class MyTrueClass extends MyBoolean with MyTruthiness {}
class MyFalseClass extends MyBoolean with MyFalsiness {}
object MyTrue extends MyTrueClass {}
object MyFalse extends MyFalseClass {}
Just add a little implicit conversion:
object MyBoolExtension {
implicit def boolean2MyBoolean(b: => Boolean) =
if (b) { MyTrue } else { MyFalse }
}
import MyBoolExtension._
And now we can use it:
object Main extends App {
(2 < 3) iff { println("2 is less than 3") }
}
[Note: my type-fu is rather weak. I had to cheat a little bit to get this to compile within a reasonable timeframe. Someone with a better understanding of Scala's type system may want to fix it up. Also, now that I look at it, 8 classes, traits and objects, two of them abstract, seems a little over-engineered ;-) ]
Of course, the same is true for pattern matching as well. Any language with pattern matching doesn't need other kinds of conditionals, since pattern matching is more general anyway.
[BTW: This is basically a port of this Ruby code I wrote a couple of years ago for fun.]

Pattern matching with conjunctions (PatternA AND PatternB)

Scala has a language feature to support disjunctions in pattern matching ('Pattern Alternatives'):
x match {
case _: String | _: Int =>
case _ =>
}
However, I often need to trigger an action if the scrutiny satisfies PatternA and PatternB (conjunction.)
I created a pattern combinator '&&' that adds this capability. Three little lines that remind me why I love Scala!
// Splitter to apply two pattern matches on the same scrutiny.
object && {
def unapply[A](a: A) = Some((a, a))
}
// Extractor object matching first character.
object StartsWith {
def unapply(s: String) = s.headOption
}
// Extractor object matching last character.
object EndsWith {
def unapply(s: String) = s.reverse.headOption
}
// Extractor object matching length.
object Length {
def unapply(s: String) = Some(s.length)
}
"foo" match {
case StartsWith('f') && EndsWith('f') => "f.*f"
case StartsWith('f') && EndsWith(e) && Length(3) if "aeiou".contains(e) => "f..[aeiou]"
case _ => "_"
}
Points for discussion
Is there an existing way to do this?
Are there problems with this approach?
Can this approach create any other useful combinators? (for example, Not)
Should such a combinator be added to the standard library?
UPDATE
I've just been asked how the compiler interprets case A && B && C. These are infix operator patterns (Section 8.1.9 of the Scala Reference). You could also express this with standard extract patterns (8.1.7) as &&(&&(A, B), C).' Notice how the expressions are associated left to right, as per normal infix operator method calls likeBoolean#&&inval b = true && false && true`.
I really like this trick. I do not know of any existing way to do this, and I don't foresee any problem with it -- which doesn't mean much, though. I can't think of any way to create a Not.
As for adding it to the standard library... perhaps. But I think it's a bit hard. On the other hand, how about talking Scalaz people into including it? It looks much more like their own bailiwick.
A possible problem with this is the bloated translation that the pattern matcher generates.
Here is the translation of the sample program, generated with scalac -print. Even -optimise fails to simplify the if (true) "_" else throw new MatchError() expressions.
Large pattern matches already generate more bytecode than is legal for a single method, and use of this combinator may amplify that problem.
If && was built into the language, perhaps the translation could be smarter. Alternatively, small improvements to -optimise could help.