Import package as another - scala

Let's say I have a Scala project with a bunch of case classes under package com.example.a.b.c. I want to import all these classes into a package com.example.c (which contains a few more non-conflicting case classes) so that anywhere else in my project, I only need to import com.example.c._ to use every case class both from com.example.c and com.example.a.b.c.
How can I do that?

There is discussion of adding an export mechanism which would do what you want, but it's not clear whether that will happen.
In any case, for now the only way is to
Define the type of every class
Set a val equal to every object
So for example,
package bar
case class Foo(i: Int) {}
would need to be mimicked in another package with
package object baz {
type Foo = bar.Foo
val Foo = bar.Foo
}
When faced with this, people usually just settle for an extra import or two.

The import statement in scala just tells the compiler where to find other classes like in java, not like the #include directive in C/C++ where the compiler physically copies the entire header file. If you want to use the case classes from com.example.a.b.c, you should import them from their own package as this is the conventional way.

Related

Is it possible to automatically load an implicit def if included as a dependency (no importing)

I'm working on a commons library that includes a config library (https://github.com/kxbmap/configs).
This config library uses "kebab-case" when parsing configuration files by default and it can be overridden by an implicit def in scope.
However, I don't want to force that on the users of my commons library when they get access to the config library transitively.
So without me forcing users to import this implicit, like:
import CommonsConfig._
can I somehow override the naming strategy via an implicit that gets into scope by only including my commons library on the classpath. I'm guessing no but I just have to ask :)
So if not, is someone aware of another approach?
kxbmap/configs isn't that well documented to explain this.
Thanks!
Implicits work in compile time, so they cannot get magically present if something is included and then disappear if it isn't.
The closest thing would be something like:
main library
package my.library
// classes, traits, objects but no package object
extension
package my
package object library {
// implicits
}
user's code
import my.library._
however that would only work if there were no package object in main library, only one extension library could pull off this trick at once (Scala doesn't like more than one package object) and user would have to import everything available with a package, always.
In theory you could create a wrapper around all you deps, with your own configs:
final case class MyLibConfig(configsCfg: DerivationConfig)
object MyLibConfig {
implicit val default: MyLibConfig = ...
}
and then derive using this wrapper
def parseThings(args...)(implicit myLibConfig: MyLibConfig) = {
implicit val config: DerivationConfig = myLibConfig.config
// derivation
}
but in practice it would not work (parseThings would have to already know the target type or would need to have the already derived implicits passed). Unless you are up to writing your own derivation methods... avoid it.
Some way of making user just import all relevant stuff is the most maintainable strategy. E.g. you could pull off the same thing authors did and add type aliases for all types that you use, do the same for companion objects and finally put some implicits there:
package my
package object library {
type MyType = some.library.Type
val MyType = some.library.Type
implicit val derivationConfig: DerivationConfig = ...
}

How could a "global implicit class" be defined in Scala?

Considering that a implicit class "must be defined inside of another trait/class/object"1, how can a implicit conversion be defined globally?
The case is that I'd like to add a method to all Strings (or Lists) in my application, or at least to several packages of it.
One cannot add anything to the "global" scope, neither in Java, nor in Scala.
However, in Scala one can define package objects, which can contain methods that are used all over the package, and can be easily imported by the user.
This looks something like this: in the directory foo/bar/baz one creates a file called package.scala with the following content:
package foo.bar
package object baz {
implicit def incrediblyUsefulConversion(s: String) = ...
}
The user then can do the following in his code to activate the conversion:
import foo.bar.baz._
or maybe
import foo.bar.baz.incrediblyUsefulConversion
Of course, you can also use your own code in other packages, just like any other user.

How to (properly) enrich the standard library?

I would like to define an implicit conversion from Iterator[T] to a class that I have defined: ProactiveIterator[A].
The question isn't really how to do it but how to do it properly, i.e. where to place the method, so that it is as transparent and unobtrusive as possible. Ideally it should be as the implicit conversion from String to StringOps in scala.Predef If the conversion was from a class in the library to some other class, then it could be defined inside that class, but AFAIK that's not possible here.
So far I have considered to add an object containing these conversions, similarly to JavaConversions, but better options may be possible.
You don't really have much of a choice. All implicits must be contained within some sort of object, and imported with a wildcard import (you could import them individually, but I doubt you want that).
So you'll have some sort of implicits object:
package foo.bar
object Implicits {
implicit class ProactiveIterator[A](i: Iterator[A]) {
...
}
}
Then you must explicitly import it wherever you use it:
import foo.bar.Implicits._
In my opinion, this is a good thing. Someone reading the code might not understand where your pimped methods are coming from, so the explicit import is very helpful.
You can similarly place your implicits within a package object. You would have to import them the same way into other namespaces, but they would be available to classes within the same package.
For example, using the following, anything within foo.bar will have this implicit class available:
package foo
package object bar {
implicit class ProactiveIterator[A](i: Iterator[A]) {
...
}
}
Elsewhere you would import foo.bar._ (which may or may not be as clean, depending on what's in bar).

Types defined in a package object aren't in scope

To avoid writing out a large type in several places in my code, I thought I'd shortcut it using a type declaration in a package object:
package pet
package object pet {
type Ops = ((Int,Int) => Int,String)
}
object Q extends App {
val ops = List[Ops](
((_+_),"+"),
((_-_),"-"),
((_*_),"*")
)
}
But it's saying that for val ops, Ops isn't found. I'm guessing I'm misunderstanding something, but after looking over several package object examples, I can't tell what. There are no errors in the package object itself, so I don't think that it's a problem with that.
When declaring a package object, you need to place it in the package "above". As it stands, you're declaring package object pet inside package pet, so that Ops is actually located at the path pet.pet.Ops.
In your case, you should just place the package object inside it's own file without any package declaration.
If you were to import pet.pet._ inside Q it would also work.
Each package is allowed to have one package object. Any definitions
placed in a package object are considered members of the package
itself.
As seen from here, the definitions are package specific (in this case pet.pet). So you need to import them for use.
You can try:
object Q extends App {
import pet.pet._
...

If scala case class and object have same name, how to import case class only

Well I have a scala class Foo.scala containing these two elements,
First One,
case class Foo(
.
.
.
)
And secondly,
object Foo{
.
.
.
}
Now when I import the Foo in some other file, I want to use the case class not the Object, but when I import the file, object instance is returned in Foo<= this is the object,(I needed to do Foo.apply, Foo.tupled)
Is there anyway I can get the Foo to act as the case class then an object.
you can try this
(Foo.apply _).tupled
You have ambiguity in your scala namespaces. A simple solution to the problem would be to nest the case class inside of the object, then import it with
import Foo.Foo
another solution would be to place them in separate packages. Depending on your system design this could affect the cohesiveness of your packages, which in my mind is probably more important.