Scala packages and importing - scala

I have my very first scala program HelloWorld.scala which is located in ~/home/Jacobian/Projects/core/scala/ folder. Now I want to test the concept of packages and see how they can be imported/used. This is the code I have:
package Projects.core.scala
class HelloWorld{
private[scala] var greeting: String = "Hello from package"
}
That is. As you can see, I call my package Projects.core.scala just to reflect that I'm somewhere in /...very_long_path/Projects/core/scala/. I'm not sure what I'm doing wrong, but the problem is, when I compile my program with $ scalac HelloWorld.scala I get an error message:
error: '{' expected but ';' found
It's a funny error message, because I have no ';' in my code. If someone can show what I'm doing wrong, that would be great. But it would be even more useful, if someone could also share how this class HelloWorld wrapped in some arbitrary package (not necessary compatible with folders structure) can be imported. (PS. I'm reading Horstman book on Scala, but I can not figure out what can I do when it comes to a real world program and not to abstract concepts that are quite easy to understand)
FULL ERROR MESSAGE:
HelloWorld.scala:9: error: '{' expected but ';' found
class HelloWorld{
^ one error found
This error message pops up, when there are no parantheses and if I add
package Projects.core.scala {
class HelloWorld { ...
then the error goes away.
Importing issue
Now that I've wrapped class HelloWorld with parantheses and compiled the program, I see that there appeared some folder structure. So, it seems like now it should be quite easy to import the class and this is how I try to do that:
import Projects.core.scala.HelloWorld
object Test{
def main(args: Array[String]){
println("Hello from Test")
}
}
Test.scala is located right in the same folder where HelloWorld.scala and in this very folder I see Projects/core/scala/HelloWorld.class and other compiled files. However, when I try to compile now Test.scala, I get another error message:
Test.scala:3:error not found: object Projects
It is again very interesting - why it is trying to find an object, when I want it to import a class? And why does not it import this class? What other woodoo magic should take place?
File tree structure
HelloWorld.scala
Test.scala
Projects/core/scala/HelloWorld.class
And this is how Test.scala looks like:
import Projects.core.scala.HelloWorld._
object Test{
def main(args: Array[String]){
println("Hello from test")
}
}
I also tried import Projects.core.scala.HelloWorld and import Projects.core.scala._, but none of them work. I always get an error message:
error: not found: object Projects
EDIT
I added full path to Projects/core/scala/ to the CLASSPATH, but it does not help. Still, compiler is unable to import my custom class. I find it really frustrating, cos in Python or other languages that I know, it will take me a couple of second to do the trick, here I have to spend hours on such a miserable task - just importing a class. Gosh!

Related

Intellij + FunSuite weird Behavior

I have a problem with Intellij running tests on scala. I guess It is a configuration issue but I can't figure it out.
1.- When I write some simple test like below, I got the message: "class MyTest must either be declare as abstract or implement abstract member 'expectedTestCount' ... "
class MyTest extends FunSuite {
test("a") {
assert(true)
}
}
But I am just following scala's documentation in which no overriding is going on. It compiles and I can run the test, but it is anoying
2.- The other weird thing is the triple equal operator (===). You can use it in scala for a better explanation on tests, but Intellij seems to not recognize It: "cannot resolve symbol ===" message pops up when writing it. Again It compiles and works OK but you get all your code in alarm red
Any suggestion?
Best regards

Scala Macro - error referencing class symbol "not found: value <class>"

I'm trying to create a Scala macro that generates code like:
val x = new com.foo.MyClass()
where com.foo.MyClass is definitely on the classpath at compile time and run time in the project using the macro.
I'm using the following c.Tree to generate the code:
Apply(Select(New(Ident(TermName("com.foo.MyClass"))), termNames.CONSTRUCTOR), List())
Printing the output of the show and showRaw commands indicate that the correct code is generated, however it seems that com.foo.MyClass either isn't on the class path during macro expansion or during compilation immediately after.
I'm seeing the following error generated at the usage point of the macro (the macro impl itself is defined in a separate project):
[ERROR] /src/main/java/foo/MyWhatever.scala:10: not found: value com.foo.MyClass
[ERROR] MyMacros.someMacro(someInput)
[ERROR]
Why is it failing to find this class on the classpath even though it's a Java file in the same project? I tried -Ymacro-debug-verbose and com.foo.MyClass isn't in the output, but a bunch of other Java & Scala classes are. I can't find a pattern to which classes are on the classpath for the Macro expansion.
Thanks for any help!
Okay! I managed to answer my own question. It turns out it works to use c.mirror.staticClass("com.foo.MyClass") to use compile-time reflection to get a class Symbol, then use Quasi-quotes.
My solution:
val classSymbol = c.mirror.staticClass("com.foo.MyClass")
val newClassTree = q"new ${classSymbol.toType}()"
c.Expr { newClassTree } // Success! This compiles and runs

Not getting a result from SBTCookbook code from Play Framework

Play Framework has, as part of their guides, this bit: https://www.playframework.com/documentation/2.5.x/SBTCookbook#Hooking-into-Plays-dev-mode
It describes the creation of a .scala file in the project/ folder, which allows you to execute some processes before starting the application in DEV mode.
So, I thought I'd try something simple like this:
import play.sbt.PlayRunHook
import sbt._
object Hello {
def apply(base: File): PlayRunHook = {
object HelloThere extends PlayRunHook {
override def beforeStarted(): Unit = {
Process("echo hello", base).run
}
}
HelloThere
}
}
File is saved as Hello.scala
But I'm not seeing anything in the console after running activator run. Am I doing something wrong? I did go to the localhost:9000 url in the browser to see if that caused the compilation of anything more, but no results from that either.
Using Play 2.5.8
I have no experience in Scala, only Java. Though there doesn't seem anything wrong with the code. It's just a copy paste with the object name replaced and the process text replaced.

Run/Debug Config on IDEA 13 for Scala Application

complete stranger/newbie question, sorry to bother you:
I want to run a scala project in IDEA 13 (on Mac OSX), there is no run/debug configuration. I tried some options, however I don't know what to choose (and what should happen, then).
I tried:
Scala Console
Scala Script
Scala Test
Specs2
Choosing Scala Console: something happens, but I get no message box from my showMessage(message = "Hello World") messagebox. (It did work in Eclipse, so far).
Scala Script: I suppose this is meant for single lines of code, not an app, is that?
Specs2: Error in options-dialog: Specs2 is not specified. What is spec2? What should I enter and where? Error while debugging: no main class detected. OK, there is none, I can see that.
Any other option I should use, or normally is used?
Would any help appreciate very much!
This is my (very simple) scala app. Somehow, I'd expect to get an message box while running from IDEA.
import swing._
import swing.Dialog._
import scala.swing.event.ButtonClicked
object HW {
def main(args: Array[String]): Unit = {}
showMessage(message = "Hello World")
}
by the way: the closest tread I've found was this, but it didn't really help, looked too different:
How to run scala code on Intellij Idea 11?
Just use "Application". You have to select a main class and a module.
In terms of your example, I recommend not mixing a def main with a "free" standing constructor body. Also, Swing code should be called only from the event dispatch thread (Swing.onEDT). The easiest for desktop applications is to extend trait SwingApplication which handles that for you:
import swing._
import swing.Dialog._
object HW extends SwingApplication {
def startup(args: Array[String]): Unit =
showMessage(message = "Hello World")
}

How to reload a class or package in Scala REPL?

I almost always have a Scala REPL session or two open, which makes it very easy to give Java or Scala classes a quick test. But if I change a class and recompile it, the REPL continues with the old one loaded. Is there a way to get it to reload the class, rather than having to restart the REPL?
Just to give a concrete example, suppose we have the file Test.scala:
object Test { def hello = "Hello World" }
We compile it and start the REPL:
~/pkg/scala-2.8.0.Beta1-prerelease$ bin/scala
Welcome to Scala version 2.8.0.Beta1-prerelease
(Java HotSpot(TM) Server VM, Java 1.6.0_16).
Type in expressions to have them evaluated.
Type :help for more information.
scala> Test.hello
res0: java.lang.String = Hello World
Then we change the source file to
object Test {
def hello = "Hello World"
def goodbye = "Goodbye, Cruel World"
}
but we can't use it:
scala> Test.goodbye
<console>:5: error: value goodbye is not a member of object Test
Test.goodbye
^
scala> import Test;
<console>:1: error: '.' expected but ';' found.
import Test;
There is an alternative to reloading the class if the goal is to not have to repeat previous commands. The REPL has the command
:replay
which restarts the REPL environment and plays back all previous valid commands. (The invalid ones are skipped, so if it was wrong before, it won't suddenly work.) When the REPL is reset, it does reload classes, so new commands can use the contents of recompiled classes (in fact, the old commands will also use those recompiled classes).
This is not a general solution, but is a useful shortcut to extend an individual session with re-computable state.
Note: this applies to the bare Scala REPL. If you run it from SBT or some other environment, it may or may not work depending on how SBT or the other environment packages up classes--if you don't update what is on the actual classpath being used, of course it won't work!
Class reloading is not an easy problem. In fact, it's something that the JVM makes very difficult. You do have a couple options though:
Start the Scala REPL in debug mode. The JVM debugger has some built-in reloading which works on the method level. It won't help you with the case you gave, but it would handle something simple like changing a method implementation.
Use JRebel (http://www.zeroturnaround.com/jrebel). JRebel is basically a super-charged class reloading solution for the
JVM. It can handle
member addition/removal, new/removed classes, definition changes, etc. Just about the only thing it can't handle is changes in class hierarchy (adding a super-interface, for
example). It's not a free tool, but they do offer a complementary license which is limited to Scala compilation units.
Unfortunately, both of these are limited by the Scala REPL's implementation details. I use JRebel, and it usually does the trick, but there are still cases where the REPL will not reflect the reloaded class(es). Still, it's better than nothing.
There is an command meet you requirement
:load path/to/file.scala
which will reload the scala source file and recompiled to classes , then you can replay you code
This works for me....
If your new source file Test.scala looks something like this...
package com.tests
object Test {
def hello = "Hello World"
def goodbye = "Goodbye, Cruel World"
}
You first have to load the new changes into Scala console (REPL).
:load src/main/scala/com/tests/examples/Test.scala
Then re-import the package so you can reference the new code in Scala console.
import com.tests.Test
Now enjoy your new code without restarting your session :)
scala> Test.goodbye
res0: String = Goodbye, Cruel World
If the .scala file is in the directory where you start the REPL you can ommit the full path, just put :load myfile.scala, and then import.