Scala JSR 223 importing types/classes - scala

The following example fails because the definition for Stuff can't be found:
package com.example
import javax.script.ScriptEngineManager
object Driver5 extends App {
case class Stuff(s: String, d: Double)
val e = new ScriptEngineManager().getEngineByName("scala")
println(e.eval("""import Driver5.Stuff; Stuff("Hello", 3.14)"""))
}
I'm unable to find any import statement that allows me to use my own classes inside of the eval statement. Am I doing something wrong? How does one import classes to be used during eval?
EDIT: Clarified example code to elicit more direct answers.

The Scripting engine does not know the context. It surely can't access all the local variables and imports in the script, since they are not available in the classfiles. (Well, variable names may be optionally available as a debug information, but it is virtually impossible to use them for this purpose.)
I am not sure if there is a special API for that. Imports are different across various languages, so bringing an API that should fit them all can be difficult.
You should be able to add the imports to the eval-ed String. I am not sure if there is a better way to do this.

Related

Scala-Lang recommended import statement style: package._ or package.ClassName?

Looking for best Scala-Lang practice for import statements. Don't see any recommendation here:
https://docs.scala-lang.org/style/naming-conventions.html#packages
https://github.com/scala/scala
So what is recommended?
Option (1):
import package._
Option (2):
import package.ClassName
This is generally a matter of taste, but there is an argument for avoiding ._ so that the code is more robust to library changes that might introduce unwanted symbols into your code or create other subtle changes to your code that are difficult to track down.
Regarding implicits, wildcard imports have a potential advantage in that the name of the implicit can change without having to fix the import statements, for example, consider
object Qux {
object Implicts {
implicit class ExtraListOps[T](l: List[T]) {
def shuffle: List[T] = scala.util.Random.shuffle(l)
}
}
}
import Qux.Implicts._
List(1,2,3,4,5).shuffle
Here we could rename ExtraListOps and yet would not have to modify import statement. On the other hand, Joshua Suereth states:
You can pull implicits in individually without wildcards. Explicit
imports have 'priority' over wildcard imports. Because of this, you
can shadow wildcard imports with an explicit import.
Also consider the discussion in the SIP Wildcard imports considered harmful, where for example, Ichoran states
Superfluous clutter at the top of every file that can only be managed
by an IDE, and even then not very well, is something I find a lot more
harmful in most cases. If you get conflicting implicits and the
compiler doesn’t tell you exactly where they came from, that’s a
compiler issue. Once detected, the fix is easy enough (e.g. import org.foo.{troublesomeImplicit => _, _}).

How to get the full class name of a dynamically created class in Scala

I have a situation where I have to get the fully qualified name of a class I generate dynamically in Scala. Here's what I have so far.
import scala.reflect.runtime.universe
import scala.tools.reflect.ToolBox
val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()
val generatedClass = "class Foo { def addOne(i: Int) = i + 1 }"
tb.compile(tb.parse(generatedClass))
val fooClass:String = ???
Clearly this is just a toy example, but I just don't know how to get the fully qualified name of Foo. I tried sticking a package declaration into the code but that threw an error when calling tb.compile.
Does anyone know how to get the fully qualified class name or (even better) to specify the package that Foo gets compiled under?
Thanks
EDIT
After using the solution proposed I was able to get the class name. However, the next step is the register this class to take some actions later. Specifically I'm trying to make use of the UDTRegistration within Apache Spark to handle my own custom UserDefinedTypes. This strategy works fine when I manually create all the types, however, I want to use them to extend other types I may not know about.
After reading this it seems like what I'm trying to do might not be possible using code compiled at runtime using reflection. Maybe a better solution is to use Scala macros, but I'm very new to that area.
You may use define instead of compile to generate new class and get its package
val cls = tb.define(tb.parse(generatedClass).asInstanceOf[universe.ImplDef])
println(cls.fullName) //__wrapper$1$d1de39015284494799acd2875643f78e.Foo

How can I use Monocle's built in law implementations to test my own lenses?

I noticed that Monocle has implementations of lens laws that are used to test the libraries internals. They seem to be nicely generalized and modularized. I tried to use them to test my own lenses, but I am lost in the jungle of dependencies. Has anybody tried to do this, and could post an example? The documentation does not seem to talk about laws at all. Thank you.
To elaborate, here is what I am trying to do (fumbling, not sure if I am using the intended way to use the API):
it should "pass the LensLaws" in check {
forAll {(c: (String,Int), a: String) =>
new monocle.law.LensLaws(l).setGet(c,a) } }
where l is the Monocle lens, visible in scope. I am receiving the following error message:
No implicit view available from monocle.internal.IsEq[String] => org.scalacheck.Prop
As far as I can see the setGet law constructs an IsEq object and I was not able to find how to turn it into a Prop (or Boolean).
I can also see that the framework is using a function checkAll to test all LensLaws at the same time, but I could not get this to work in my own code either. Any help appreciated.
The following works for me
import org.scalatest.FunSuite
import org.typelevel.discipline.scalatest.Discipline
class LensesSuite extends FunSuite with Discipline {
import scalaz._
import Scalaz._
checkAll("Lens l", monocle.law.discipline.LensTests(l))
}
It turns out that the main problem was my relatively short knowledge on scalatest. checkAll is a checker provided by org.typelevel.discipline.scalatest.Discipline, which only works in FunSuite (not in FlatSpec that I was using). It took me ages to figure that out ...
Still have no idea how to elegantly use this RuleSet (LensTests) into another spec. It seems strange that the choice of RuleSet by Monocle would enforce the Spec style on the project using these tests.

Transitively import foo._ in Scala

I'm using a utility library for dimensional analysis that i'd like to extend with my own units, and I'd like to be able to write
import my.util.units._
in files in my project. My thought was to define
package my.util
object units {
import squants._
[... other definitions ...]
}
and I expected import my.util.units._ to have the same effect as import squants._, plus the other definitions. But it seems importing units._ doesn't end up adding squants._ to the scope.
Is there a way to do this in scala?
We've dealt with this a little bit at work, and we've tried to resolve this a few ways. Here's an example of how we import rabbitmq types throughout scala-amqp:
package com.bostontechnologies
package object amqp {
type RabbitShutdownListener = com.rabbitmq.client.ShutdownListener
type RabbitConnection = com.rabbitmq.client.Connection
type RabbitChannel = com.rabbitmq.client.Channel
type RabbitConsumer = com.rabbitmq.client.Consumer
type RabbitAddress = com.rabbitmq.client.Address
...
}
So now when we import com.bostontechnologies.amqp._ we get access to the rabbitmq types that we've defined. I know it requires quite a bit of duplication, however we've found it to be somewhat useful, especially since it gives us granularity over type names.
Also, you don't need to use a package object, we mainly use it for convenience of automatically importing our types around a package. You could just use a normal object as well.
Imports are not transitive in Java or Scala. Probably the closest you are going to get to what you seek is to create an object (perhaps a package object) with a type definition for each type of interest.

Scala-IDE or Scala strange import behavior

I am working on a small Scala project. I have the following issue with 'import':
If, at the top of one of my files, I import two thing with these commands:
import main.Main._
import main.game.Game
^^^^
it gives me the following error message at the underlined 'main' word: "missing arguments for method main in object Main; follow this method with `_' if you want to treat it as a partially applied function" which is quite strange especially that it is just an import statement. And naturally no actual importing occures. At first I thought about semicolon inference quirks again but it is not the case. If I swap the two lines and write like this:
import main.game.Game
import main.Main._
then everythinng is fine.
Could anyone shed some light on that? Is it something special about Scala?
Presumably you have a main method in object Main. So after import main.Main._ main refers to this method instead of the main package. You could avoid it in several ways:
Change import order, as in the question.
Don't import the main method, as Daniel C. Sobral's answer suggests.
Explicitly say you want the top-level main package:
import _root_.main.game.Game
Following the normal Java package naming convention should avoid this problem in most cases, as you are unlikely to have members (or subpackages) called com or org (though net could be a problem).
You do have a method named main inside main.Main, don't you? Well, since you imported it, it has now shadowed the package by the name main. You can try this to confirm:
import main.Main.{main => _, _}
import main.game.Game
This will exclude main from being imported.