In a scala macro called with an implicit def, how can I get the source statement of the caller to the implicit def as a string? - scala

I'm trying to write an implicit def macro that captures the invoking statement (and preferably nothing else) as a string, that can hopefully be used just by having the desired output object as an implicit parameter. But I'm having some trouble getting it to work with multi line statements.
For example:
case class HowWasICalled(statement:String, lineNumber:Int)
object HowWasICalled {
implicit def generate: HowWasICalled = macro macro_impl
}
def callMe(something: Any)(implicit context: HowWasICalled)
// macro: c is the blackbox Context
def macro_impl(c: blackbox.Context): c.Expr[HowWasICalled] = { ... }
And the first attempt at implementing a method inside the macro that returns the invoking statement as a string:
def makeString:String = show(c.macroApplication)
But, this only returned "HowWasICalled.generate". I actually wanted the statement invoking callMe.
I was hoping the following would work, but it doesn't. The -Yrangepos compiler flag does not seem to result in range positions in def macros? :(
def makeString:String = {
if (c.enclosingPosition.isRange) {
new String(c.enclosingPosition.source.content.slice(
c.enclosingPosition.start,
c.enclosingPosition.end
))
}
}
The closest I got to any working implementation doesn't exactly capture just statement nor the entire statement, but at least I get the line of source invoking callMe.
def makeString:String = {
val lineNumber = c.enclosingPosition.line
val lineIndex = lineNumber-1
c.enclosingPosition.source.lineToString(lineIndex)
}
How can I improve the macro to handle the following case? It should ideally generate something like a HowIWasCalled("callMe( 1 + 2 )", 123) given the following input
0; 0; 0; val x = callMe(1 +
2)

Related

Sum of list element in scala is not executable : error. How to fix?

I am not able to execute or **▶ button is not clickable in intelleiJ ** the sum function in following two ways. Please help me to identify the mistakes in both.
object Main{
def sum1(xs : List[Int]): Int = {
xs.filter(_ > 0).sum // am i missing return word here ?
}
def sum2(xs: List[Int]): Unit = {
val mx = xs.filter(_ > 0).sum // is it ok to have return in a variable ?
println(mx)
}
Main.sum1(List(1,2))
Main.sum2(List(1,2,3,4))
}
For Intellij, unless you code from within a Scala Worksheet where you can execute execute code without an entry point, in any normal application, you require an entry point to your application.
In Scala 2 you can do this in 2 ways. Either define the main method yourself inside an object definition, which is the conventional way:
object Main {
def main(args: Array[String]): Unit = {
// code here
}
}
Or - have your object definition extend the App trait, which provides the main method for you, so you can start writing code directly inside:
object Main extends App {
// code here
}
This is a bit cleaner, and one nested-levels less.
In Scala, statements are called expressions, because they generally return the value of the last expression, if the last expression is not an assignment. This code:
def sum1(xs: List[Int]): Int =
xs.filter(_ > 0).sum
Is a syntactic sugar for this:
def sum1(xs: List[Int]): Int = {
return xs.filter(_ > 0).sum
}
Because braces are optional if the code has only 1 expression, and will return the value of the last expression by default. So even though you can write code both ways, you'll get the warning Return keyword is redundant, because you'll never need to use it explicitly.
Also, you don't need to write Main.sum1(...) from within Main. You can omit the object:
object Main extends App {
def sum1(xs: List[Int]): Int =
xs.filter(_ > 0).sum
def sum2(xs: List[Int]): Unit = {
val mx = xs.filter(_ > 0).sum
println(mx) // 10
}
println(sum1(List(1, 2))) // 3
sum2(List(1, 2, 3, 4))
}
For Scala 3, things get simpler. The recommended way is to annotate a method with the #main annotation to mark it as the entry point in your program. This method ca either be defined at the top-level, or inside an object definition, and it's name does not matter anymore:
#main def hello() =
// code here
While Scala 3 still supports the App trait from Scala 2, it has now become deprecated and it's functionality has been limited, so if your program needs to cross-build between both Scala 2 and Scala 3 versions, it’s recommended to stick with the basic way of explicitly define a main method inside an object definition with an Array[String] argument instead:
object MyMain:
def main(args: Array[String]) =
// code here
Note, curly braces become optional in Scala 3 in favor of the cleaner Python-style indentation.

Calling function library scala

I'm looking to call the ATR function from this scala wrapper for ta-lib. But I can't figure out how to use wrapper correctly.
package io.github.patceev.talib
import com.tictactec.ta.lib.{Core, MInteger, RetCode}
import scala.concurrent.Future
object Volatility {
def ATR(
highs: Vector[Double],
lows: Vector[Double],
closes: Vector[Double],
period: Int = 14
)(implicit core: Core): Future[Vector[Double]] = {
val arrSize = highs.length - period + 1
if (arrSize < 0) {
Future.successful(Vector.empty[Double])
} else {
val begin = new MInteger()
val length = new MInteger()
val result = Array.ofDim[Double](arrSize)
core.atr(
0, highs.length - 1, highs.toArray, lows.toArray, closes.toArray,
period, begin, length, result
) match {
case RetCode.Success =>
Future.successful(result.toVector)
case error =>
Future.failed(new Exception(error.toString))
}
}
}
}
Would someone be able to explain how to use function and print out the result to the console.
Many thanks in advance.
Regarding syntax, Scala is one of many languages where you call functions and methods passing arguments in parentheses (mostly, but let's keep it simple for now):
def myFunction(a: Int): Int = a + 1
myFunction(1) // myFunction is called and returns 2
On top of this, Scala allows to specify multiple parameters lists, as in the following example:
def myCurriedFunction(a: Int)(b: Int): Int = a + b
myCurriedFunction(2)(3) // myCurriedFunction returns 5
You can also partially apply myCurriedFunction, but again, let's keep it simple for the time being. The main idea is that you can have multiple lists of arguments passed to a function.
Built on top of this, Scala allows to define a list of implicit parameters, which the compiler will automatically retrieve for you based on some scoping rules. Implicit parameters are used, for example, by Futures:
// this defines how and where callbacks are run
// the compiler will automatically "inject" them for you where needed
implicit val ec: ExecutionContext = concurrent.ExecutionContext.global
Future(4).map(_ + 1) // this will eventually result in a Future(5)
Note that both Future and map have a second parameter list that allows to specify an implicit execution context. By having one in scope, the compiler will "inject" it for you at the call site, without having to write it explicitly. You could have still done it and the result would have been
Future(4)(ec).map(_ + 1)(ec)
That said, I don't know the specifics of the library you are using, but the idea is that you have to instantiate a value of type Core and either bind it to an implicit val or pass it explicitly.
The resulting code will be something like the following
val highs: Vector[Double] = ???
val lows: Vector[Double] = ???
val closes: Vector[Double] = ???
implicit val core: Core = ??? // instantiate core
val resultsFuture = Volatility.ATR(highs, lows, closes) // core is passed implicitly
for (results <- resultsFuture; result <- results) {
println(result)
}
Note that depending on your situation you may have to also use an implicit ExecutionContext to run this code (because you are extracting the Vector[Double] from a Future). Choosing the right execution context is another kind of issue but to play around you may want to use the global execution context.
Extra
Regarding some of the points I've left open, here are some pointers that hopefully will turn out to be useful:
Operators
Multiple Parameter Lists (Currying)
Implicit Parameters
Scala Futures

Return first element of array, in a def

Can you please help me understand, why the second def is not compiling, and how to write the second def for that it is compiling (return first entry of Array in one line). Thanks!
import java.awt.{GraphicsDevice, GraphicsEnvironment}
class SeparatedTestCase {
def does_compile: GraphicsDevice = {
val ge: GraphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment
val devices: Array[GraphicsDevice] = ge.getScreenDevices
devices(0)
}
def does_not_compile: GraphicsDevice = {
val ge: GraphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment
val device0: GraphicsDevice = (ge.getScreenDevices)(0) // <---- compile error
device0
}
}
//Error:(13, 59) no arguments allowed for nullary method getScreenDevices: ()Array[java.awt.GraphicsDevice]
//val device0: GraphicsDevice = (ge.getScreenDevices)(0)
You have to invoke the method with explicit parentheses:
ge.getScreenDevices()(0)
This does not compile, because your second invocation means the same as
ge.getScreenDevices(0)
which does not do what you want because getScreenDevices is a Java null-ary method which can be invoked either with parentheses or not, and if you specify one set of parentheses, Scala assumes that you want to invoke this method with these parameters, which of course won't work since it does not accept any arguments.

scala macro that refers to 'this' object

I am trying to use a macro to eliminate the need for scala to construct a downward-passed function object. This code gets used in inner-loops of our system, and we don't want the inner loop to just allocate objects endlessly. This is creating performance problems for us.
Our original code was this:
dis.withBitLengthLimit(newLimit){... body ...}
And the body was a function that was passed in as a function object.
The problem I have is that the original non-macro version refers to 'this'. My workaround below is to make each place the macro is called pass the 'this' object as another argument. i.e., ugly like:
dis.withBitLengthLimit(dis, newLimit){... body ...}
It's not awful, but sure seems like passing dis should be unnecessary.
Is there a cleaner way?
Here's the macro below.
object IOMacros {
/**
* Used to temporarily vary the bit length limit.
*
* Implementing as a macro eliminates the creation of a downward function object every time this
* is called.
*
* ISSUE: this macro really wants to use a self reference to `this`. But when a macro is expanded
* the object that `this` represents changes. Until a better way to do this comes about, we have to pass
* the `this` object to the `self` argument, which makes calls look like:
* dis.withBitLengthLimit(dis, newLimit){... body ...}
* That looks redundant, and it is, but it's more important to get the allocation of this downward function
* object out of inner loops.
*/
def withBitLengthLimitMacro(c: Context)(self: c.Tree, lengthLimitInBits: c.Tree)(body: c.Tree) = {
import c.universe._
q"""{
import edu.illinois.ncsa.daffodil.util.MaybeULong
val ___dStream = $self
val ___newLengthLimit = $lengthLimitInBits
val ___savedLengthLimit = ___dStream.bitLimit0b
if (!___dStream.setBitLimit0b(MaybeULong(___dStream.bitPos0b + ___newLengthLimit))) false
else {
try {
$body
} finally {
___dStream.resetBitLimit0b(___savedLengthLimit)
}
true
}
}"""
}
The prefix method on Context provides access to the expression that the macro method is called on, which should allow you to accomplish what you're trying to do. Here's a quick example of how you can use it:
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
class Foo(val i: Int) {
def bar: String = macro FooMacros.barImpl
}
object FooMacros {
def barImpl(c: Context): c.Tree = {
import c.universe._
val self = c.prefix
q"_root_.scala.List.fill($self.i + $self.i)(${ self.tree.toString }).mkString"
}
}
And then:
scala> val foo = new Foo(3)
foo: Foo = Foo#6fd7c13e
scala> foo.bar
res0: String = foofoofoofoofoofoo
Note that there are some issues you need to be aware of. prefix gives you the expression, which may not be a variable name:
scala> new Foo(2).bar
res1: String = new Foo(2)new Foo(2)new Foo(2)new Foo(2)
This means that if the expression has side effects, you have to take care not to include it in the result tree more than once (assuming you don't want them to happen multiple times):
scala> new Qux(1).bar
hey
hey
res2: String = new Qux(1)new Qux(1)
Here the constructor is called twice since we include the prefix expression in the macro's result twice. You can avoid this by defining a temporary variable in the macro:
object FooMacros {
def barImpl(c: Context): c.Tree = {
import c.universe._
val tmp = TermName(c.freshName)
val self = c.prefix
q"""
{
val $tmp = $self
_root_.scala.List.fill($tmp.i + $tmp.i)(${ self.tree.toString }).mkString
}
"""
}
}
And then:
scala> class Qux(i: Int) extends Foo(i) { println("hey") }
defined class Qux
scala> new Qux(1).bar
hey
res3: String = new Qux(1)new Qux(1)
Note that this approach (using freshName) is a lot better than just prefixing local variables in the macro with a bunch of underscores, which can cause problems if you include an expression that happens to contain a variable with the same name.
(Update about that last paragraph: actually I don't remember for sure if you can get yourself into problems with local variable names shadowing names that might be used in included trees. I avoid it myself, but I can't manufacture an example of it causing problems at the moment, so it might be fine.)

Scala: Preference among overloaded methods with implicits, currying and defaults

The following simple piece of code fails to compile:
object O {
def apply(s:String, o:Int=5)(implicit i:String) = {
println("am first");
s
}
def apply(s:String)(o:Boolean*) = {
println("am second");
o
}
}
object Main extends App {
implicit val myS = "foo"
O("test")
}
The error being
error: missing arguments for method apply in object O;
follow this method with `_' if you want to treat it as a partially applied function
O("test")
^
one error found
This appears to be because the compiler prefers the second apply. But why is this? Especially considering that the conditions for applying the first apply are satisfied? If I delete the second apply the piece of code compiles fine.
Are there any way to "guide" the compiler towards compiling this correctly? Or am I forced to create two different method names?
You're right that it is possible for the Scala compiler to be smarter. The problem is that noone has wanted to come up with the new specification for this. It'll be very complicated.
There are ways to get around this limitation.
1. replace overloading with pattern matching within apply to choose one of the two functions
def apply(s: String, i: Option[Int] = None) = {
i match {
case Some(n) => // call the 1st
case None => // call the 2nd
}
}
Then:
apply("test", Some(5)) => ... // if we want the first
apply("test") => ... // if we want the second
2. use overloading but with different parameter names for the two functions:
def apply(apple: String, o: Int = 5)(implicit i: String)
def apply(banana: String)(o: Boolean*)
Then:
apply(apple = "test") // if we want the first
apply(banana = "test") // if we want the second
Let's regard this situation without implicits
object O {
def apply(s: String, o: Int = 5) = {
println("am first")
}
def apply(s: String) = {
println("am second")
}
}
In this situation O("test") will be compiled with second apply, so you can't use default parameters in this situation. Implicits changes nothing here. If you'll explicitly provide Int parameter, you cod will compile with first apply.