It is well-known that a programmer can declare a new variable in Scala by using val or var, like this:
val x = 10 //x is now defined and an Integer.
A function parameter also introduces a new variable:
def fun(y: String) {
//y of type String is now available here
}
These are straight forward examples. However, there are more ways to declare a variable in a given context.
For instance, a match expression can also introduce new variables:
val z = 10
z match {
case w: Int => w //w is a valid variable of type Int in this scope
}
What are further commands which introduce variables into a certain scope in Scala?
Background for the interested:
I'm using this in a macro which finds variable definitions (ValDefs) in the abstract syntax tree. match expressions or function definitions generate a different syntax tree than normal ValDefs, which I have to take care of. Since I want my macro to be robust, I want to test it against all possible forms of variable declarations.
Notes on comments:
Method definitions with def are not of concern. Furthermore, I am only interested in variables which are visible in the source code and can be referenced by some term.
Here's a list of everything I know of that might be different; x is the variable created:
// Within a block
val x = 5
var x = 5
lazy val x = 5
def x = 5
object x { val value = 5 }
val MyCaseClass(x, _) = oneOfMyCaseClasses
val MyCaseClass(_, Another(x)) = foo
val MyCaseClass(_, x # Another(_)) = foo
// Functions
m.map( x => bar(x) )
m.map( (x: Int) => bar(x) )
// Functions that destructure
m.map{ case y if foo(y) => baz; case x => bar(x) }
m.map{ case Option(x) => bar(x) }
m.map{ case Option(List(x)) => bar(x) }
m.map{ case Option(x # List(_)) => foo(x) }
// Partial functions with/without destructuring
m.collect{ case x => bar(x) }
m.collect{ case Option(List(x)) => bar(x) }
m.collect{ case Option(x # List(_)) => foo(x) }
// For comprehensions
for (x <- xs)
for (y <- ys; x = foo(y))
for ((x, _) <- zs)
for ((_, y # Option(_)) <- ws)
// Method arguments
def foo(x: Int) =
def foo(y: Int)(implicit x: Foo) =
class Foo(x: Int)
class Foo(val x: Int)
class Foo(var x: Int)
case class Foo(x: Int)
case class Foo(var x: Int)
Destructuring Bind:
case class CaseClassFiftyThree(x: Double, y: Long, z: String)
...
someValue match { case CaseClassFiftyThree(x, y, z) =>
/* x, y and z are bound here as Double, Long and String, resp. */ }
Irrefutable Pattern Match:
val (r, s, t) = (53, 17.0 * 3 + 2, "LIII")
/* r, s and t are bound here as Int, Double and String, resp. */
Related
In the following code:
def product(f: Int => Int)(a:Int, b:Int): Int =
if (a > b) 1
else f(a) * product(f)(a + 1, b)
The parameters a and b are passed to the inner function, but you could write exactly the same function definition like so:
def product(f: Int => Int, a:Int, b:Int): Int =
if (a > b) 1
else f(a) * product(f, a + 1, b)
So what is the purpose of separating the parameters? In other words, why do this:
(f: Int => Int)(a:Int, b:Int)
when you can more clearly write:
(f: Int => Int, a:Int, b:Int)
Another feature of multiple parameters lists is partial application:
def sum3(a: Int)(b: Int)(c: Int): Int = a + b + c
val g: Int => Int => Int = sum3(10) _
val h: Int => Int = g(20)
val r: Int = h(30) // 10 + 20 + 30 = 60
You can partially apply a function and obtain another function which is equivalent to the original one but with one of the arguments fixed. _ after sum3(10) is needed because sum3 is a method, not a function, and _ converts methods to functions.
This is very useful when you are using higher-order functions:
def adder(x: Int)(y: Int) = x + y
Seq(1, 2, 3, 4) map adder(10) // Seq(11, 12, 13, 14)
When partially applied method/function is used as an argument of a higher-order call, _ is not needed, and the syntax becomes very succinct.
Another use case of this feature is that if you want to create a control structure that looks like it's built into Scala programming language itself.
For example, I could write an control structure named times which help me execute the code block exactly n times by the following method definition:
// since block is call by name, it will not be evaluate when you call it.
def times(n: Int)(block: => Any): Unit = {
for (i <- 0 until n) {
block // evaluate(execute) block
}
}
// Now I can use the times method like a control structure
times(5) {
println("Hello World");
}
It depends whether there is implicit parameter (which can't be properly mixed with plain ones)...
def foo(i: Int)(implicit p: P): Foo
... and the way you want to call it ...
def foo1(a: Int)(b: Int => Boolean): Boolean
foo1(9) { i => false }
def foo2(a: Int, b: Int => Boolean): Boolean
foo2(9, { i => false })
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)
}
}
I am trying to rewrite some java math classes into Scala, but am having an odd problem.
class Polynomials[#specialized T](val coefficients:List[T]) {
def +(operand:Polynomials[T]):Polynomials[T] = {
return new Polynomials[T](coefficients =
(operand.coefficients, this.coefficients).zipped.map(_ + _))
}
}
My problem may be similar to this question: How do I make a class generic for all Numeric Types?, but when I remove the #specialized I get the same error.
type mismatch; found : T required: String
The second underscore in the map function is highlighted for the error, but I don't think that is the problem.
What I want to do is have:
Polynomial(1, 2, 3) + Polynomial(2, 3, 4) return Polynomial(3, 5, 7)
And Polynomial(1, 2, 3, 5) + Polynomial(2, 3, 4) return Polynomial(3, 5, 7, 5)
For the second one I may have to pad the shorter list with zero elements in order to get this to work, but that is my goal on this function.
So, how can I get this function to compile, so I can test it?
List is not specialized, so there's not much point making the class specialized. Only Array is specialized.
class Poly[T](val coef: List[T]) {
def +(op: Poly[T])(implicit adder: (T,T) => T) =
new Poly(Poly.combine(coef, op.coef, adder))
}
object Poly {
def combine[A](a: List[A], b: List[A], f: (A,A) => A, part: List[A] = Nil): List[A] = {
a match {
case Nil => if (b.isEmpty) part.reverse else combine(b,a,f,part)
case x :: xs => b match {
case Nil => part.reverse ::: a
case y :: ys => combine(xs, ys, f, f(x,y) :: part)
}
}
}
}
Now we can
implicit val stringAdd = (s: String, t: String) => (s+t)
scala> val p = new Poly(List("red","blue"))
p: Poly[String] = Poly#555214b9
scala> val q = new Poly(List("fish","cat","dog"))
q: Poly[String] = Poly#20f5498f
scala> val r = p+q; r.coef
r: Poly[String] = Poly#180f471e
res0: List[String] = List(redfish, bluecat, dog)
You could also ask the class provide the adder rather than the + method, or you could subclass Function2 so that you don't pollute things with implicit addition functions.
in scala play framework I seen this code:
abstract class AnalyserInfo
case class ColumnC(typeName:String,fieldName:String) extends AnalyserInfo
case class TableC(typeName:String) extends AnalyserInfo
val asIs :PartialFunction[AnalyserInfo,String] = {
case ColumnC(_,f) => f;
case TableC(typeName) => typeName
}
What is the difference with:
val asIs: (AnaliserInfo)=>String = (info) => info match {
case ColumnC(_,f) => f;
case TableC(typeName) => typeName
}
There is a preferred style? and why in the first case the match keyword can be omitted?
Thank you for the support.
Double => Double is just a shorthand for Function[Double, Double]. PartialFunction inherits from Function but adds a few methods. Most importantly, it adds the method isDefinedAt which allows you to query if the function is defined for some parameter.
The cases without a match are a special syntax to define partial functions, which generates an isDefinedAt that returns true for all matching cases.
Say we have a function that returns 1/x, but only for positive values of x, we could it define as:
scala> val f: (Double => Double) = { case x if x > 0 => 1/x }
f: (Double) => Double = <function1>
or as:
scala> val g: PartialFunction[Double, Double] = { case x if x > 0 => 1/x }
g: PartialFunction[Double,Double] = <function1>
The second version has the benefit that we could check if the function is applicable to some parameter:
scala> g.isDefinedAt(-3)
res0: Boolean = false
This feature is for example used in Scala to implement the actor library where an Actor might only consume certain types of messages.
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
...
}