【问题标题】:Scala: How can I install a package system wide for working with in the repl?Scala:如何在 repl 中安装一个包系统范围?
【发布时间】:2013-10-27 02:31:18
【问题描述】:

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

我该怎么做?

【问题讨论】:

  • 与 Scala 相比,我认为您指的是 Java/Scala 的最大弱点之一。

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


【解决方案1】:

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

【讨论】:

  • 我希望有一个更简单的解决方案。
【解决方案2】:

除了 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>

【讨论】:

    【解决方案3】:

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

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

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

    编辑

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

    就像我上面所说的,scala 脚本会加载其TOOL_CLASSPATH 文件夹(通常是${SCALA_HOME}/lib)中存在的所有 jar 文件。它还提供了使用有前途的-toolcp 选项添加到TOOL_CLASSPATH 的能力 - 让我们看看它显示了什么:(批处理脚本类似 - 我将只显示来自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 &lt;list-of-paths-to-be-added-to-toolcp&gt;。或者您可以只保留一个文件夹并继续向该文件夹添加新库。希望这会有所帮助 - 正如其他人所说,请注意二进制兼容性问题。二进制不兼容问题只会影响主要的 scala 版本,次要版本应该完全兼容。最后,冒着重蹈覆辙的风险,在您确定要这样做的情况下使用。 :-)

    【讨论】:

      猜你喜欢
      • 2019-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多