Scala untyped macro in infix position - scala

In response to this question, I've been having a go at implementing a Haskell-style 'where' expression in Scala using the macro-paradise branch. The code is available at scala-where. I can now write something like the following:
val result = where ( f1(1) * f2(2), {
def f1(x : Int) = x + 1
def f2(x : Int) = x + 2
})
However, what I'd really like to do is to be able to call this in infix position:
val result = ( f1(1) * f2(2)) where {
def f1(x : Int) = x + 1
def f2(x : Int) = x + 2
}
Normally, this sort of thing would be easy, but I can't see how to do it with the macro call. The expression (f1(1) * f2(2)) won't type before macro application, so something like building an implicit value class doesn't work. Is there a way to get this kind of syntax otherwise?
Failing this, just having two parameter lists so one could do:
val result = where (f1(1) * f2(2)) {
def f1(x : Int) = x + 1
def f2(x : Int) = x + 2
}
would be nice, but again this seems difficult. Can one call a macro with two parameter lists?

For the first option: I would think you could make the implicit conversion an untyped macro itself, no?
For the second option: You can call a macro with multiple parameter lists, yes. Multiple lists at the call site will translate to multiple lists at the definition site, e.g.:
def myMacro(a: _)(b: _) = macro myMacro_impl
def myMacro_impl(c: Context)(a: c.Tree)(b: c.Tree): c.Tree = { ... }
Would be called as:
myMacro(...)(...)

Answer: as of 2013-03-08 it is not possible to use untyped macros in an infix position. Quoted from Eugene Burmako on the scala-user mailing list:
Currently the argument on the left has to be typechecked first before
any implicit resolution kicks in. The fact that you can write "class
foo(x: _)" is an oversight - the underscore syntax is supposed to be
working only in untyped macros.
For reference, the closest I came to being able to do this was the following:
implicit class HasWhere(val exp : _) {
def where(block : Unit) = macro whereInfix
}
def whereInfix(c : Context)(block : c.Expr[Unit]) = {
import c.universe._
val exp = Select(c.prefix.tree, TermName("exp"))
val Expr(Block((inner, _))) = block
val newinner = inner :+ exp
Block(newinner : _*)
}

Related

Found Unit, required Int

I have the following Scala code:
object Solution {
def getBestSolution(sumList: List[Int]): Int = {
return 0
}
def main(args: Array[String]) {
val t = readInt()
(0 until t).foreach({
val n = readInt()
val a = readLine().split(" ").map(_.toInt).toList
val sumList = a.scanLeft(0)(_ + _).tail.toList
//println(classOf[sumList])
println(sumList)
println(getBestSolution(sumList))
})
}
}
For it, I am getting this error:
file.scala:16: error: type mismatch;
found : Unit
required: Int => ?
println(getBestSolution(sumList))
^
one error found
Any idea what is causing this?
The argument you are passing to foreach is the result of executing the code block (which is a Unit), not a function.
Remove the outer parentheses (they do not really hurt anything, but are unnecessary and look ugly), and add _ => in the beginning:
(0 to t).foreach { _ =>
...
println(getBestSolution(sumList))
}
This is the proper syntax for creating an unnamed function. The stuff before => is the parameter list that the function accepts. In your case, you can just put an underscore there, because you do not need the value of the parameter. Or you could give it a name if you needed to do something with it, e.g.: (0 to t).foreach { x => println(x*x) }
you could have done it with simple for comprehension too instead of foreach
for(x <- 0 to t){
val n = readInt()
val a = readLine().split(" ").map(_.toInt).toList
val sumList = a.scanLeft(0)(_ + _).tail.toList
//println(classOf[sumList])
println(sumList)
println(getBestSolution(sumList))
}
To sum up, Programming in Scala book has pointed that Scala provides the for comprehension, which provides syntactically pleasing nesting of map, flatMap, and filter ... The for comprehension is not a looping construct, but is a syntactic construct the compiler reduces to map, flatMap, and filter.

Cats Writer Vector is empty

I wrote this simple program in my attempt to learn how Cats Writer works
import cats.data.Writer
import cats.syntax.applicative._
import cats.syntax.writer._
import cats.instances.vector._
object WriterTest extends App {
type Logged2[A] = Writer[Vector[String], A]
Vector("started the program").tell
val output1 = calculate1(10)
val foo = new Foo()
val output2 = foo.calculate2(20)
val (log, sum) = (output1 + output2).pure[Logged2].run
println(log)
println(sum)
def calculate1(x : Int) : Int = {
Vector("came inside calculate1").tell
val output = 10 + x
Vector(s"Calculated value ${output}").tell
output
}
}
class Foo {
def calculate2(x: Int) : Int = {
Vector("came inside calculate 2").tell
val output = 10 + x
Vector(s"calculated ${output}").tell
output
}
}
The program works and the output is
> run-main WriterTest
[info] Compiling 1 Scala source to /Users/Cats/target/scala-2.11/classes...
[info] Running WriterTest
Vector()
50
[success] Total time: 1 s, completed Jan 21, 2017 8:14:19 AM
But why is the vector empty? Shouldn't it contain all the strings on which I used the "tell" method?
When you call tell on your Vectors, each time you create a Writer[Vector[String], Unit]. However, you never actually do anything with your Writers, you just discard them. Further, you call pure to create your final Writer, which simply creates a Writer with an empty Vector. You have to combine the writers together in a chain that carries your value and message around.
type Logged[A] = Writer[Vector[String], A]
val (log, sum) = (for {
_ <- Vector("started the program").tell
output1 <- calculate1(10)
foo = new Foo()
output2 <- foo.calculate2(20)
} yield output1 + output2).run
def calculate1(x: Int): Logged[Int] = for {
_ <- Vector("came inside calculate1").tell
output = 10 + x
_ <- Vector(s"Calculated value ${output}").tell
} yield output
class Foo {
def calculate2(x: Int): Logged[Int] = for {
_ <- Vector("came inside calculate2").tell
output = 10 + x
_ <- Vector(s"calculated ${output}").tell
} yield output
}
Note the use of for notation. The definition of calculate1 is really
def calculate1(x: Int): Logged[Int] = Vector("came inside calculate1").tell.flatMap { _ =>
val output = 10 + x
Vector(s"calculated ${output}").tell.map { _ => output }
}
flatMap is the monadic bind operation, which means it understands how to take two monadic values (in this case Writer) and join them together to get a new one. In this case, it makes a Writer containing the concatenation of the logs and the value of the one on the right.
Note how there are no side effects. There is no global state by which Writer can remember all your calls to tell. You instead make many Writers and join them together with flatMap to get one big one at the end.
The problem with your example code is that you're not using the result of the tell method.
If you take a look at its signature, you'll see this:
final class WriterIdSyntax[A](val a: A) extends AnyVal {
def tell: Writer[A, Unit] = Writer(a, ())
}
it is clear that tell returns a Writer[A, Unit] result which is immediately discarded because you didn't assign it to a value.
The proper way to use a Writer (and any monad in Scala) is through its flatMap method. It would look similar to this:
println(
Vector("started the program").tell.flatMap { _ =>
15.pure[Logged2].flatMap { i =>
Writer(Vector("ended program"), i)
}
}
)
The code above, when executed will give you this:
WriterT((Vector(started the program, ended program),15))
As you can see, both messages and the int are stored in the result.
Now this is a bit ugly, and Scala actually provides a better way to do this: for-comprehensions. For-comprehension are a bit of syntactic sugar that allows us to write the same code in this way:
println(
for {
_ <- Vector("started the program").tell
i <- 15.pure[Logged2]
_ <- Vector("ended program").tell
} yield i
)
Now going back to your example, what I would recommend is for you to change the return type of compute1 and compute2 to be Writer[Vector[String], Int] and then try to make your application compile using what I wrote above.

Is it possible to annotate lambda in scala?

For my dsl I need something in the spirit of:
#deprecated def foo(x: Int) = x
... only for lambdas\anonymous functions.
Is something like this possible?
Apparently this exists in the language according to the lang spec:
An annotation of an expression e appears after the expression e,
separated by a colon.
So this supposed to work:
object TestAnnotation {
val o = Some(1)
def f = o.map(_ + 1 : #deprecated("gone", "forever"))
val e = { 1 + 2 } : #deprecated("hmm", "y")
println(f)
println(e)
}
However, when I compile it with scalac -deprecation I get no warnings whatsoever. I opened an issue here and got a response that it's not supported.
One workaround you could use is to declare lambda separately:
object TestAnnotation {
val o = Some(1)
#deprecated("this", "works") val deprecatedLambda: Int => Int = _ + 1
o.map(deprecatedLambda)
}
scalac then gives:
Annotation.scala:6: warning: value deprecatedLambda in object TestAnnotation is deprecated: this
o.map(deprecatedLambda)
^
one warning found

How can I use a macro with refined return type inline?

I have a macro:
def f[T]: Any = macro fImpl[T]
def fImpl[T : context.WeakTypeTag](context: whitebox.Context):
context.Tree =
{
import context.universe._
q"{ (x: ${weakTypeOf[T]}) => x + 1 }"
}
When I use it as
f[Int](1)
I see
Error:(26, 6) Any does not take parameters
f[Int](1)
^
If I split into two statements,
val x = f[Int]
x(1)
there are no errors.
Is there a way that I can use the macro f[Int] as a function, without writing an auxiliary statement?
This is a bug, which is reported in our issue tracker at https://issues.scala-lang.org/browse/SI-7914.

Scala operator overloading with multiple parameters

In short: I try to write something like A <N B for a DSL in Scala, for an integer N and A,B of Type T. Is there a nice possibility to do so?
Longer: I try to write a DSL for TGrep2 in Scala. I'm currently interested to write
A <N B B is the Nth child of A (the rst child is <1).
in a nice way and as close as possible to the original definition in Scala. Is there a way to overload the < Operator that it can take a N and a B as a argument.
What I tried: I tried two different possibilities which did not make me very happy:
scala> val N = 10
N: Int = 10
scala> case class T(n:String) {def <(i:Int,j:T) = println("huray!")}
defined class T
scala> T("foo").<(N,T("bar"))
huray!
and
scala> case class T(n:String) {def <(i:Int) = new {def apply(j:T) = println("huray!")}}
defined class T
scala> (T("foo")<N)(T("bar"))
warning: there were 1 feature warnings; re-run with -feature for details
huray!
Id suggest you use something like nth instead of the < symbol which makes the semantics clear. A nth N is B would make a lot of sense to me at least. It would translate to something like
case class T (label:String){
def is(j:T) = {
label equals j.label
}
}
case class J(i:List[T]){
def nth(index:Int) :T = {
i(index)
}
}
You can easily do:
val t = T("Mice")
val t1 = T("Rats")
val j = J(List(t1,t))
j nth 1 is t //res = true
The problem is that apply doesn't work as a postfix operator, so you can't write it without the parantheses, you could write this:
case class T(n: String) {
def <(in: (Int, T)) = {
in match {
case (i, t) =>
println(s"${t.n} is the ${i} child of ${n}")
}
}
}
implicit class Param(lower: Int) {
def apply(t: T) = (lower, t)
}
but then,
T("foo") < 10 T("bar")
would still fail, but you could work it out with:
T("foo") < 10 (T("bar"))
there isn't a good way of doing what you want without adding parenthesis somewhere.
I think that you might want to go for a combinational parser instead if you really want to stick with this syntax. Or as #korefn proposed, you break the compatibility and do it with new operators.