I have Scala code with some boilerplate, and I figure it's Scala, so I must be doing something wrong. I need some help figuring out how to remove the redundancies.
trait Number {
val x: Int
}
case class EvenNumber(x: Int) extends Number
object EvenNumber {
def unapply(s: String): Option[EvenNumber] = {
val x = s.toInt
if (x % 2 == 0) Some(EvenNumber(x))
else None
}
}
case class OddNumber(x: Int) extends Number
object OddNumber {
def unapply(s: String): Option[OddNumber] = {
val x = s.toInt
if (x % 2 == 1) Some(OddNumber(x))
else None
}
}
In this simple example there are even numbers and odd numbers which are subtypes of a general number type. Both even and odd numbers have extractors that allow them to be created from strings. This enables use cases like the following.
scala> "4" match {case EvenNumber(n) => n;case _ => None}
// returns EvenNumber(4)
scala> "5" match {case EvenNumber(n) => n;case _ => None}
// returns None
scala> "4" match {case OddNumber(n) => n;case _ => None}
// returns None
scala> "5" match {case OddNumber(n) => n;case _ => None}
// returns OddNumber(5)
The source code for the two extractors is identical except for the result of the x % 2 operation (0 or 1) and the extracted type (EvenNumber or OddNumber). I'd like to be able to write the source once and parameterize on these two values, but I can't figure out how. I've tried various type parameterizations to no avail.
The Stackoverflow question "How to use extractor in polymorphic unapply?" is related but different, because my implementing classes are not distinguished by the types they contain by rather by the string inputs they recognize.
Here is a revised version of the code incorporating comments I received in addition to the original post. (As is often the case, the first round of answers helped me figure out what my real question was.)
import scala.util.Try
trait Number {
val x: Int
}
object NumberParser {
def parse[N <: Number](s: String, remainder: Int, n: Int => N): Option[N] =
Try {s.toInt}.toOption.filter(_ % 2 == remainder).map(n(_))
}
case class EvenNumber(x: Int) extends Number
object EvenNumber {
def unapply(s: String): Option[EvenNumber] = NumberParser.parse(s, 0, EvenNumber(_))
}
case class OddNumber(x: Int) extends Number
object OddNumber {
def unapply(s: String): Option[OddNumber] = NumberParser.parse(s, 1, OddNumber(_))
}
Factoring out a static NumberParser.parse function is a reasonable solution. I would still like to have have syntactic sugar that obviated my repeating unapply lines in all of my case classes, since in a more complicated example that had more than two that could get ugly. Does anyone know of a way to do this?
More crucially, the use case I really want to support is the following.
scala> "5" match {case EvenNumber(n) =>n;case OddNumber(n) => n;case _ => None}
// returns OddNumber(5)
scala> "4" match {case EvenNumber(n) =>n;case OddNumber(n) => n;case _ => None}
// returns EvenNumber(4)
scala> "x" match {case EvenNumber(n) =>n;case OddNumber(n) => n;case _ => None}
// returns None
Again this is fine for two cases, but in a different application where there are more than two it can become unmanageable. I want to write a single case
s match {case Number(n) => n; case _ => None}
which returns OddNumber(5), EvenNumber(4), None as above.
I can't figure out how to write my Number supertype to support this. Is it possible in Scala?
Edit: Wrote a description of my final answer with additional commentary in "Runtime Polymorphism with Scala Extractors".
Why inherit?
object Mod2Number {
def parse[A <: Number](s: String, i: Int, n: Int => A) = {
val x = s.toInt
if (x % 2 == i) Some(n(x))
else None
}
}
case class EvenNumber(x: Int) extends Number
object EvenNumber {
def unapply(s: String) = Mod2Number.parse(s, 0, n => EvenNumber(n))
}
But if even that is too much noise you can go one step further:
trait Makes[A <: Number] {
def apply(i: Int): A
def mod: Int
def unapply(s: String): Option[A] = {
val x = s.toInt
if (x % 2 == mod) Some(apply(x))
else None
}
}
case class EvenNumber(x: Int) extends Number
object EvenNumber extends Makes[EvenNumber] { def mod = 0 }
I guess you should catch exceptions on toInt - exceptions in pattern matching is something strange.
object EvenNumber {
def unapply(s: String): Option[Int] = Try{s.toInt}.toOption.filter{_ % 2 == 0}
}
object OddNumber {
def unapply(s: String): Option[Int] = Try{s.toInt}.toOption.filter{_ % 2 == 1}
}
You could extract similar code, but I don't think it's useful here:
class IntFilter(f: Int => Boolean) {
def unapply(s: String): Option[Int] = Try{s.toInt}.toOption.filter(f)
}
object EvenNumber extend IntFilter(_ % 2 == 0)
object OddNumber extend IntFilter(_ % 2 == 1)
For edited question:
s match {case Number(n) => n; case _ => None}
You could create object Number like this:
object Number{
def unapply(s: String): Option[Number] = Try{s.toInt}.toOption.collect{
case i if i % 2 == 0 => EvenNumber(i)
case i if i % 2 == 1 => OddNumber(i)
}
}
Related
It looks First and Second are the same, but why?
First
val iter = List(1, 2, 3, 4, 5).iterator
val first = iter.collect(new PartialFunction[Int, Int]{
def apply(i: Int) = i
def isDefinedAt(i: Int) = i > 0 && i < 3
})
first.foreach((println(_)))
Second
val iter2 = List(1, 2, 3, 4, 5).iterator
val second = iter2.collect {
case i:Int if i > 0 && i < 3 => i
}
second.foreach((println(_)))
Is it because the Scala compiler automatically converts
{ case i:Int if i > 0 && i < 3 => i } into the implelentation form of First with generating isDefinedAt from if i > 0 && i < 3 part?
Also, case i:Int if i > 0 && i < 3 => i is Case class pattern matching, if I am correct. However, in scala/src/library/scala/PartialFunction.scala, there is no Case class definition for PartialFunction.
trait PartialFunction[-A, +B] extends (A => B)
Then why this case class pattern match works?
I suppose Scala compiler does lots of implicit works intelligently but it confuses me to understand what is happening and how to write Scala code.
If there are good references, instead of language or compiler specifications, to understand
Scala code syntax and Scala way of writing code, please suggest.
Is it because the Scala compiler automatically converts { case i:Int if i > 0 && i < 3 => i } into the implelentation form of First with generating isDefinedAt from **if i > 0 && i < 3 ** part?
Yes, the exact translation is given in Pattern Matching Anonymous Functions. Here it'll be
new PartialFunction[Int, Int]{
def apply(x: Int) = x match {
case i:Int if i > 0 && i < 3 => i
}
def isDefinedAt(x: Int) = x match {
case i:Int if i > 0 && i < 3 => true
case _ => false
}
}
Note the difference with your first example in apply! You can still call it when isDefined is false.
Also, case i:Int if i > 0 && i < 3 => i is Case class pattern matching, if I am correct
If anything, it's the other way around; case classes are called that way because they can be pattern-matched and pattern matching uses case keyword in Scala.
Yes, the compiler converts the second version into a PartialFunction[Int,Int] (because that is what collect takes).
There is no case class matching here, and it is not even matching on type because the value must be Int (and therefore the type declaration in the second version is not required).
The style guide gives lots on tips on how Scala is typically written.
For your example
object Main {
def f = (1 to 5).collect { case i if i > 0 && i < 3 => i }
}
The compiler-generated partial function defines applyOrElse because it is more efficient than the naive idiom:
if (pf.isDefinedAt(x)) pf.apply(x) else ???
Showing that implementation, which is similar to what is described in the spec:
$ scalac -Vprint:typer pf.scala
[[syntax trees at end of typer]] // pf.scala
package <empty> {
object Main extends scala.AnyRef {
def <init>(): Main.type = {
Main.super.<init>();
()
};
def f: IndexedSeq[Int] = scala.Predef.intWrapper(1).to(5).collect[Int](({
#SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[Int,Int] with java.io.Serializable {
def <init>(): <$anon: Int => Int> = {
$anonfun.super.<init>();
()
};
final override def applyOrElse[A1 <: Int, B1 >: Int](x1: A1, default: A1 => B1): B1 = ((x1.asInstanceOf[Int]: Int): Int #unchecked) match {
case (i # _) if i.>(0).&&(i.<(3)) => i
case (defaultCase$ # _) => default.apply(x1)
};
final def isDefinedAt(x1: Int): Boolean = ((x1.asInstanceOf[Int]: Int): Int #unchecked) match {
case (i # _) if i.>(0).&&(i.<(3)) => true
case (defaultCase$ # _) => false
}
};
new $anonfun()
}: PartialFunction[Int,Int]))
}
}
where AbstractPartialFunction defines
def apply(x: T1): R = applyOrElse(x, PartialFunction.empty)
Here is an external link to a change to use applyOrElse. The improved PartialFunction dates back to 2012. Probably the feature is under-documented or under-advertised. Some information is available by expanding the Scaladoc for PartialFunction. For some reason, that link shows orElse, so you'd actually have to scroll back for applyOrElse. It seems documentation is hard.
I have an array of objects of type Either[A, B]. If I know for a particular element whether it is an A or a B, how do I call a method on it that only exists on one of the 2 types. For example:
import scala.util.Random
object EitherTest extends App {
def newObj(x: Int): Either[A,B] = {
if (x == 0)
Left(new A())
else
Right(new B())
}
val random = new Random()
val randomArray = (0 until 10).map(_ => random.nextInt(2))
val eitherArray = randomArray.map(newObj)
(0 until 10).foreach(x => randomArray(x) match {
case 0 => eitherArray(x).aMethod()
case 1 => eitherArray(x).bMethod()
case _ => println("Error!")
})
}
class A {
def aMethod() = println("A")
}
class B {
def bMethod() = println("B")
}
When I compile this code, the lines
case 0 => eitherArray(x).aMethod()
case 1 => eitherArray(x).bMethod()
both have the error "value aMethod is not a member of Either[A,B]". How can I solve this?
I don't know why fold doesn't get the respect it deserves. It can be so useful.
eitherArray.foreach(_.fold(_.aMethod(), _.bMethod()))
Well, you can do it if you exctract the logic to another method, and do some pattern matching over the value Either, then check if it is Right or Left, and that's it!
object HelloWorld {
import scala.util.Random
def main(args: Array[String]) {
val random = new Random()
val randomArray = (0 until 10).map(_ => random.nextInt(2))
val eitherArray = randomArray.map(EitherTest.newObj)
(0 until 10).foreach(x => randomArray(x) match {
case 0 => EitherTest.callmethod(eitherArray(x))
case 1 => EitherTest.callmethod(eitherArray(x))
case _ => println("Error!")
})
println("Hello, world!")
}
}
class EitherTest
object EitherTest {
def callmethod(ei : Either[A,B]) = {
ei match {
case Left(a) => a.aMethod()
case Right(b) => b.bMethod()
}
}
def newObj(x: Int): Either[A,B] = {
if (x == 0)
Left(new A())
else
Right(new B())
}
}
class A {
def aMethod() = println("A")
}
class B {
def bMethod() = println("B")
}
Will print for you, for one random example:
A
B
A
B
A
A
A
B
B
B
Hello, world!
Basically, the way you do with Either is projections: Either.left gives you the projection of the left type, and Either.right gives you that of the right.
The projections are somewhat similar to options, in that they can be empty (if your Either is a Right, then the left projection is empty and vice versa), and you can use the usual monadic transformations with them, like map, flatMap, foreach, getOrElse etc.
Your example, could look like this:
randomArray.foreach { either =>
either.left.foreach(_.aMethod)
either.right.foreach(_.bMethod)
}
You could also use pattern-matching instead, that's less general, but, perhaps looks a bit clearer in this case:
randomArray.foreach {
case Left(a) => a.aMethod
case Right(b) => b.bMethod
}
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 thought the following would be the most concise and correct form to collect elements of a collection which satisfy a given type:
def typeOnly[A](seq: Seq[Any])(implicit tag: reflect.ClassTag[A]): Seq[A] =
seq.collect {
case tag(t) => t
}
But this only works for AnyRef types, not primitives:
typeOnly[String](List(1, 2.3, "foo")) // ok. List(foo)
typeOnly[Double](List(1, 2.3, "foo")) // fail. List()
Obviously the direct form works:
List(1, 2.3, "foo") collect { case d: Double => d } // ok. List(2.3)
So there must be a (simple!) way to fix the above method.
It's boxed in the example, right?
scala> typeOnly[java.lang.Double](vs)
res1: Seq[Double] = List(2.3)
Update: The oracle was suitably cryptic: "boxing is supposed to be invisible, plus or minus". I don't know if this case is plus or minus.
My sense is that it's a bug, because otherwise it's all an empty charade.
More Delphic demurring: "I don't know what the given example is expected to do." Notice that it is not specified, expected by whom.
This is a useful exercise in asking who knows about boxedness, and what are the boxes? It's as though the compiler were a magician working hard to conceal a wire which keeps a playing card suspended in midair, even though everyone watching already knows there has to be a wire.
scala> def f[A](s: Seq[Any])(implicit t: ClassTag[A]) = s collect {
| case v if t.runtimeClass.isPrimitive &&
| ScalaRunTime.isAnyVal(v) &&
| v.getClass.getField("TYPE").get(null) == t.runtimeClass =>
| v.asInstanceOf[A]
| case t(x) => x
| }
f: [A](s: Seq[Any])(implicit t: scala.reflect.ClassTag[A])Seq[A]
scala> f[Double](List(1,'a',(),"hi",2.3,4,3.14,(),'b'))
res45: Seq[Double] = List(2.3, 3.14)
ScalaRunTime is not supported API -- the call to isAnyVal is just a match on the types; one could also just check that the "TYPE" field exists or
Try(v.getClass.getField("TYPE").get(null)).map(_ == t.runtimeClass).getOrElse(false)
But to get back to a nice one-liner, you can roll your own ClassTag to handle the specially-cased extractions.
Version for 2.11. This may not be bleeding edge, but it's the recently cauterized edge.
object Test extends App {
implicit class Printable(val s: Any) extends AnyVal {
def print = Console println s.toString
}
import scala.reflect.{ ClassTag, classTag }
import scala.runtime.ScalaRunTime
case class Foo(s: String)
val vs = List(1,'a',(),"hi",2.3,4,Foo("big"),3.14,Foo("small"),(),null,'b',null)
class MyTag[A](val t: ClassTag[A]) extends ClassTag[A] {
override def runtimeClass = t.runtimeClass
/*
override def unapply(x: Any): Option[A] = (
if (t.runtimeClass.isPrimitive && (ScalaRunTime isAnyVal x) &&
x.getClass.getField("TYPE").get(null) == t.runtimeClass)
Some(x.asInstanceOf[A])
else super.unapply(x)
)
*/
override def unapply(x: Any): Option[A] = (
if (t.runtimeClass.isPrimitive) {
val ok = x match {
case _: java.lang.Integer => runtimeClass == java.lang.Integer.TYPE
//case _: java.lang.Double => runtimeClass == java.lang.Double.TYPE
case _: java.lang.Double => t == ClassTag.Double // equivalent
case _: java.lang.Long => runtimeClass == java.lang.Long.TYPE
case _: java.lang.Character => runtimeClass == java.lang.Character.TYPE
case _: java.lang.Float => runtimeClass == java.lang.Float.TYPE
case _: java.lang.Byte => runtimeClass == java.lang.Byte.TYPE
case _: java.lang.Short => runtimeClass == java.lang.Short.TYPE
case _: java.lang.Boolean => runtimeClass == java.lang.Boolean.TYPE
case _: Unit => runtimeClass == java.lang.Void.TYPE
case _ => false // super.unapply(x).isDefined
}
if (ok) Some(x.asInstanceOf[A]) else None
} else if (x == null) { // let them collect nulls, for example
if (t == ClassTag.Null) Some(null.asInstanceOf[A]) else None
} else super.unapply(x)
)
}
implicit def mytag[A](implicit t: ClassTag[A]): MyTag[A] = new MyTag(t)
// the one-liner
def g[A](s: Seq[Any])(implicit t: ClassTag[A]) = s collect { case t(x) => x }
// this version loses the "null extraction", if that's a legitimate concept
//def g[A](s: Seq[Any])(implicit t: ClassTag[A]) = s collect { case x: A => x }
g[Double](vs).print
g[Int](vs).print
g[Unit](vs).print
g[String](vs).print
g[Foo](vs).print
g[Null](vs).print
}
For 2.10.x, an extra line of boilerplate because implicit resolution is -- well, we won't say it's broken, we'll just say it doesn't work.
// simplified version for 2.10.x
object Test extends App {
implicit class Printable(val s: Any) extends AnyVal {
def print = Console println s.toString
}
case class Foo(s: String)
val vs = List(1,'a',(),"hi",2.3,4,Foo("big"),3.14,Foo("small"),(),null,'b',null)
import scala.reflect.{ ClassTag, classTag }
import scala.runtime.ScalaRunTime
// is a ClassTag for implicit use in case x: A
class MyTag[A](val t: ClassTag[A]) extends ClassTag[A] {
override def runtimeClass = t.runtimeClass
override def unapply(x: Any): Option[A] = (
if (t.runtimeClass.isPrimitive && (ScalaRunTime isAnyVal x) &&
(x.getClass getField "TYPE" get null) == t.runtimeClass)
Some(x.asInstanceOf[A])
else t unapply x
)
}
// point of the exercise in implicits is the type pattern.
// there is no need to neutralize the incoming implicit by shadowing.
def g[A](s: Seq[Any])(implicit t: ClassTag[A]) = {
implicit val u = new MyTag(t) // preferred as more specific
s collect { case x: A => x }
}
s"Doubles? ${g[Double](vs)}".print
s"Ints? ${g[Int](vs)}".print
s"Units? ${g[Unit](vs)}".print
s"Strings? ${g[String](vs)}".print
s"Foos? ${g[Foo](vs)}".print
}
Promoting a comment:
#WilfredSpringer Someone heard you. SI-6967
I want to the get the manifest of one List's inner type like following and pass it to another function, how can I do that ? Thanks
def f(any: Any) = any match {
case x: Int => println("Int")
case a: List[_] => // get the manifest of List's inner type, and use it in the function g()
}
def g[T:Manifest](list:List[T]) = {}
Add the manifest as an implicit requirement to your method, and tweak the type signature a tiny bit:
def f[T](any: T)(implicit mf: Manifest[T]) = mf match {
case m if m == Manifest[Int] => println("Int")
case m if m == Manifest[List[Int]] => println("List of Ints")
//etc...
}
The Manifest class has a method, typeArguments, that should serve your purpose for finding the "inner type". For example
manifest[List[Int]].typeArguments == List(manifest[Int])
You could tweak #Dylan's answer a bit and try this as well:
object ManifestTest {
def f[T](t: T)(implicit m:Manifest[T]) = t match {
case x: Int => println("Int")
case a: List[Any] =>
val innerType = m.typeArguments.head
println(innerType)
}
def main(args: Array[String]) {
f(1)
f(List("hello", "world"))
f(List(1))
}
}