I'm fairly new to Scala and very new to writing macros and looking for a little help/advise. I have the following code...
trait ValidationRule
case class Required() extends ValidationRule
case class HasLength(l: Int) extends ValidationRule
case class Person(name: String)
myMacro[Person] { p => p.name.is(Required(), HasLength(255)) }
Obviously there is some missing code here but this is just pseudo to get the question out.
So given a Tree representing p => p.name.is(Required(), HasLength(255)) I'm trying to write a match/case to select out all expressions representing a ValidationRule. Something like:
case TypeApply(Select(_, ....
Can anyone suggest the best match case to be able to extract a List of Trees that represent each "all" ValidationRules from within the "is" method?
You should definitely look into Quasiquotes.
Quasiquotes are used to do two things: to build Trees, and to pattern match Trees. They allow you to express the tree that you want to work with in terms of the equivalent Scala code. You let the quasiquote library deal with how Scala code maps to a Tree graph, and that's a good thing!
You can play around with them in the REPL, though the results might be slightly different in the macro universe:
scala> import scala.reflect.runtime.universe._
scala> showRaw(cq"p => p.name.is(Required(), HasLength(255))")
res0: String = CaseDef(
Bind(
TermName("p"),
Ident(termNames.WILDCARD)),
EmptyTree,
Apply(
Select(
Select(
Ident(TermName("p")),
TermName("name")),
TermName("is")),
List(
Apply(
Ident(TermName("Required")),
List()),
Apply(
Ident(TermName("HasLength")),
List(Literal(Constant(255)))))))
The other thing you can do with Quasiquotes is to actually use them to pattern match.
scala> val fromTree = cq"p => p.name.is(Required(), HasLength(255))"
scala> val cq"p => p.name.is($x, $y)" = fromTree
x: reflect.runtime.universe.Tree = Required()
y: reflect.runtime.universe.Tree = HasLength(255)
Now, you have to be careful, because that pattern ONLY matches if the user named their pattern variable p.
scala> val fromTree = cq"x => x.name.is(Required(), HasLength(255))"
scala> val cq"p => p.name.is($x, $y)" = fromTree
scala.MatchError: case (x # _) => x.name.is(Required(), HasLength(255)) (of class scala.reflect.internal.Trees$CaseDef)
... 33 elided
Instead, you'll want to be a bit more generic:
scala> val cq"${p1:TermName} => ${p2:TermName}.name.is($x, $y)" = fromTree
p1: reflect.runtime.universe.TermName = x
p2: reflect.runtime.universe.TermName = x
x: reflect.runtime.universe.Tree = Required()
y: reflect.runtime.universe.Tree = HasLength(255)
scala> p1 == p2
res2: Boolean = true
And, of course, if you were doing this as part of a pattern match, you could do:
case cq"${p1:TermName} => ${p2:TermName}.name.is($x, $y)" if p1 == p2 =>
???
Keep in mind that Macros are a deep, dark hole. If you're just getting started, expect to spend a lot of time getting your macro code correct. After that, expect to spend a lot of time dealing with edge cases.
Related
I am new to Scala and I am having to provide values extracted from an object/case class into a Seq. I was wondering whether there would be any generic way of extracting values of an object into Seq of those values in order?
Convert the following:
case class Customer(name: Option[String], age: Int)
val customer = Customer(Some("John"), 24)
into:
val values = Seq("John", 24)
case class extends Product class and it provides such method:
case class Person(age:Int, name:String, lastName:Option[String])
def seq(p:Product) = p.productIterator.toList
val s:Seq[Any] = seq(Person(100, "Albert", Some("Einstain")))
println(s) //List(100, Albert, Some(Einstain))
https://scalafiddle.io/sf/oD7qk8u/0
Problem is that you will get untyped list/array from it. Most of the time it is not optimal way of doing things, and you should always prefer statically typed solutions.
Scala 3 (Dotty) might give us HList out-of-the-box which is a way of getting product's values without loosing type information. Given val picard = Customer(Some("Picard"), 75) consider the difference between
val l: List[Any] = picard.productIterator.toList
l(1)
// val res0: Any = 75
and
val hl: (Option[String], Int) = Tuple.fromProductTyped(picard)
hl(1)
// val res1: Int = 75
Note how res1 did not loose type information.
Informally, it might help to think of an HList as making a case class more generic by dropping its name whilst retaining its fields, for example, whilst Person and Robot are two separate models
Robot(name: Option[String], age: Int)
Person(name: Option[String], age: Int)
they could both represented by a common "HList" that looks something like
(_: Option[String], _: Int) // I dropped the names
If it's enough for you to have Seq[Any] you can use productIterator approach proposed by #Scalway. If I understood correctly you want also to unpack Option fields. But you haven't specified what to do with None case like Customer(None, 24).
val values: Seq[Any] = customer.productIterator.map {
case Some(x) => x
case x => x
}.toSeq // List(John, 24)
Statically typed solution would be to use heterogeneous collection e.g. HList
class Default[A](val value: A)
object Default {
implicit val int: Default[Int] = new Default(0)
implicit val string: Default[String] = new Default("")
//...
}
trait LowPriorityUnpackOption extends Poly1 {
implicit def default[A]: Case.Aux[A, A] = at(identity)
}
object unpackOption extends LowPriorityUnpackOption {
implicit def option[A](implicit default: Default[A]): Case.Aux[Option[A], A] = at {
case Some(a) => a
case None => default.value
}
}
val values: String :: Int :: HNil =
Generic[Customer].to(customer).map(unpackOption) // John :: 24 :: HNil
Generally it would be better to work with Option monadically rather than to unpack them.
I am new to Scala (Functional Programming). I am reading the book 'Functional Programming in Scala'. It was an exercise in which we need to define a partially applied function
def partial1 [A, B, C] (a: A, f: (A, B) => C): B => C = {
(b: B) => f(a, b)
}
I was wondering what is a real world use of this function? I tried to read different blogs to find an example, but couldn't find a useful example.
(Relevant to your question before you edited it) Let's start with terminology. PartialFunction is trait in scala that says that your function might not process all possible variations of the input:
val partialFunction: PartialFunction[Int, Int] = {
case 1 => 1
case 2 => 2
}
scala> partialFunction(1)
res43: Int = 1
scala> partialFunction(3)
scala.MatchError: 3 (of class java.lang.Integer)
It's completely unrelated to your example, which is a partial application - the article provided basically shows real-world example with email filtering.
About partial application.
Sometimes you might have a function with several parameters, let's say:
def sendMail(recipient: String, subject: String, body: String) = println(s"To: $recipient\n Subj: $subject\n Body: $body")
This function might be a part of the API, so you might not be able to change it. Now, let's say you need to send a same email to many different recipients:
object Spam{
val subject = "Hello!"
val body = "World!"
def spam(recipient: String) = sendMail(recipient, subject, body)
}
scala> Spam.spam("aaa#aa")
To: aaa#aa
Subj: Hello!
Body: World!
Another way to do that is to generate a function per subject/body, so to make it customizable:
def spammer(subject: String, body: String): String => Unit = (recipient: String) => {
sendMail(recipient, subject, body)
}
val spam1 = spammer("Hello", "World!")
spam1("emai#email.com")
It's roughly equivalent to OOP's:
class Spammer(subject: String, body: String){
def apply(recipient: String) = sendMail(recipient, subject, body)
}
val spam1 = new Spammer("Hello", "World!")
spam1("emai#email.com")
The difference is that partial application is able to deal more easily with complex cases and also has additional syntax sugar:
val spam1 = sendMail(_, "Hello", "World!")
spam1("emai#email.com")
So in simple cases you don't even need to define your own wrapper.
Returning to your more sophisticated example, you could use it this way:
scala> val incrementInt = partial1[Int, Int, Int](1, _ + _)
incrementInt: Int => Int = $$Lambda$1258/21635151#18ca65ea
scala> incrementInt(2)
res47: Int = 3
scala> val incrementList = partial1[List[Int], List[Int], List[Int]](List(0), _ ++ _)
incrementList: List[Int] => List[Int] = $$Lambda$1258/21635151#79f8af90
scala> incrementList(List(0))
res49: List[Int] = List(0, 0)
scala> incrementList(List(0, 0))
res50: List[Int] = List(0, 0, 0)
Basically abstract over addition (A, B) = C of some fixed abstract element A to unknown element B. In the example above it's addition over integers, and addition over lists of zeros. You can imagine more practical example like merging two json's with some fixed pattern and so on.
You might think of partail1 as providing a unified interface to all those cases.
Similar to this case class question but with a twist:
I have a case class which has some deeply nested case classes as properties. As a simple example,
case class Foo(fooPropA:Option[String], fooPropB:Option[Int])
case class Bar(barPropA:String, barPropB:Int)
case class FooBar(name:Option[String], foo:Foo, optionFoo: Option[Foo], bar:Option[Bar])
I'd like to merge two FooBar case classes together, taking the values which exist for an input and applying them to an existing instance, producing an updated version:
val fb1 = FooBar(Some("one"), Foo(Some("propA"), None), Some(Foo(Some("propA"), Some(3))), Some(Bar("propA", 4)))
val fb2 = FooBar(None, Foo(Some("updated"), Some(2)), Some(Foo(Some("baz"), None)), None)
val merged = fb1.merge(fb2)
//merged = FooBar(Some("one"), Foo(Some("updated"), Some(2)), Some(Foo(Some("baz"), Some(3))), Some(Bar("propA", 4)))
I know I can use a lens to compose the deeply nested property updates; however, I feel this will require a lot of boiler plate code: I need a lens for every property, and another composed lens in the parent class. This seems like a lot to maintain, even if using the more succinct lens creation approach in shapeless.
The tricky part is the optionFoo element: in this scenario, both elements exist with a Some(value). However, I'd like to merge the inner-option properties, not just overwrite fb1 with fb2's new values.
I'm wondering if there is a good approach to merge these two values together in a way which requires minimal code. My gut feeling tells me to try to use the unapply method on the case class to return a tuple, iterate over and combine the tuples into a new tuple, and then apply the tuple back to a case class.
Is there a more efficient way to go about doing this?
One clean way to tackle this problem is to think of your merge operation as something like addition given the right set of monoid instances. You can see my answer here for a solution to a very similar problem, but the solution is even easier now thanks to the efforts of the typelevel team. First for the case classes:
case class Foo(fooPropA: Option[String], fooPropB: Option[Int])
case class Bar(barPropA: String, barPropB: Int)
case class FooBar(name: Option[String], foo: Foo, bar: Option[Bar])
Then some boilerplate (which won't be necessary in the upcoming 2.0 release of Shapeless):
import shapeless._
implicit def fooIso = Iso.hlist(Foo.apply _, Foo.unapply _)
implicit def barIso = Iso.hlist(Bar.apply _, Bar.unapply _)
implicit def fooBarIso = Iso.hlist(FooBar.apply _, FooBar.unapply _)
I'm going to cheat just a little for the sake of clarity and put the "second" monoid instance for Option into scope instead of using tags:
import scalaz._, Scalaz._
import shapeless.contrib.scalaz._
implicit def optionSecondMonoid[A] = new Monoid[Option[A]] {
val zero = None
def append(a: Option[A], b: => Option[A]) = b orElse a
}
And we're done:
scala> val fb1 = FooBar(Some("1"), Foo(Some("A"), None), Some(Bar("A", 4)))
fb1: FooBar = FooBar(Some(one),Foo(Some(propA),None),Some(Bar(propA,4)))
scala> val fb2 = FooBar(None, Foo(Some("updated"), Some(2)), None)
fb2: FooBar = FooBar(None,Foo(Some(updated),Some(2)),None)
scala> fb1 |+| fb2
res0: FooBar = FooBar(Some(1),Foo(Some(updated),Some(2)),Some(Bar(A,4)))
See my previous answer for some additional discussion.
My previous answer used Shapeless 1.2.4, Scalaz, and shapeless-contrib, and Shapeless 1.2.4 and shapeless-contrib are pretty outdated at this point (over two years later), so here's an updated answer using Shapeless 2.2.5 and cats 0.3.0. I'll assume a build configuration like this:
scalaVersion := "2.11.7"
libraryDependencies ++= Seq(
"com.chuusai" %% "shapeless" % "2.2.5",
"org.spire-math" %% "cats" % "0.3.0"
)
Shapeless now includes a ProductTypeClass type class that we can use here. Eventually Miles Sabin's kittens project (or something similar) is likely to provide this kind of thing for cats's type classes (similar to the role that shapeless-contrib played for Scalaz), but for now just using ProductTypeClass isn't too bad:
import algebra.Monoid, cats.std.all._, shapeless._
object caseClassMonoids extends ProductTypeClassCompanion[Monoid] {
object typeClass extends ProductTypeClass[Monoid] {
def product[H, T <: HList](ch: Monoid[H], ct: Monoid[T]): Monoid[H :: T] =
new Monoid[H :: T] {
def empty: H :: T = ch.empty :: ct.empty
def combine(x: H :: T, y: H :: T): H :: T =
ch.combine(x.head, y.head) :: ct.combine(x.tail, y.tail)
}
val emptyProduct: Monoid[HNil] = new Monoid[HNil] {
def empty: HNil = HNil
def combine(x: HNil, y: HNil): HNil = HNil
}
def project[F, G](inst: => Monoid[G], to: F => G, from: G => F): Monoid[F] =
new Monoid[F] {
def empty: F = from(inst.empty)
def combine(x: F, y: F): F = from(inst.combine(to(x), to(y)))
}
}
}
And then:
import cats.syntax.semigroup._
import caseClassMonoids._
case class Foo(fooPropA: Option[String], fooPropB: Option[Int])
case class Bar(barPropA: String, barPropB: Int)
case class FooBar(name: Option[String], foo: Foo, bar: Option[Bar])
And finally:
scala> val fb1 = FooBar(Some("1"), Foo(Some("A"), None), Some(Bar("A", 4)))
fb1: FooBar = FooBar(Some(1),Foo(Some(A),None),Some(Bar(A,4)))
scala> val fb2 = FooBar(None, Foo(Some("updated"), Some(2)), None)
fb2: FooBar = FooBar(None,Foo(Some(updated),Some(2)),None)
scala> fb1 |+| fb2
res0: FooBar = FooBar(Some(1),Foo(Some(Aupdated),Some(2)),Some(Bar(A,4)))
Note that this combines values inside of Some, which isn't exactly what the question asks for, but is mentioned by the OP in a comment on my other answer. If you want the replacing behavior you can define the appropriate Monoid[Option[A]] as in my other answer.
Using Kittens 1.0.0-M8, we're now able to derive a Semigroup (I thought it was enough for this example, but Monoid is a simply import away) without boilerplate at all:
import cats.implicits._
import cats.derived._, semigroup._, legacy._
case class Foo(fooPropA: Option[String], fooPropB: Option[Int])
case class Bar(barPropA: String, barPropB: Int)
case class FooBar(name: Option[String], foo: Foo, bar: Option[Bar])
val fb1 = FooBar(Some("1"), Foo(Some("A"), None), Some(Bar("A", 4)))
val fb2 = FooBar(None, Foo(Some("updated"), Some(2)), None)
println(fb1 |+| fb2)
Yields:
FooBar(Some(1),Foo(Some(Aupdated),Some(2)),Some(Bar(A,4)))
What would be the best and/or easiest way to extract a value that I've saved in a case class?
take for example the following code:
abstract class Something
case class Foo(input: Int) extends Something
case class Bar(input: Double) extends Something
def someMethod(a: Something, b: Something) {
// code that extracts values goes here
}
someMethod(Foo(10), Foo(20))
someMethod(Bar(2.1), Bar(21.2))
how would I then go about getting the integer or the double itself out of a and b when I call the method like I did under its definition?
Note that both the parameters are used in the same equation
In case classes constructor arguments are vals, so just call:
a.input
b.input
You can also use extractor with the help of unapply method:
val Foo(val1) = a
val Bar(val2) = b
and then use val1 and val2
Update
Then you should use pattern matching on your value:
value match {
case Foo(val1) => val1
case Bar(val1) => val1
}
It works just like val Foo(val1) = a, with using generated unapply method (extractor) in your class, and it is also an expression, so you van assign the result to the variable
If you have multiple arguments just change PatMat construct according to the number of your parameters, in your case:
someMethod(a: Something, b: Something) = (a, b) match {
case (Foo(v1), Foo(v2)) => (v1, v2) // or any other logic with values
case (Foo(v1), Bar(v2)) => // logic for this case
... // logic for other cases
}
The more parameters the more cases you should provide, but you case blank cases if you don't need them
someMethod(a: Something, b: Something) = (a, b) match {
case (Foo(v1), Foo(v2)) => (v1, v2) // or any other logic with values
case _ =>
}
in this case all other cases will be ignored, not the best choice, cause the result type will be incorrect. And you also can black values
someMethod(a: Something, b: Something) = (a, b) match {
case (Foo(v1), _) => v1 // in such case you can work only with v1
... // logic for other cases
}
An alternative to pattern matching could be do redefine your classes like this:
trait Something[T]{
def input:T
}
case class Foo(input: Int) extends Something[Int]
case class Bar(input: Double) extends Something[Double]
Then, any instance of Something will expose the input property. The only potential downside is that it will be of a generic type when you access it.
The alternative approach
In addition to the direct solution of pattern matching in your method, I'll try to show a somewhat more convoluted, general and functional approach to this kind of situations. Still pattern matching is the most direct and simple answer!
If you can explicitly "certify" in your interface the input accessor, you can generalize how you work with the Something class.
In code this translates to
trait Something[T] {
def input: T
}
case class Foo(input: Int) extends Something[Int]
case class Bar(input: Double) extends Something[Double]
from here you can define how to "lift" any function you like to one that works over Somethings
Let's say you have methods that takes two inputs (e.g. Ints or Doubles) and you want to operate on such inputs within one of your case classes (i.e. Foo, Bar)
//this function lift your specific input method to one that takes Somethings
def liftSomething2[T, R](f: (T, T) => R): (Something[T], Something[T]) => R =
(a, b) => f(a.input, b.input)
Let's examine this a bit: it takes a function
(T, T) => R of 2 arguments of type T and a result R
and transforms it in a
(Something[T], Something[T]) => R which takes Somethings as arguments.
Examples
//lifts a function that sums ints
scala> val sumInts = liftSomething2[Int, Int](_ + _)
sumInts: (Something[Int], Something[Int]) => Int = <function2>
//lifts a function that multiplies ints
scala> val multInts = liftSomething2[Int, Int](_ * _)
multInts: (Something[Int], Something[Int]) => Int = <function2>
//lifts a function that divides doubles
scala> val divDbl = liftSomething2[Double, Double](_ / _)
divDbl: (Something[Double], Something[Double]) => Double = <function2>
//Now some test
scala> sumInts(Foo(1), Foo(2))
res2: Int = 3
scala> multInts(Foo(4), Foo(-3))
res3: Int = -12
scala> divDbl(Bar(20.0), Bar(3.0))
res4: Double = 6.666666666666667
//You can even complicate things a bit
scala> val stringApp = liftSomething2[Int, String](_.toString + _)
stringApp: (Something[Int], Something[Int]) => String = <function2>
scala> stringApp(Foo(1), Foo(2))
res5: String = 12
All the above examples lift functions of type (T,T) => R but the "lifting" can be made for all and any argument you need
//This takes three args of different types and returns another type
// the logic doesn't change
def liftSomething3[A,B,C,R](f: (A,B,C) => R): (Something[A], Something[B], Something[C]) => R =
(a,b,c) => f(a.input, b.input, c.input)
//sums to ints and divides by a double
scala> val sumDiv = liftSomething3[Int,Int,Double,Double]((i,j,d) => (i + j) / d)
sumDiv: (Something[Int], Something[Int], Something[Double]) => Double = <function3>
scala> sumDiv(Foo(5), Foo(30), Bar(4.2))
res7: Double = 8.333333333333332
more...
All we've seen so far should be somewhat related to category theory concepts like Applicative Functors and Comonads, but I'm no expert so I encourage you to search for yourself if you feel this sort of abstractions are useful and interesting.
In your example both the a and b have specific types: Foo and Bar respectively. That's why you can simply access their fields like so:
scala> a.input
res4: Int = 10
scala> b.input
res5: Double = 25.1
If however your value has type Something, then you'll need to pattern-match:
val input = somethingOfTypeSomething match {
case Foo(input) => input
case Bar(input) => input
}
The other answers have covered the basic scenario. There are useful variations to consider.
Constructor Pattern
As already answered there is:
value match {
case Foo(x) => x
...
}
Deep Matching
The constructor pattern also supports deep matching. For example, extract x within Bar within Foo which is 3 levels deep:
value match {
case Foo(y, Bar(x)) => x
...
}
Variable Binding
If the value you want to extract is an actual case class inside another case class you can use variable binding. E.g. to extract the whole Bar(x) into b:
value match {
case Foo(y, b # Bar(x)) => b
...
}
Programming in Scala by M. Odersky, Spoon and Venners has a great chapter on case classes and pattern matching which covers many other scenarios. Pattern matching is such a rich part of the language it would be a worthwhile investment.
Given:
case class Thing(a:Int, b:String, c:Double)
val v = Vector(1, "str", 7.3)
I want something that will magically create:
Thing(1, "str", 7.3)
Does such a thing exist (for arbitrary size Things)?
My first time dipping my toes into the 2.10 experimental reflection facilities. So mostly following this outline http://docs.scala-lang.org/overviews/reflection/overview.html, I came up with this:
import scala.reflect.runtime.{universe=>ru}
case class Thing(a: Int, b: String, c: Double)
object Test {
def main(args: Array[String]) {
val v = Vector(1, "str", 7.3)
val thing: Thing = Ref.runtimeCtor[Thing](v)
println(thing) // prints: Thing(1,str,7.3)
}
}
object Ref {
def runtimeCtor[T: ru.TypeTag](args: Seq[Any]): T = {
val typeTag = ru.typeTag[T]
val runtimeMirror = ru.runtimeMirror(getClass.getClassLoader)
val classSymbol = typeTag.tpe.typeSymbol.asClass
val classMirror = runtimeMirror.reflectClass(classSymbol)
val constructorSymbol = typeTag.tpe.declaration(ru.nme.CONSTRUCTOR).asMethod
val constructorMirrror = classMirror.reflectConstructor(constructorSymbol)
constructorMirrror(args: _*).asInstanceOf[T]
}
}
Note that when I had the case class inside the main method, this did not compile. I don't know if type tags can only be generated for non-inner case classes.
I don't know if it's possible to get a working solution with a compile-time error, but this is my solution using matching:
case class Thing(a: Int, b: String, c: Double)
def printThing(t: Thing) {
println(t.toString)
}
implicit def vectToThing(v: Vector[Any]) = v match {
case (Vector(a: Int, b: String, c: Double)) => new Thing(a, b, c)
}
val v = Vector(1, "str", 7.3) // this is of type Vector[Any]
printThing(v) // prints Thing(1,str,7.3)
printThing(Vector(2.0, 1.0)) // this is actually a MatchError
Is there an actual purpose to this "Thing"-conversion or would you rather use Tuple3[Int,String,Double] instead of Vector[Any]?
From your question it's not clear what you will use it for. What you call a Thing might actually be a HList or a KList. HList stands for Heterogeneous Lists which is an "arbitrary-length tuple".
I am unsure how hard it would be to add an 'unnapply' or 'unapplySeq' method in order for it to behave more like a case class.
I have little experience with them, but a good explanation can be found here: http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala/
If this is not what you need it might be a good idea to tell us what you want to achieve.