In this explanation of partial functions in scala, an case statement is used as follows:
val divide2: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 42 / d
}
Then it says:
Although this code doesn’t explicitly implement the isDefinedAt
method, it works exactly the same as the previous divide function
definition
The previous divide function explicitly defines apply and isDefined methods as follows:
val divide = new PartialFunction[Int, Int] {
def apply(x: Int) = 42 / x
def isDefinedAt(x: Int) = x != 0
}
I see that the compiler is doing some sort of magic here, but I'm curious about the nature of the mechanism: is the guard in the case (if d != 0) extracted into body of isDefined at the background? What about multiple case statements with their own guards? The domain of the function is defined in the case statement(s), so that must be how the compiler is building the implementation of isDefined behind the scenes.
Am I right?
First of all, the explanation is wrong, since both the presented examples don't work the same:
scala> val a: PartialFunction[Int, Int] = {
| case i if i != 0 => 42 / i
| }
a: PartialFunction[Int,Int] = <function1>
scala> val b = new PartialFunction[Int, Int] {
| def apply(i: Int) = 42 / i
| def isDefinedAt(i: Int) = i != 0
| }
b: PartialFunction[Int,Int] = <function1>
scala> a(0)
scala.MatchError: 0 (of class java.lang.Integer)
at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:253)
at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:251)
at $anonfun$1.applyOrElse(<console>:7)
at $anonfun$1.applyOrElse(<console>:7)
at scala.runtime.AbstractPartialFunction$mcII$sp.apply$mcII$sp(AbstractPartialFunction.scala:36)
... 33 elided
scala> b(0)
java.lang.ArithmeticException: / by zero
at $anon$1.apply$mcII$sp(<console>:8)
... 33 elided
But the core of it is true, the compiler converts the code in the case clauses to a boolean expression for the isDefinedAt method and then the function itself as the apply method (hence the MatchError if the value is not defined)
For a general example, a function like this:
val a = PartialFunction[A, B] {
case <clause A> => <action A>
case <clause B> => <action B>
}
Is compiled as:
val a = new PartialFunction[A, B] {
def isDefinedAt(a: A) = a match {
case <clause A> => true
case <clause B> => true
case _ => false
}
def apply(a: A) = a match {
case <clause A> => <action A>
case <clause B> => <action B>
}
}
Here is the spec that defines this behavior.
I believe it's working because of the available case supported by the pattern matching definition.
The divide2 method has one matching case: x != 0 given x of type Int, therefore, if your value is anything else than that, it should return false.
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.
We define a customEquality[String]:
implicit val upperCaseEquality = new Equality[String] {
override def areEqual(self: String, b: Any): Boolean = b match {
case other: String => self.toUpperCase == other.toUpperCase
case _ => false
}
}
The following code works, as expected:
Seq("a").view should contain theSameElementsInOrderAs Seq("A")
Now, we add a custom Equality for Seq:
implicit def SeqEquality[T, SEQ[e] <: GenSeq[e]](implicit equality: Equality[T]): Equality[SEQ[T]] = new Equality[SEQ[T]] {
override def areEqual(self: SEQ[T], b: Any): Boolean = b match {
case other: GenSeq[_] => self.size == other.size && self.zip(other).forall(equality.areEqual _ tupled)
case _ => false
}
}
Custom TripleEquals equality works for Seq:
assert(Seq("a") === Seq("A"))
but does not work for SeqView:
assert(Seq("a").view === Seq("A"))
Exception in thread "main" org.scalatest.exceptions.TestFailedException: SeqView("a") did not equal List("A")
Why?
If you look at what .view returns:
def view(from: Int, until: Int): SeqView[A, Seq[A]]
you see that SeqView[_, _] actually has two type parameters, so it is not conforming to your specification SEQ[e] <: GenSeq[e]. (In theory you could imagine that if Scala supported partially-applied type constructors this could be unified somehow, but it is a tricky problem and Scala does not support it).
In your case, you can make it work by making a definition that is explicit for SeqView and does not use higher-kinded types:
implicit def SeqViewEquality[T](implicit equality: Equality[T]): Equality[SeqView[T, Seq[T]]] = new Equality[SeqView[T, Seq[T]]] {
override def areEqual(self: SeqView[T, Seq[T]], b: Any): Boolean = b match {
case other: GenSeq[_] => self.size == other.size && self.zip(other).forall(equality.areEqual _ tupled)
case _ => false
}
}
Though, I admit this is somewhat unsatisfying.
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'm attempting to write an extractor(s) for use in matching against a multiple parameter case class. Simplified example:
case class X(p1: String, p2: Int)
I'd like each extractor objects to define a fixed value for p1, and p2 is defined on use. (A,B, etc cannot be a case class and subclass X, and I would also like to use X(,) as a case)
Example with apply method:
object A {
def apply(p2: Int): X = X("A", p2)
}
object B {
def apply(p2: Int): X = X("B", p2)
}
...
For pattern matching, I would like them to match like this:
X("A", 2) match {
case A(2) => true // <- should match: p1="A" and p2=2
case A(_) => true // <- should match: p1="A" and p2=_
case X("A", _) => true // <- should match: p1="A" and p2=_
case A(1) => false // <- should not match
case B(2) => false // <- should not match: p1="B" and p2=2
}
I know I need to define unapply method in A, B, etc., but I'm thoroughly confused what the signature and logic should be:
object A {
def unapply(x: ???): Option[???] = {
???
}
}
Assistance, please?
unapply takes an Any and returns an Option of whatever you want to extract. In your case this would be:
scala> case class X(p1: String, p2: Int)
defined class X
scala> object A {
| def unapply(target: Any): Option[Int] =
| PartialFunction.condOpt(target) {
| case X("A", p2) => p2
| }
| }
defined module A
scala> val A(x) = X("A", 1)
x: Int = 1
scala> val A(x) = X("B", 1)
scala.MatchError: X(B,1) (of class X)
...
But to be honest, the example you came up with could be rewritten without A and B:
X("A",2) match {
case X("A", 2) => true
case X("A", 1) => false
case X("A", _) => true
case X("B", 2) => false
}
What are all the instances of syntactic sugar in Scala?
They are hard to search for since most/all of them are purely symbols and are thus hard to search for without knowing the name of the concept.
TODO:
Implicit conversions
_ syntax for anonymous functions
Other things I'm forgetting
Basics:
a b is equivalent to a.b.
a b c is equivalent to a.b(c), except when b ends in :. In that case, a b c is equivalent to c.b(a).
a(b) is equivalent to a.apply(b) This is why the following definitions for an anonymous functions are identical:
val square1 = (x: Int) => x*x
val square2 = new Function1[Int,Int] {
def apply(x: Int) = x*x
}
When calling square1(y), you are actually calling square1.apply(y) which square1 must have as specified by the Function1 trait (or Function2, etc...)
a(b) = c is equivalent to a.update(b,c). Likewise, a(b,c) = d is equivalent to a.update(b,c,d) and so on.
a.b = c is equivalent to a.b_=(c). When you create a val/var x in a Class/Object, Scala creates the methods x and x_= for you. You can define these yourself, but if you define y_= you must define y or it will not compile, for example:
scala> val b = new Object{ def set_=(a: Int) = println(a) }
b: java.lang.Object{def set_=(Int): Unit} = $anon$1#17e4cec
scala> b.set = 5
<console>:6: error: value set is not a member of java.lang.Object{def set_=(Int): Unit}
b.set = 5
^
scala> val c = new Object{ def set = 0 ; def set_=(a:Int) = println(a) }
c: java.lang.Object{def set: Int; def set_=(Int): Unit} = $anon$1#95a253
scala> c.set = 5
5
-a corresponds to a.unary_-. Likewise for +a,~a, and !a.
a <operator>= b, where <operator> is some set of special characters, is equivalent to a = a <operator> b only if a doesn't have the <operator>= method, for example:
class test(val x:Int) {
def %%(y: Int) = new test(x*y)
}
var a = new test(10)
a.x // 10
a %%= 5 // Equivalent to a = a %% 5
a.x // 50
Special Classes: Tuples and Symbols
As mentioned by Rahul G, tuples and symbols get a slightly special syntax.
Symbols: the syntax 'x is short for Symbol("x")
Tuples: (p1,p2,..,pn) is short for a case class Tuplen[T1,T2,..,Tn](p1,p2,..,pn)
For example, the following two are equivalent.
val tuple1 = ("Hello",1)
val tuple2 = Tuple2[String,Int]("Hello",1)
In addition to Jaxkson's answer:
type F[A,B] can be used as A F B.
For example:
type ->[A,B] = (A,B)
def foo(f: String -> String)
Using => type in a method definition makes the compiler wrap expressions inside the method call in a function thunk.
For example
def until(cond: => Boolean)(body: => Unit) = while(!cond) body
var a = 0
until (a > 5) {a += 1}
Extractors:
There are two methods used for extractors, unapply and unapplySeq. These are used in multiple variable assignments and pattern matching.
The first use case is where unapply takes the object it is supposed to match and returns a Boolean based on whether or not it matches, for example,
trait Gender
trait Male extends Gender
trait Female extends Gender
object Male extends Male
object Female extends Female
class Person(val g: Gender, val age: Int)
object Adult {
def unapply(p: Person) = p.age >= 18
}
def check(p: Person) = p match {
case Adult() => println("An Adult")
case _ => println("A Child")
}
//Will print: An Adult since Adult.unapply returns true.
check(new Person(Female, 18))
//Will print: A Child as it falls through to the _ case.
check(new Person(Male, 17))
Honestly, I don't really get the purpose of the above syntax since it can be done almost just as easily by just putting the code in the case statements. Of course if you have a better example, leave a comment below
The general case where unapply takes some fixed-number of parameters and returns either an Option[T] for a single parameter or a Option[(p1,p2,...)] for multiple, i.e. a Tuple with the matched values, for example, continuing from the above code:
object Person {
def apply(g: Gender, age: Int) = new Person(g, age)
def unapply(p: Person) = if(p.age < 0) None else Some((p.g, p.age))
}
//Using Person.apply as described in the Basics section
val alice = Person(Female, 30)
val bob = Person(Male, 25)
//This calls Person.unapply(alice), which returns Some((Female, 30)).
//alice_gender is assigned Female and alice_age 30.
val Person(alice_gender, alice_age) = alice
bob match {
//Calls Person.unapply(bob), but sees that g is Male, so no match.
case Person(Female, _) => println("Hello ma'am")
//Calls Person.unapply(bob) and assigns age = bob.age, but it doesn't pass
//the 'if' statement, so it doesn't match here either.
case Person(Male, age) if age < 18 => println("Hey dude")
//So bob falls through to here
case _ => println("Hello Sir")
}
Person(Male,-1) match {
//Person.unapply(Person.apply(Male,-1)) returns None because p.age < 0.
//Therefore this case will not match.
case Person(_, _) => println("Hello person")
//Thus it falls through to here.
case _ => println("Are you Human?")
}
Note: Case classes do all those apply/unapply definitions for you (as well as other stuff) so use them whenver possible to save time and reduce code.
unapplySeq. This works similarly to unapply as above, except it must return an Option of some kind of sequence.
As a quick example,
scala> List.unapplySeq(List(1,2,3))
res2: Some[List[Int]] = Some(List(1, 2, 3))
Anonymous functions:
_ + _ is short for (a, b) => a + b
Context bounds desugar into implicit parameters, e.g. consider a function that leverages the Monoid type class:
def suml[T: Monoid](xs: List[T]) = {
val T = implicitly[Monoid[T]]
xs.foldLeft(T.mzero)(T.mplus)
}
where the : Monoid part is a context bound, gets translated to:
def suml[T](xs: List[T])(implicit evidence$1: Monoid[T]]) = {
...
}
therefore the following compiles, too:
def suml[T: Monoid](xs: List[T]) = {
val T = evidence$1
...
}