17

在 Python 中,如果我使用 安装一个包pip install package_name,我可以通过键入打开一个 Python replpython并简单地按其名称导入包,而不管我当前在文件系统中的哪个目录。

像这样

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

我怎样才能做到这一点?

4

3 回答 3

14

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 中声明即可。

于 2013-10-18T12:29:33.323 回答
1

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

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

PS:我目前无法访问实际文件来帮助您解决此问题,但您可以在此处此处scala.bat查找以了解我的意思。请注意,这些文件可能不会显示 .bat 文件的结构与发行版中的文件相同(并且可能已经过时了)。请在官方发行版中查找以获取信息。

编辑

现在我可以再解释一下,因为我回来查看了官方发行版中包含的实际scala 批处理和 shell 脚本 :-)

就像我上面说的,scala脚本会加载其文件夹中存在的所有 jar 文件,该TOOL_CLASSPATH文件夹通常是${SCALA_HOME}/lib. 它还提供了TOOL_CLASSPATH使用有希望的-toolcp选项添加的能力 - 让我们看看它显示了什么:(批处理脚本类似 - 我将只显示scalashell 脚本中的内容)

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 版本,次要版本应该完全兼容。最后,冒着重蹈覆辙的风险,只有当你确定你想要这个时才使用它。:-)

于 2013-10-18T10:24:46.807 回答
1

除了SRI ,我还使用以下解决方案,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>
于 2013-10-18T10:43:27.193 回答