Predefine routine in scala sbt console? - scala

I am recently writing scala, using sublimetext to write *.scala and run sbt in another window.
When I use sbt console to debug, every time I need to manually import packages and do routines.
It's really annoying to repeat copying codes again and again after I recompile and restart console.
I wonder is there a way to set a predefined environment to do it manually?
Another question I want to know is in console REPL can I auto complete lines by the initial characters? For example in python IDLE one can use Alt+p to search history. It's really convenience.

Initial commands
You could add this line to your build.sbt:
initialCommands in console := "import scalaz._, Scalaz._"
Result:
$ sbt console
[info] Starting scala interpreter...
[info]
import scalaz._
import Scalaz._
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_45).
Type in expressions to have them evaluated.
Type :help for more information.
scala>
REPL auto complete
You could tap Tab key to get limited auto complete:
scala> List(1, 2, 3)
res0: List[Int] = List(1, 2, 3)
scala> res0.ap
First Tab - auto complete and options:
scala> res0.apply
apply applyOrElse
Second Tab - method signature:
scala> res0.apply
def apply(n: Int): A
History
You could use Ctrl+R to search in history (including history from previous REPL sessions). Use addition Ctrl+R to get next result.

Also probably worth noting is that you can load scripts into the repl, too:
$ cat > guessing.txt
import scala.util.Random.nextInt
def guess() {
val r = nextInt()
println("I randomly picked %d.".format(r))
}
$ sbt console
scala> :load guessing.txt
Loading guessing.txt...
import scala.util.Random.nextInt
guess: ()Unit
scala> guess
I randomly picked -630907258.
:help is your friend.

Related

Import statement:error:not found in Scala REPL

I am new to scala. I have created a scala object containing a couple of methods. I am trying to invoke the method from Scala REPL but the import statement is not working.
This is the code I tried (It is in a default package):
object Hello extends App {
def sum(xs: List[Int]): Int = 0;
def max(xs: List[Int]): Int = 0;
}
For starting the Scala REPL, I opened the console and then did the following:
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\user>sbt
[info] Set current project to user (in build file:/C:/Users/user/)
> console
[info] Updating {file:/C:/Users/user/}user...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Starting scala interpreter...
[info]
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_2
2).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import Hello._
<console>:7: error: not found: value Hello
import Hello._
^
scala>
The project workspace and the project is created in E:/Work. Even I tried navigating to the project and then followed the same steps above but it gives the same error.
Please let me know how to make this import statement work from Scala REPL.
For project structure please refer to this page
Your dir tree should be something like
E:
|
`- Work
|
`- {PROJECT}
|
+- build.sbt
|
`- src
|
`- main
|
`- scala
|
`- Hello.scala
Next navigate to E:\Work\{Project} and from there run sbt and only then console and do all the work
Remember that your REPL will refer to classes that were compiled before console were executed.
Note that your project structure could be much simpler like
E:
|
`- Work
|
`- {PROJECT}
|
`- Hello.scala
But this is not recommended
you need to compile your project
exit the scala REPL, then from the shell prompt:
> sbt clean compile package
the compile task is a dependency on the sbt, so just sbt is the same as sbt compile, but i don't see a line in your console output that shows it compiled your project (it will begin with Compiling)
alternatively if you have no dependencies (which it looks like you don't) then you can just paste that code directly in the REPL session, and let the Scala REPL compile your code for you, like so:
scala> :paste
// paste your code in the REPL window
scala> ctrl-D

Scala sbt jar allows import when class path is passed on command line, but not in REPL

I've built a small test jar with Scala and SBT. If I put the classpath argument on the Scala REPL command line, it imports the package perfectly. However if I get into the shell and then add the classpath, it does not recognize the import. Being new to Scala this confuses me so I hope someone can explain. I'll try to provide enough information without going overboard.
scala -cp configparser_2.10-1.0.jar
Welcome to Scala version 2.10.4 (OpenJDK 64-Bit Server VM, Java 1.7.0_75).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import com.oaktreepeak.util._
import com.oaktreepeak.util._
scala> val c = new OakConfig()
c: com.oaktreepeak.util.OakConfig = com.oaktreepeak.util.OakConfig#58d9a418
Now I'll wait and load the classpath to the jar after I'm in the shell:
scala
Welcome to Scala version 2.10.4 (OpenJDK 64-Bit Server VM, Java 1.7.0_75).
Type in expressions to have them evaluated.
Type :help for more information.
scala> :cp configparser_2.10-1.0.jar
Added '/home/*****/Dyn/projects/DynECT2/scala/common/ConfigParser/test-configs/configparser_2.10-1.0.jar'. Your new classpath is:
".:/home/*****/Dyn/projects/DynECT2/scala/common/ConfigParser/test-configs/configparser_2.10-1.0.jar"
Nothing to replay.
scala> import com.oaktreepeak.util._
<console>:7: error: object oaktreepeak is not a member of package com
import com.oaktreepeak.util._
^
scala>
Here is my build.sbt file:
name := "ConfigParser"
version := "1.0"
scalaVersion := "2.10.4"
organization := "com.oaktreepeak"
And the single Scala source file:
package com.oaktreepeak.util
import scala.io._
import scala.util.parsing.json._
class OakConfig {
var iRollupAfter: Int = -1;
def Load(sPath: String) {
val config = Source.fromFile(sPath).mkString
val json:Option[Any] =JSON.parseFull(config)
val map:Map[String,Any] = json.get.asInstanceOf[Map[String, Any]]
iRollupAfter = map.get("RollupAfter").get.asInstanceOf[Double].toInt
}
}
Anyone have any ideas or explanations?
Thanks
:cp was broken in Scala 2.10, and has been replaced with (a working) :require in Scala 2.11.
If you're new to Scala I would recommend using the latest, stable version of Scala, which currently is 2.11.6.
Also, as you're new to Scala, if you want to try things out from your project in the REPL (which is a great workflow) from sbt just run console, which will compile your code and give you REPL with all of Scala's classes, your projects classes and the classes for all your dependencies! No need to feed manually feed the REPL a classpath.

How can I get scala to work in the command line?

I run Windows 7.
I have java (a current enough version to run scala) and scala downloaded on my computer. I've set PATH so that when I type "scala" into the command prompt it sends me to the proper interface:
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51)
Type in expressions to have them evaluated.
Type :help for more information
However I can't execute the command "scala" or "scalac" on my test files.
scala> scala Hello
(console):8: error: object Hello is not a member of package scala
This makes me think I'm in the wrong directory. The file Hello.scala is saved in the home directory that I set PATH to.
However I get a different issue when I try to compile code.
scala> scalac Hello.scala
(console):1: error: ';' expected but '.' found.
I actually got my test file to work at one point... but I wasn't actually IN scala.
C:\scala-2.9.1.final\bin> scala Hello.scala
Hello world!
I'm not really sure how to proceed from here. If anyone has any ideas of what may be wrong I would greatly appreciate input.
It appears that you're trying to run & compile programs from within the Scala REPL (read-evaluate-print loop - a kind of Scala interpreter) and you cannot do that in the REPL. The REPL allows you to type in Scala statements and see them execute immediately. (If you're not sure how you entered the REPL, you probably just entered the command scala from the command line.) The REPL is useful for testing ideas, and for experimenting with Scala. For example:
C:\some\path> scala
Welcome to Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_91).
Type in expressions for evaluation. Or try :help.
scala> println ("Hello!")
Hello!
scala> val x = 10
x: Int = 10
scala> val y = x * 5
y: Int = 50
scala> sys.exit
C:\some\path>
However, the REPL isn't what you would use to compile & run Scala programs - you need to do that from the command line (or from a tool such as sbt). If you want to run your program directly from the command line, without using the REPL (that is, without being in Scala, as you put it) then you would need to do the following:
Firstly, compile your program using scalac:
C:\some\path> scalac Hello.scala
If that succeeds, you can then run the program with the scala command (which looks for a Hello.class file):
C:\some\path> scala Hello
(Here C:\some\path is the location of the files Hello.scala & Hello.class.)
Alternatively, as you have already discovered, you can run your Scala program as a script in the REPL. You can do this from the command line as follows (note the addition of the filetype .scala after Hello compared to the command above):
C:\some\path> scala Hello.scala
or from within the REPL:
scala> :load Hello.scala
Hope this helps!
You don't have to issue scala command when you're inside REPL. If you want to execute code from that file, load it:
here is what I have in Foo.scala
println("I'm foo")
Now I'm starting the REPL (and as you can see scala> is a sign that you're ALREADY into REPL and can start execute raw scala code):
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> :load Foo.scala
Loading Foo.scala...
I'm foo

Using eval to println elements of library-dependencies in SBT 0.12.x shell

Trying to master SBT and Scala makes my live tough at times when simple things in theory turn themselves into not so simple in practise.
I'm working with Apache Spark 0.9.0-incubating that uses SBT 0.12.4.
While poking around in their SBT build configuration I ran across an issue of how to println elements of library-dependencies in SBT (interactive) shell. It's a more general question of how to eval more complex Scala expressions in sbt shell?
> external-mqtt/library-dependencies
[info] List(org.scala-lang:scala-library:2.10.3, io.netty:netty-all:4.0.13.Final, org.eclipse.jetty:jetty-server:7.6.8.v20121106, org.eclipse.jetty.orbit:javax.servlet:2.5.0.v201103041518, org.scalatest:scalatest:1.9.1:test, org.scalacheck:scalacheck:1.10.0:test, com.novocode:junit-interface:0.9:test, org.easymock:easymock:3.1:test, org.mockito:mockito-all:1.8.5:test, commons-io:commons-io:2.4:test, commons-io:commons-io:2.4, org.eclipse.paho:mqtt-client:0.4.0)
I managed to do the following
> eval libraryDependencies in externalMqtt
[info] ans: sbt.SettingKey[Seq[sbt.ModuleID]] = sbt.Scoped$$anon$1#aa3170e
but am struggling with getting the Seq[sbt.ModuleID] out of sbt.SettingKey.
A concise explanation on how to proceed would be very appreciated. Thanks.
Instead of you using eval, if you first drop into:
consoleProject
then you can attach .eval to settings, so e.g.
> consoleProject
[info] Starting scala interpreter...
[info]
import sbt._
import Keys._
import currentState._
import extracted._
import cpHelpers._
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51).
scala> (fullClasspath in Compile).eval.foreach(println)
Attributed(/Users/tisue/Dropbox/repos/euler/target/scala-2.10/classes)
Attributed(/Users/tisue/.sbt/boot/scala-2.10.3/lib/scala-library.jar)
This doesn't answer your question directly; I don't know how to make eval do what you want. As documented at http://www.scala-sbt.org/release/docs/Detailed-Topics/Console-Project.html , and as actually visible in the above transcript, consoleProject does a number of imports that bring useful names and implicits into scope, which is what makes the above work. You might expect that eval would evaluate code you pass it in a context where the same identifiers and implicits are in scope, but it doesn't. (I tried putting the same imports into a call into eval but it didn't work.)
Not the greatest answer — perhaps someone else can be more authoritative.

Scala: How can I install a package system wide for working with in the repl?

In Python, if I install a package with pip install package_name, I can open a Python repl by typing python and simply import the package by its name, regardless of what directory I'm currently in in the filesystem.
Like so
$ python
Python 2.7.3 (default, Sep 26 2013, 20:03:06)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>>
and the requests library is imported and I can play with it in the repl.
In Scala, I know how to do this in a project that uses sbt, but for learning purposes, I would like to install a package in such a way so that I can simply type scala at the command line and then import the installed package, without being tied to a specific project.
$ scala
Welcome to Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_40).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scalaz._
<console>:7: error: not found: value scalaz
import scalaz._
How can I do this?
Scala is different from Python. Code compiled for Scala 2.9.x is not compatible to 2.10.x. So global definitions can cause a lot of problems if you work with different versions.
You can use SBT and add to $HOME/.sbt/plugins/build.sbt
libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.0.4"
or
libraryDependencies += "org.scalaz" % "scalaz-core_2.10" % "7.0.4"
and then go to /tmp and start a Scala REPL with SBT:
sbt console
But on long term it is not a good idea.
The best thing would be to install SBT, create a file build.sbt
and put this in it:
libraryDependencies += "org.scalaz" % "scalaz-core_2.10" % "7.0.4"
scalaVersion := "2.10.2"
initialCommands in console := "import scalaz._, Scalaz._"
Now change with the console into the folder of build.sbt and run
sbt console
With this you can experiment with the REPL and have already scalaz imported and in the class path. In addition it is easy to add additional dependencies.
SBT is cool, you don't need to install new Scala versions manually, just declare it in build.sbt.
In addition to S.R.I i'm using the following solution, shell script:
/usr/bin/scalaz
#!/bin/sh
scala -cp ~/.ivy2/cache/org.scalaz/scalaz-core_2.10/bundles/scalaz-core_2.10-7.1.0-M3.jar ... other libs
then just call it in the terminal:
$ scalaz
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_40).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> Monad[Option].point(1)
res0: Option[Int] = Some(1)
scala>
This is generally not recommended since most jar libraries are meant to be used along with programmer projects. Also, unlike other ecosystems, jar libraries are usually installed via some user mode library management tool like ivy or maven or sbt, as you may have observed.
If you really want to do this, you can install jars to scala's TOOL_CLASSPATH location which you can find out from scala.bat or scala shell script file bundled along with your scala distribution. Alternatively, you can build your own custom scala repl, which can load globally installable libraries from some configured location. Either way, it requires futzing with the TOOL_CLASSPATH.
P.S: I currently do not have access to the actual scala.bat file to help you with this, but you can look it up here and here to understand what I mean. Note that these files may not show how the .bat files are structured as those in the distribution(and may be quite dated). Please look it up in the official distribution for information.
EDIT
I can explain a bit more now that I'm back and looked at the actual scala batch and shell scripts included in official distribution :-)
Like I said above, the scala script loads all jar files present in its TOOL_CLASSPATH folder which is usually ${SCALA_HOME}/lib. It also offers the ability to add to TOOL_CLASSPATH with the promising -toolcp option - Let's see what it shows: (the batch script is similar - I'll just show things from scala shell script)
while [[ $# -gt 0 ]]; do
case "$1" in
-D*)
# pass to scala as well: otherwise we lose it sometimes when we
# need it, e.g. communicating with a server compiler.
java_args=("${java_args[#]}" "$1")
scala_args=("${scala_args[#]}" "$1")
shift
;;
-J*)
# as with -D, pass to scala even though it will almost
# never be used.
java_args=("${java_args[#]}" "${1:2}")
scala_args=("${scala_args[#]}" "$1")
shift
;;
-toolcp)
TOOL_CLASSPATH="${TOOL_CLASSPATH}${SEP}${2}"
shift 2
;;
-nobootcp)
unset usebootcp
shift
;;
-usebootcp)
usebootcp="true"
shift
;;
-debug)
SCALA_RUNNER_DEBUG=1
shift
;;
*)
scala_args=("${scala_args[#]}" "$1")
shift
;;
esac
done
As you can see, this is sorely limiting - you'd have to specify each jar to be added. You could just use -cp! Can we make it better? Sure, we'd have to muck around in this toolcp business.
addtoToolCP() {
for i in $(find $1 -name "*.jar")
do
if [[ -z "$TOOLCP" ]]
then
TOOLCP="$i"
else
TOOLCP="${TOOLCP}:$i"
fi
done
}
So, you could just check for the emptiness of our TOOLCP parameter and accordingly call scala as scala -toolcp $TOOLCP if it's non-empty. Now, you can just invoke your shell script as: myscalascript <list-of-paths-to-be-added-to-toolcp>. Or you could just keep one folder and go on adding new libraries to that folder. Hope this helps - as others have said, do watch out for binary compatibility issues. Binary incompatibility issues would only affect major scala versions, minor versions should be perfectly compatible. Lastly, at risk of repeating myself to death, use this only if you're sure you want this. :-)