I am new to scala. I am looking through some code and came up with a code that imports com.infinite.usermanagement.controllers.{ SecurityService => BaseSecurityService } package. I was wondering what does => sign means in an import.
This line means you import the class SecurityService and rename it to BaseSecurityService. You can use this to prevent name conflicts, etc. You can use this class by using BaseSecurityService instead of the original class name.
A very common example is the following (to prevent mixing up Scala and Java classes):
import java.util.{Map => JMap, List => JList}
As others have mentioned, it's an import rename. There is however one further feature that proves astoundingly-useful on occasion that I would like to highlight: If you "rename" to _, the symbol is no longer imported.
This is useful in a few cases. The simplest is that you'd like to do a wildcard import from two packages, but there's a name that's defined in both and you're only interested in one of them:
import java.io.{ File=>_, _ }
import somelibrary._
Now when you reference File, it will unambiguously use the somelibrary.File without having to fully-qualify it.
In that case, you could have also renamed java.io.File to another name to get it out of the way, but sometimes you really do not want a name visible at all. This is the case for packages that contain implicits. If you do not want a particular implicit conversion (e.g. if you'd rather have a compile error) then you have to delete its name completely:
import somelibrary.{RichFile => _, _}
// Files now won't become surprise RichFiles
Related
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'm using pureconfig pureconfig lib with pureconfig-yaml module. Everything works like a charm, my only problem is that I have to convert the property names from camel case to kebab case.
Painful examples from real world:
case class Config(log4JPath: String, registryURL: String, HOUR_FORMAT: String)
Yaml:
log-4-j-path: /conf/log4j.properties
registry-url: http://foo.com
hour-_-format: dd-mm-yy
I don't want to maintain 2 different case types and think about how to convert from one to the other, I would love to have pure copy&paste scala class -> yaml config solution. Is there a chance I could achieve camel case on both sides ?
Edit:
I've created a wrapper around pureconfig lib, which does some config overriding by environment variables. Client should use the wrapper in following manner:
val conf: Config = ConfigLoader(file).load[Config]
However this is not sufficient and the client needs to provide 2 imports:
// to find implicit reader
import pureconfig.generic.auto._
// to use Camelcase - as suggested from the answer
import ConfigLoader.productHint
It would be great if the wrapper (ConfigLoader) could deal with the imports and they would not be left on client's responsibility.
Moreover the imports are identified as "Unused" by IntelliJ IDE and when "optimize imports" is triggered or "Optimize imports on the fly" is enabled the imports are auto-erased. According to this thread (accepted answer is not working for me), we can solve this with "Mark import as always used...", however this is not an ideal solution because other team members will have to do the same for every project or we should commit .idea to VCS (which I'd like to avoid).
I'm attaching screenshot of my test (dependency pureconfig.generic.auto._ have already been marked as allways used):
Yes you can. Take a look to the documentation - field-mappings.
import pureconfig._
import pureconfig.generic.auto._
import pureconfig.generic.ProductHint
// Case classes should be final ;)
final case class Config(log4JPath: String, registryURL: String, HOUR_FORMAT: String)
val yaml =
"""log4JPath: /conf/log4j.properties
|registryURL: http://foo.com
|HOUR_FORMAT: dd-mm-yy""".stripMargin
implicit val indentityHint: ProductHint[Conf] =
ProductHint[Conf](new ConfigFieldMapping {
def apply(fieldName: String) = fieldName // Basically the identity.
})
loadYaml[Config](yaml)
// res: ConfigReader.Result[Config] = Right(Config("/conf/log4j.properties", "http://foo.com", "dd-mm-yy"))
(Note, this was tested in ammonite, using pureconfig 0.11.0).
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.
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.
I heard recently some advice to "unimport an implicit conversion from Predef" - I presume that this means it is possible to unimport unwanted classes too:
import java.awt._
unimport java.awt.List
But this is not the syntax of an "unimport" (i.e. there is no such unimport keyword). What is the correct syntax?
Use the import alias feature but rename the "unwanted class" to "_". Since "_" can not be accessed in Scala code as a classname, it hides the renamed class from unqualified access.
import java.awt.{List => _, _}