Pergunta

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?

Foi útil?

Solução

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.

Outras dicas

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. :-)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top