scala: can't import object from root scope - scala

I Have the following code:
(src/main/scala/coins/coins.scala)
object Main extends App {
def countChange(money: Int, coins: List[Int]): Int = {
[...]
And I'm trying to reference it from a test like this:
(src/test/scala/coins/CoinsSuite.scala)
package coins
import org.scalatest.FunSuite
class CoinsSuite extends FunSuite {
import Main.countChange
test("only onw way to pay $0") {
[...]
And I get the following error:
not found: value Main
[error] import Main.countChange
But on the other hand, from an sbt console it works fine
If I declare any package in the main file, like
package x
object Main extends App {
Console.println("Hello World!")
Then I can correcly issue
import x.Main.countChange
Is there limitation on root package or on singleton objects visibility that I'm not aware of?
-- added
just to complete the answer, a couple of useful links at SO
https://stackoverflow.com/a/2030159/47633
https://stackoverflow.com/a/9822212/47633
https://stackoverflow.com/a/9822227/47633

Java (and Scala according to the same convention) is grumpy about importing things in the unnamed package, which is not the same thing as the root package. Put Main into a package.
See Why is my object not a member of package <root> if it's in a separate source file?

Related

IntelliJ IDEA Scala inspection : import play.api.xxx conflict with com.company.play package

I want to make a helper class at the root of my core project using play-json from typesafe, something like
package com.company
import play.api.libs.json.JsValue
object Helper {
implicit class RichJson(json: JsValue) {
def doStuff() //...
}
}
The problem is that I have somewhere else in the project a package com.company.play
package com.company.play
class Foo() { //...
}
In IntelliJ IDEA 2018.2.4 CE, the line import play.api.libs.json.JsValue is in error with telling me "cannot resolve symbol api" and when Ctrl+Click on the play it goes to the folder containing my Foo.scala file
If I compile the solution with sbt outside of IDEA, there is no problem.
If I put the Helper object in a subpackage (eg com.company.common) there is no error (which also means the dependency is correct in my build.sbt)
I don't understand why IDEA miss this, com.company.play isn't even in the dependencies of the core project. I already tried to invalidate cache, and it doesn't help.
The problem is that Intellij gives precedence to the package play into your project, instead of the package coming from the framework, when resolving the import of JsValue inside com.company scope.
If you really want to keep that name for com.company.play, there is a simple workaround using a fully-qualified import, just prefix like this:
import _root_.play.api.libs.json.JsValue

How do make a `CustomExecutionContext` available for dependency injection in a Play 2.6 controller?

I'm following along with Play 2.6's Scala documentation and sample code for creating non-blocking actions, and am running into some runtime issues. I have created a new Play application using the Scala template (sbt new playframework/play-scala-seed.g8).
The code that the Play documentation suggests should work in a new controller is (this code is taken verbatim from the Play documentation page, with some extra imports from me):
// some imports added by me to get the code to compile
import javax.inject.Inject
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import akka.actor.ActorSystem
import play.api.libs.concurrent.CustomExecutionContext
import play.api.mvc._
import play.api.mvc.ControllerComponents
// end imports added by me
import play.api.libs.concurrent.CustomExecutionContext
trait MyExecutionContext extends ExecutionContext
class MyExecutionContextImpl #Inject()(system: ActorSystem)
extends CustomExecutionContext(system, "my.executor") with MyExecutionContext
class HomeController #Inject()(myExecutionContext: MyExecutionContext, val controllerComponents: ControllerComponents) extends BaseController {
def index = Action.async {
Future {
// Call some blocking API
Ok("result of blocking call")
}(myExecutionContext)
}
}
Then, according to the documentation for using other thread pools, I've defined the my.executor thread pool in the application.conf file of my application:
my.executor {
fork-join-executor {
parallelism-factor = 20.0
parallelism-max = 200
}
}
I should note that I do not want to use the default execution context as I want to prepare for running futures in a separate context that may be used for a limited resource like a database connection pool.
All of this compiles just fine with sbt compile. However, when I run this with sbt run and access my app in a web browser, I get this error:
CreationException: Unable to create injector, see the following errors:
1) No implementation for controllers.MyExecutionContext was bound.
while locating controllers.MyExecutionContext
for the 1st parameter of controllers.NewController.(NewController.scala:17)
while locating controllers.NewController
for the 2nd parameter of router.Routes.(Routes.scala:29)
at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:121):
Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)
I've used Play 2.3 in the past, and know that dependency injection works when you define an instance of an object (via #Singleton or in a module); however, Play 2.6's documentation on DI indicates that "Guice is able to automatically instantiate any class with an #Inject on its constructor without having to explicitly bind it. This feature is called just in time bindings is described in more detail in the Guice documentation."
My question is: what specific lines of code or configuration do I need to add to Play's own sample to make this work, and why?
I found one possible solution when reading further in the Binding Annotations section of the Scala Dependency Injection documentation page. In particular, it states:
The simplest way to bind an implementation to an interface is to use the Guice #ImplementedBy annotation.
So, by adding that to the my MyExecutionContext trait, like so:
import com.google.inject.ImplementedBy
#ImplementedBy(classOf[MyExecutionContextImpl])
trait MyExecutionContext extends ExecutionContext
an instance of the MyExecutionContextImpl is instantiated and properly injected into the controller.
Too bad that this #ImplementedBy annotation isn't listed in the sample code for the non-blocking action documentation!

TypeError: Cannot read property 'freeze' of undefined

I am trying to create a facade for the npm library avsc. When I compile with sbt fastOptJS::webpack and open the .html file, I get Uncaught TypeError: Cannot read property 'freeze' of undefined from the file treepad-fastopt-bundle.js in the line $g["Object"]["freeze"]($env);. I don't use Object.freeze it anywhere.
This is the facade code:
import buffer.Buffer
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSImport, JSName}
#js.native
trait Type extends js.Object {
#JSName("val")
def toBuffer(v: String): Buffer = js.native
}
#JSImport("avsc/", "avro")
#js.native
object avro extends avro
#js.native
trait avro extends js.Object {
def parse(schema: js.Any): Type = js.native
}
Also have a look at the whole project, it's very little code.
Using #JSImport("avsc", JSImport.Namespace) instead did not change anything.
The problem comes from the fact that, in your webpack configuration file, you tell webpack to target the Node.js execution environment instead of web browsers.
However, as you noticed, the avsc module uses the fs Node.js module, which is not available in web browsers. It seems that the right workaround, in this case, is to add the following line to your webpack configuration file:
module.exports.node = { fs: "empty" };
Last but not least, the right #JSImport is indeed #JSImport("avsc", JSImport.Namespace) because you want to import the whole avsc module, as shown in the documentation.

Scala: How to always make certain utils available to sub packages?

All my code is under package com.company.project. In almost all of my files, I end up importing some common things like import scala.util.{Failure, Try, Success} and import scala.util.control.NonFatal etc. Is it possible to somehow setup a package object in such a way that all these utils are always available to all sub packages in com.company.project.sub (kind of my own project level Predef)?
Simply create a package object with type aliases:
package com.company.project
import scala.util
package object sub {
type Failure = util.Failure
type Try = util.Try
type Success = util.Success
type NonFatal = util.control.NonFatal
}

Why does my Scala enumeration break when I move it to another package?

Enumeration code looks like the following
package com.mydomain
object Market extends Enumeration {
type Market = Value
val ASX, LSE = Value
}
I try to use as follows
import com.mydomain.Market._
.
.
.
if (Market.ASX == currentMarket) {
...
}
This was working when everything was in the same package. When I moved to a new package I now get
not found: value Market
If you import Market, you have ASX and LSE directly available to you. You don't have Market.ASX available--that would be if you had object Market available, which is what would happen if you did import com.mydomain._.
Being inside package com.mydomain causes com.mydomain._ to be loaded just like you imported it, so that's why you can say Market.ASX when you're in the same package.
When you write code in a different package, you need to either import com.mydomain._ and then use Market.ASX, or import com.mydomain.Market._ and then use ASX.