There is currently a severe REPL limitation:
scala> import concurrent._
import concurrent._
scala> Fut<tab>
This doesn't complete to Future. In other words, wildcard imports are not understood by the JLineCompletion.
I am trying to work around this. I am able to find the ImportHandler instances which report importsWildcard == true, but they are otherwise empty except for the plain importString (e.g., "import concurrent._").
How do I get a list of these wildcard imports, so I can fix the completion candidates?
One idea is as follows: I can get the completions for concurrent.<tab>, so somehow there must be already the functionality to look up the members of a package via the IMain instance.
This problem doesn't affect current versions of Scala. I tried the sbt console with Scala 2.12.4, and tab completion works with wildcard imports. (Beware of this problem, through).
Related
What is the exact import for the triple equals?
Before I was importing "cats.implicits._" and it was working fine but I can't do that anymore as it causes ambiguities with other imports.
Triple equals resides in package cats.evidence
https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/evidence/package.scala
Moreover, some of its instances reside in cats.evidence.Is:
https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/evidence/Is.scala
Then, probably cats.evidence._ cats.evidence.Is._ would be enough.
The general way of figuring out which implicit instance is used by function (at least in Intellij Idea) is Ctrl+Shift+P for arguments, and Ctrl+Shift+Q for implicit conversions.
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 => _, _}).
I have code similar to below
import sqlCtx.implicits._
val items = sc.parallelize(List(i1, i2, i3))
items.toDF().registerTempTable("items")
When I hover over items I would like usual behaviour - displaying type information. Instead I get warnings Avoid wildcard imports and Imports should be grouped together. I can get rid of the first by importing specific function, like
import sqlCtx.implicits.rddToDataFrameHolder
but I can't put import on top of the file what IntelliJ expects of me since it imports from an object that is created with the code and not preexisting. How to workaround it?
I use IntelliJ IDEA v. 15.0.3 with the latest Scala plugin.
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.
Back when reflection was still incipient, on the days of Scala 2.10.0 milestones, I asked a question about how could I use it to see the trees of code snippets from REPL. The excellent answer went further than I asked, and showed how they can be used to parse and evaluate trees as well, so I went ahead and tried to use that on a little project I had going on today.
Unfortunately, code parsed and evaluated that way doesn't seem to see any REPL definition:
scala> val x = 1
x: Int = 1
scala> import scala.tools.reflect.ToolBox
import scala.tools.reflect.ToolBox
scala> val tb = scala.reflect.runtime.universe.runtimeMirror(
getClass.getClassLoader).mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = ...
scala> tb.eval(tb.parse("x"))
scala.tools.reflect.ToolBoxError: reflective compilation has failed:
not found: value x
Is there a way to get it to recognize definitions made on REPL?
Recently I dug into repl, when trying to make it support type macros, so I'm well equipped to explain why it doesn't work. Getting it to work would be the next step :)
I know that you know that every snippet entered into repl gets wrapped into some boilerplate before being compiled. Therefore that x ends up being a field in a nested-nested-nested object in a package with a weird name.
Apparently, repl keeps track of all defined symbols and then injects the necessary imports along with the boilerplate it generates. Therefore subsequent lines can see that x unqualified. To the contrast, toolboxes simply reuse repl's classloader, but don't do anything about the imports, hence the failure.
A workaround would be to somehow get to an object representing a repl, ask it about defined symbols and then generate corresponding imports into the code that you feed to a toolbox. If you file a ticket, I'll try to code up a workaround after the 2.10.1 code freeze madness ends (supposedly, end of this week).