Scala:如何在repl中安装广泛的软件包系统?

时间:2013-10-18 09:40:54

标签: scala packages read-eval-print-loop

在Python中,如果我安装了一个包含pip install package_name的软件包,我可以通过键入python打开一个Python repl,然后只需按名称导入软件包,无论我目前在哪个目录中文件系统。

喜欢这样

$ 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
>>> 

并导入了requests库,我可以在repl中使用它。

在Scala中,我知道如何在使用sbt的项目中执行此操作,但出于学习目的,我希望以这样的方式安装包,以便我只需键入scala在命令行中,然后导入已安装的软件包,而不依赖于特定项目。

$ 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._

我该怎么做?

3 个答案:

答案 0 :(得分:11)

Scala与Python不同。为Scala 2.9.x编译的代码与2.10.x不兼容。因此,如果使用不同的版本,全局定义可能会导致很多问题。

您可以使用SBT并添加到$ HOME / .sbt / plugins / build.sbt

libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.0.4"

libraryDependencies += "org.scalaz" % "scalaz-core_2.10" % "7.0.4"

然后转到/ tmp并使用SBT启动Scala REPL:

sbt console

但从长远来看,这不是一个好主意。

最好的办法是安装SBT,创建一个build.sbt文件 把它放进去:

libraryDependencies += "org.scalaz" % "scalaz-core_2.10" % "7.0.4"

scalaVersion := "2.10.2" 

initialCommands in console := "import scalaz._, Scalaz._"

现在使用控制台更改为build.sbt文件夹并运行

sbt console

有了这个,您可以尝试使用REPL并且已经导入了scalaz并在类路径中。此外,还可以轻松添加其他依赖项。 SBT很酷,你不需要手动安装新的Scala版本,只需在build.sbt中声明它。

答案 1 :(得分:1)

通常不建议这样做,因为大多数jar库都应该与程序员项目一起使用。此外,与其他生态系统不同,jar库通常通过某些用户模式库管理工具安装,如ivymavensbt,您可能已经观察过。

如果您真的想要这样做,您可以将jars安装到scala的TOOL_CLASSPATH位置,您可以从scala.batscala shell脚本文件中找到该位置与您的scala分发捆绑在一起。或者,您可以构建自己的自定义scala repl,它可以从某个已配置的位置加载全局可安装的库。无论哪种方式,它都需要TOOL_CLASSPATH

PS:我目前无法访问实际的scala.bat文件来帮助您解决此问题,但您可以查看herehere以了解我的内容意思。请注意,这些文件可能不会显示.bat文件的结构如何与分发中的文件一样(并且可能过时)。请在官方发行版中查阅。

编辑

我现在可以解释一下,我回来看看正式发行版中包含的实际 scala批处理和shell脚本: - )

就像我上面所说,scala脚本会加载TOOL_CLASSPATH文件夹中通常为${SCALA_HOME}/lib的所有jar文件。它还可以使用有希望的TOOL_CLASSPATH选项添加到-toolcp - 让我们看看它显示的内容:(批处理脚本类似 - 我只是显示来自scala shell脚本的内容)

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

正如您所看到的,这是严重限制 - 您必须指定要添加的每个 jar。你可以使用-cp!我们可以做得更好吗?当然,我们不得不在这个toolcp业务中捣乱。

addtoToolCP() {
    for i in $(find $1 -name "*.jar")
    do
        if [[ -z "$TOOLCP" ]]
        then
            TOOLCP="$i"
        else
            TOOLCP="${TOOLCP}:$i"
        fi
    done
}

因此,您可以检查我们TOOLCP参数的空白情况,并相应地将scala称为scala -toolcp $TOOLCP,如果它不是空的话。现在,您只需调用shell脚本:myscalascript <list-of-paths-to-be-added-to-toolcp>。或者您可以保留一个文件夹,然后继续向该文件夹添加新库。希望这有助于 - 正如其他人所说的那样,注意二进制兼容性问题。二进制不兼容问题只会影响主要的scala版本,次要版本应该完全兼容。最后,如果您确定要这个,请使用此 。 : - )

答案 2 :(得分:1)

S.R.I 外,我使用以下解决方案,shell脚本:

/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

然后在终端中调用它:

$ 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>