Within a function passed to a scala macro, I cannot reference a variable in scope - scala

Cannot compile even if a function that handles function arguments is passed to macro.
A sample is shown below.
trait Generated[Z] {
def deserialize[A](t: A): Z
}
def from[A, Z](apl: A => Z): Generated[Z] = macro GeneratorMacro.from[A, Z]
class GeneratorMacro(val c: blackbox.Context) {
import c.universe._
def from[A: c.WeakTypeTag, Z: c.WeakTypeTag](apl: c.Expr[A => Z]): c.Expr[Generated[Z]] = {
reify {
new Generated[Z] {
def deserialize[A](t: A): Z = {
apl.splice.apply(t)
}
}
}
}
}
object Generation {
def apply(input: String): Generated[Int] = {
Generator.from[Option[String], Int] {
case Some(i) => input.toInt + i.toInt // compilation failed
case None => 0
}
}
}
An error occurs at this time.
Error: scalac: Error while emitting Generation.scala
value input
Isn't the class recompiled with the macro expanded?
If recompiled with inline expansion, no compilation error should occur.
object Generation {
def apply(input: String): Generated[Int] = {
new Generated[Int] {
def deserialize(t: String): Int = {
{
case Some(i) => input.toInt + i.toInt // input should be visible
case None => 0
}.apply(t)
}
}
}
}
What is going on and how to avoid it.

This seems to be impossible, AFAICS. The compiler creates an anonymous class for your code, but it will not capture the lexical context of the macro call inside it.
The code looks a bit like this after the lambdalift phase:
def apply(input: String): Generated[Int] = ({
new <$anon: Generated>()
}: Generated);
...
final class $anon extends Object with Generated {
def deserialize(t: Option): Int = {
... // <- your code is here !!
};
}
Of course, the code has no access to the input variable at this place.
This might be a bug in the Scala compiler...

The first error I have is
Warning:scalac: {
final class $anon extends App.this.Generated[Int] {
def <init>() = {
super.<init>();
()
};
def deserialize(t: Option[String]): Int = ((x0$1: Option[String]) => x0$1 match {
case (value: String)Some[String]((i # _)) => scala.Predef.augmentString(input).toInt.+(scala.Predef.augmentString(i).toInt)
case scala.None => 0
}).apply(t)
};
new $anon()
}
Error:(6, 43) object creation impossible. Missing implementation for:
def deserialize[A](t: A): Int // inherited from trait Generated
Generator.from[Option[String], Int] {
Obviously this is because you define
reify {
new Generated[Z] {
def deserialize(t: A): Z = {
...
instead of def deserialize[A](t: A): Z (#OlegPyzhcov pointed this out in the comments).
Regarding your error Error while emitting ... the thing is that
{
case Some(i: String) => input.toInt + i.toInt
case None => 0
}
has type not ... => ... i.e. Function1[..., ...] but actually PartialFunction[..., ...].
Try either
object Generator {
def from[Z](apl: PartialFunction[Any, Z]): Generated[Z] = macro GeneratorMacro.from[Z]
}
class GeneratorMacro(val c: blackbox.Context) {
import c.universe._
def from[Z: c.WeakTypeTag](apl: c.Expr[Any => Z]): c.Expr[Generated[Z]] = {
reify {
new Generated[Z] {
def deserialize[A](t: A): Z = {
apl.splice.apply(t)
}
}
}
}
}
Generator.from[Int]({
case Some(i: String) => input.toInt + i.toInt
case None => 0
})
or
object Generator {
def from[Z](apl: Any => Z): Generated[Z] = macro GeneratorMacro.from[Z]
}
class GeneratorMacro(val c: blackbox.Context) {
import c.universe._
def from[Z: c.WeakTypeTag](apl: c.Expr[Any => Z]): c.Expr[Generated[Z]] = {
reify {
new Generated[Z] {
def deserialize[A](t: A): Z = {
apl.splice.apply(t)
}
}
}
}
}
Generator.from[Int](new (Any => Int) {
override def apply(x: Any): Int = x match {
case Some(i: String) => input.toInt + i.toInt
case None => 0
}
})

Related

How to substitute objects in tree-like Scala case class instance with derived objects?

Suppose I have a set of case classes that represent constants, variables, and unary and binary operations on them, similar to one from "Case Classes and Pattern Matching" chapter in Programming in Scala:
abstract class Value {
def basicEvaluate(varArray: Array[Double]): Double
def evaluate(varArray: Array[Double]) = basicEvaluate(varArray)
}
case class Constant(d: Double) extends Value {
override def basicEvaluate(varArray: Array[Double]) = d
}
case class Variable(i: Int) extends Value {
override def basicEvaluate(varArray: Array[Double]) = varArray(i)
}
case class Add(v1: Value, v2: Value) extends Value {
override def basicEvaluate(varArray: Array[Double]) = v1.evaluate(varArray) + v2.evaluate(varArray)
}
...
Then, suppose I have some means to produce expression trees that reuse certain subexpressions many times, and I wish to be able to evaluate the expression efficiently, so that each distinct subexpression gets evaluated only once. For this reason, I introduce a trait
trait UsingCache extends Value {
var cached: Option[Double] = None
override def evaluate(varArray: Array[Double]) = {
if (cached == None) {
cached = Some(basicEvaluate(varArray))
}
cached.get
}
}
Then, I can do the following:
val expr = new Variable(0) with UsingCache
val expr2 = new Add(expr, expr) with UsingCache
expr2.evaluate(Array(5.0))
and it works.
My question is - how to implement a function def extend(value: Value): UsingCache which would recursively replace each Value in the tree with a corresponding .. with UsingCache object? I wish to keep this logic decoupled from the individual subclasses of Value (e.g., when I add a new operation, it shouldn't contain any code specific for caching). Is there some way to do this using implicit conversion? Or some ideas how to use Scala reflection (I'm using Scala 2.12)?
Try macro
def extend(value: Value): UsingCache = macro extendImpl
def extendImpl(c: blackbox.Context)(value: c.Tree): c.Tree = {
import c.universe._
def transformExprss(exprss: Seq[Seq[Tree]]): Seq[Seq[Tree]] =
exprss.map(_.map(expr => if (expr.tpe <:< typeOf[Value]) q"extend($expr)" else expr))
value match {
case q"$expr.$tname.apply(...$exprss)" =>
val exprss1 = transformExprss(exprss)
q"new $expr.${tname.toTypeName}(...$exprss1) with UsingCache"
case q"${tname: TermName}.apply(...$exprss)" =>
val exprss1 = transformExprss(exprss)
q"new ${tname.toTypeName}(...$exprss1) with UsingCache"
}
}
extend(Add(Constant(1.0), Variable(2)))
//Warning:scalac: performing macro expansion App.extend(App.Add.apply(App.Constant.apply(1.0), App.Variable.apply(2))) at ...
//Warning:scalac: {
// final class $anon extends App.Add(extend(App.Constant.apply(1.0)), extend(App.Variable.apply(2))) with UsingCache {
// def <init>() = {
// super.<init>();
// ()
// }
// };
// new $anon()
//}
//Warning:scalac: performing macro expansion App.extend(App.Constant.apply(1.0)) at ...
//Warning:scalac: {
// final class $anon extends App.Constant(1.0) with UsingCache {
// def <init>() = {
// super.<init>();
// ()
// }
// };
// new $anon()
//}
//Warning:scalac: performing macro expansion App.extend(App.Variable.apply(2)) at ...
//Warning:scalac: {
// final class $anon extends App.Variable(2) with UsingCache {
// def <init>() = {
// super.<init>();
// ()
// }
// };
// new $anon()
//}
Here is a solution that uses a stack to do a depth-first traversal. It is tail call optimized, so will not suffer from stack overflow. The OP also asked that old cached values be reused, so a map is used for memoization.
object CachedValueTest2 {
def main(args: Array[String]) = {
val expr1 = Add(Add(Constant(1), Add(Variable(1), Constant(1))), Add(Constant(2), Constant(2)))
println(extend(expr1))
val expr2 = Add(Add(Constant(1), Add(Add(Variable(2), Constant(1)), Constant(1))), Add(Constant(2), Add(Variable(1), Constant(2))))
println(extend(expr2))
}
def extend(value: Value): UsingCache = {
def replace(input: Value, stack: List[(Add, Option[UsingCache], Option[UsingCache])], map: Map[Value, UsingCache]): UsingCache = {
input match {
case in # Constant(d) =>
val (v, newMap) = map.get(in) match {
case Some(entry) => (entry, map)
case None =>
val entry = new Constant(d) with UsingCache
(entry, map + (in -> entry))
}
popStack(v, stack, newMap)
case in # Variable(i) =>
val (v, newMap) = map.get(in) match {
case Some(entry) => (entry, map)
case None =>
val entry = new Variable(i) with UsingCache
(entry, map + (in -> entry))
}
popStack(v, stack, newMap)
case in # Add(v1, v2) =>
map.get(in) match {
case Some(entry) => entry
case None => replace(v1, (in, None, None) :: stack, map)
}
}
}
def popStack(input: UsingCache, stack: List[(Add, Option[UsingCache], Option[UsingCache])], map: Map[Value, UsingCache]): UsingCache = {
stack match {
case head :: tail =>
head match {
case (add, None, None) =>
replace(add.v2, (add, Some(input), None) :: tail, map)
case (add, Some(v1), None) =>
val v = new Add(v1, input) with UsingCache
val newMap = map + (add -> v)
popStack(v, tail, newMap)
}
case Nil => input
}
}
replace(value, List(), Map())
}
abstract class Value {
def basicEvaluate(varArray: Array[Double]): Double
def evaluate(varArray: Array[Double]) = basicEvaluate(varArray)
}
case class Constant(d: Double) extends Value {
override def basicEvaluate(varArray: Array[Double]) = d
}
case class Variable(i: Int) extends Value {
override def basicEvaluate(varArray: Array[Double]) = varArray(i)
}
case class Add(v1: Value, v2: Value) extends Value {
override def basicEvaluate(varArray: Array[Double]) = v1.evaluate(varArray) + v2.evaluate(varArray)
}
trait UsingCache extends Value {
var caches : Map[Array[Double], Double] = Map()
override def evaluate(varArray: Array[Double]) = {
caches.get(varArray) match {
case Some(result) =>
result
case None =>
val result = basicEvaluate(varArray)
caches = caches + (varArray -> result)
result
}
}
}
}

How to get Left from a method that returns Future?

def myMethod(myType: String) :Future[Future[Either[List[MyError], MyClass]]] {
for {
first <- runWithSeq(firstSource)
}
yield {
runWithSeq(secondSource)
.map {s ->
val mine = MyClass(s.head, lars)
val errors = myType match {
case "all" => Something.someMethod(mine)
}
(s, errors)
}
.map { x =>
x._2.leftMap(xs => {
addInfo(x._1.head, xs.toList)
}).toEither
}
}
}
for {
myStuff <- myMethod("something")
} yield {
myStuff.collect {
case(Left(errors), rowNumber) =>
MyCaseClass(errors, None) //compilation error here
}
}
I get compilation error on MyCaseClass that expected: List[MyError], found: Any
The signature of MyCaseClass is:
case class MyCaseClass(myErrors: List[ValidationError])
How can I fix this such that I can correctly call MyCaseClass inside the yield?
Your code example doesn't make much sense, and doesn't compile, but if runWithSeq() returns a Future then you should be able to eliminate the double Future return type like so.
for {
_ <- runWithSeq(firstSource)
scnd <- runWithSeq(secondSource)
} yield { ...
Your example is pretty hard to paste and fix
Abstact example for this
Class C may be whatever you want
def test(testval: Int)(implicit ec: ExecutionContext): Future[Future[Either[String, Int]]] = {
Future(Future{
if (testval % 2 == 0) Right(testval) else Left("Smth wrong")
})
}
implicit class FutureEitherExt[A, B](ft: Future[Either[A, B]]) {
def EitherMatch[C](f1: A => C, f2: B => C)(implicit ec: ExecutionContext): Future[C] = {
ft.map {
case Left(value) => f1(value)
case Right(value) => f2(value)
}
}
}
val fl: Future[Either[String, Int]] = test(5).flatten
val result: Future[String] = fl.EitherMatch(identity, _.toString)

Combine two functions under the same name without overloading

Here is the code:
def transform1(f: String => String): Unit = {
val s = getString
f.andThen(putString)(s)
}
def transform2(f: String => Option[String]): Unit = {
val s = getString
f(s).foreach(putString(_))
}
How do you express these two ideas in one single function?
Method overloading does not work and seems discouraged by the community.
I didn't understand that why anyone may want this but here is a way to do it:
def transform(f: Either[(String => String), (String => Option[String])]: Unit = f match {
case Left(f) => // do transform1 here
case Right(f) => //do transform2 here
}
As I said at the begining you probably shouldn't want to do this; perhaps you should directly ask what you want.
The pattern to avoid overloading is to convert disparate arguments to a common, specific type. There could be any number of such conversions.
Not sure this is the most compelling example, however.
object X {
trait MapFlat[-A, +B] { def apply(x: A): B }
implicit class mapper[A](val f: A => A) extends MapFlat[A, A] {
override def apply(x: A) = {
val res = f(x)
println(res)
res
}
}
implicit class flatmapper[A](val f: A => Option[A]) extends MapFlat[A, Option[A]] {
override def apply(x: A) = {
val res = f(x)
res foreach println
res
}
}
def f[B](g: MapFlat[String, B]) = {
g("abc")
}
}
object Test extends App {
import X._
f((s: String) => s)
f((s: String) => Some(s))
}
One way to do it will be type classes, here's a sample -
trait Transformer[T] {
def transform(foo: String => T)
}
object Transformer {
implicit object StringTransformer extends Transformer[String] {
override def transform(foo: (String) => String): Unit = ??? // Your logic here
}
implicit object OptStringTransformer extends Transformer[Option[String]] {
override def transform(foo: (String) => Option[String]): Unit = ??? // Your logic here
}
}
class SampleClass {
def theOneTransformYouWant[T: Transformer](f: String => T) = {
implicitly[Transformer[T]].transform(f)
}
def canUseBothWays(): Unit = {
theOneTransformYouWant((s: String) => s)
theOneTransformYouWant((s: String) => Some(s))
}
}
Another way would be the magnet pattern
http://spray.io/blog/2012-12-13-the-magnet-pattern/
sealed trait TransformationMagnet {
def apply(): Unit
}
object TransformationMagnet {
implicit def fromString(f: String => String): TransformationMagnet =
new TransformationMagnet {
def apply(): Unit = ??? // Your code goes here
}
implicit def fromOptString(f: String => Option[String]): TransformationMagnet =
new TransformationMagnet {
def apply(): Unit = ??? // your code goes here
}
}
class SampleClass {
def theOneTransformYouWant(f: TransformationMagnet) = {
???
}
def hereWeUseItInBothWays(): Unit = {
theOneTransformYouWant((s: String) => s)
theOneTransformYouWant((s: String) => Some(s))
}
}
add a new parameter on the description typeOfTransform
add a conditional inside the function
if (typeOfTransform == type1){
//functionality1
}else {
//functionality2
}
Just for completeness, you can actually overload methods like this by adding implicit arguments which will always be available:
def transform(f: String => Option[String]): Unit = ...
def transform(f: String => String)(implicit d: DummyImplicit): Unit = ...

How to create a method which invokes another service and return a Future?

I want to define a method, which will return a Future. And in this method, it will call another service which returns also a Future.
We have defined a BusinessResult to represent Success and Fail:
object validation {
trait BusinessResult[+V] {
def flatMap[T](f: V => BusinessResult[T]):BusinessResult[T]
def map[T](f: V => T): BusinessResult[T]
}
sealed case class Success[V](t:V) extends BusinessResult[V] {
def flatMap[T](f: V => BusinessResult[T]):BusinessResult[T] = {
f(t)
}
def map[T](f: V => T): BusinessResult[T] = {
Success(f(t))
}
}
sealed case class Fail(e:String) extends BusinessResult[Nothing] {
def flatMap[T](f: Nothing => BusinessResult[T]):BusinessResult[T] = this
def map[T](f: Nothing => T): BusinessResult[T] = this
}
}
And define the method:
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import validation._
def name: BusinessResult[String] = Success("my name")
def externalService(name:String):Future[String] = future(name)
def myservice:Future[Int] = {
for {
n <- name
res <- externalService(n)
} yield res match {
case "ok" => 1
case _ => 0
}
}
But which is not compilable. The code in myservice can't return a Future[Int] type.
I also tried to wrap the name with Future:
def myservice:Future[Int] = {
for {
nn <- Future.successful(name)
n <- nn
res <- externalService(n)
} yield res match {
case "ok" => 1
case _ => 0
}
}
Which is also not compilable.
I know there must be a lot of issues in this code. How can I adjust them to make it compilable?
If you change the n with some hardcoded string it works, the problem is that in the for comprehension the variable n has type BusinessResult[String], as you probably already know for comprehension desugarize to map, flatMap and filter so the first part n <- name desugarize to a map on name:
val test: BusinessResult[String] = name.map(x => x)
Intellij thinks n is a String but the scala compiler disagree:
type mismatch;
[error] found : validation.BusinessResult[Nothing]
[error] required: scala.concurrent.Future[Int]
[error] n <- name
[error] ^
Easy solution could be to add a getter method to get back the string and do something like Option does:
object validation {
trait BusinessResult[+V] {
def flatMap[T](f: V => BusinessResult[T]):BusinessResult[T]
def map[T](f: V => T): BusinessResult[T]
def getVal: V
}
sealed case class Success[V](t:V) extends BusinessResult[V] {
def flatMap[T](f: V => BusinessResult[T]):BusinessResult[T] = {
f(t)
}
def map[T](f: V => T): BusinessResult[T] = {
Success(f(t))
}
def getVal: V = t
}
sealed case class Fail(e:String) extends BusinessResult[Nothing] {
def flatMap[T](f: Nothing => BusinessResult[T]):BusinessResult[T] = this
def map[T](f: Nothing => T): BusinessResult[T] = this
def getVal = throw new Exception("some message")
}
}
def myservice: Future[Int] = {
val value = name.getVal
for {
res <- externalService(value)
} yield res match {
case "ok" => 1
case _ => 0
}
}
Note that you can't extract the name in the for comprehension since map on String return Chars

Scala, method call compiles with dot, doesn't compile without

For the purposes of self-torture I have been trying to write my own implementation of if-elseif-else construct (when-butWhen-otherwise in my case). The funny thing is that the thing that I have written doesn't compile without a dot before butWhen, and does compile with it, and it compiles both with and without the dot before otherwise:
when(false) {
println(">> True")
}.butWhen(false) {
println(">> hello")
}.butWhen(false) { // Without the dot says "Boolean(false) does not take parameters"
println(">> Goodbye")
} otherwise {
println(">> Something else")
}
To my untrained eye, the declarations of both butWhen and otherwise are the same, they return the same thing, so it seems they must behave the same. Also, when I chain the otherwise directly to the when clause, the compilation succeeds without the dot, too.
Could you help me get rid of the dot? Below is the code for the when-butWhen-otherwise:
trait ButWhenTrait {
def butWhen(b: Boolean)(op3: => Unit): ButWhenTrait
def otherwise(op2: => Unit) // {}
}
object when {
def apply(b: Boolean)(op: => Unit): ButWhenTrait = {
if (b) {
op
DeadEnd
} else FalseWhen
}
}
object FalseWhen extends ButWhenTrait {
override def otherwise(op2: => Unit) { op2 }
override def butWhen(b: Boolean)(op2: => Unit) = {
if (b) {
op2
DeadEnd
} else {
FalseWhen
}
}
}
object DeadEnd extends ButWhenTrait {
override def otherwise(op: => Unit) {}
override def butWhen(b: Boolean)(op: => Unit) = { DeadEnd }
}
Error caused by the next limitations: Suffix Notation for Method Invocation is posible only for Arity-0 & Arity-1 methods.
Possible solutions:
1) reduce method arity by splitting call to 2 objects:
-- UPDATED (error fixed) --
trait ButWhenTrait {
def butWhen(b: Boolean): ExecBlock
def otherwise(op: => Unit): Unit
}
trait ExecBlock {
// $ name of method for transfer execution function
def $(op : => Unit): ButWhenTrait
}
object NextExecBlock extends ExecBlock {
object next extends ButWhenTrait {
def butWhen(b: Boolean): ExecBlock = if(b) EndExecBlock else NextExecBlock
def otherwise(op: => Unit) { op }
}
def $(op : => Unit): ButWhenTrait = next
}
trait EmptyButWhenTrait {
object next extends ButWhenTrait {
def otherwise(op : => Unit) {}
def butWhen(b : Boolean) = EmptyExecBlock
}
}
object EndExecBlock extends ExecBlock with EmptyButWhenTrait {
def $(op : => Unit): ButWhenTrait = { op; next }
}
object EmptyExecBlock extends ExecBlock with EmptyButWhenTrait {
def $(op : => Unit): ButWhenTrait = next
}
object when {
def apply(b: Boolean)(op: => Unit): ButWhenTrait =
if(b) EndExecBlock $ op else NextExecBlock $ op
}
than usage:
when(false) {
println(">> True")
} butWhen(false) $ {
println(">> hello")
} butWhen(false) $ {
println(">> Goodbye")
} otherwise {
println(">> Something else")
}
2) with implicit convesrions for boolean to object with apply method:
trait ButWhenTrait {
def butWhen(op : ButWhenTrait): ButWhenTrait = op
def otherwise(op: => Unit) { op }
}
class ExecBlock(b : Boolean) {
private object next extends ButWhenTrait
private object end extends ButWhenTrait {
override def butWhen(op : ButWhenTrait) = end
override def otherwise(op : => Unit) {}
}
def apply(op : => Unit): ButWhenTrait = if(b) { op; end } else next
}
object when {
def apply(b: Boolean)(op: => Unit): ButWhenTrait = new ExecBlock(b)(op)
}
// AND implicit conversion:
implicit def boolToExec(b : Boolean): ExecBlock = new ExecBlock(b)
than usage (as you expected):
when(false) {
println(">> True")
} butWhen(false) {
println(">> hello")
} butWhen(false) {
println(">> Goodbye")
} otherwise {
println(">> Something else")
}