运行Scala脚本时类路径不工作

wbrvyc0a  于 11个月前  发布在  Scala
关注(0)|答案(2)|浏览(85)

我在lib目录中成功编译了一个名为bnc.Encryption的Java类:/Users/satchwinston/Development/test/lib
我正在使用Java 21和Scala 3.3.1,我没有使用Metals扩展。
我这样执行Scala脚本:./encryptor依次运行scala -explain -classpath "/Users/satchwinston/Development/test/lib"
我得到以下结果:

-- [E006] Not Found Error: /Users/satchwinston/Development/test/scala-cli/src/main/scala/./encryptor:7:7 
7 |import bnc.Encryption
  |       ^^^
  |       Not found: bnc
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | The identifier for `bnc` is not bound, that is,
  | no declaration for this identifier can be found.
  | That can happen, for example, if `bnc` or its declaration has either been
  | misspelt or if an import is missing.
   -----------------------------------------------------------------------------
1 error found
Errors encountered during compilation

以下是我的Scala脚本:

#!/usr/bin/env scala -explain -classpath "/Users/satchwinston/Development/test/lib"
/* $Id$ */

import java.nio.file.Files
import java.nio.file.Path

import bnc.Encryption

val usage = """
  Usage: encryptor ([-e] | [-d]) ([-in filename] | <arg>) > <filename>
"""

def encrypt(string: String): String =
  Encryption.encrypt(string)

def decrypt(string: String): String =
  Encryption.decrypt(string)

@main def encryptor(args: String*): Unit =
  if (args.isEmpty || args.length != 2 || args.length != 3) {
    println(usage)
    sys.exit(1)
  }

  val e: Boolean = args(0) == "-e"
  val d: Boolean = args(0) == "-d"
  val in: String = if (args(1) == "-in") args(2) else ""
  val str: String = if (args(1) != "-in") args(1) else ""

  if (e && str.length() > 0)
    println(encrypt(str))
  else if (e)
    println(encrypt(Files.readString(Path.of(in))))
  else if (d && str.length > 0)
    println(decrypt(str))
  else if (d)
    println(decrypt(Files.readString(Path.of(in))))
  else {
    println(usage)
    sys.exit(1)
  }

  sys.exit(0)
k10s72fa

k10s72fa1#

我可以让你的脚本像这样工作:

// bnc/Encryption.java - stub since I do not know your implementation
package bnc;

public class Encryption {

  public static String encrypt(String s) { return s; }
  public static String decrypt(String s) { return s; }
}
#!/usr/bin/env -S scala-cli shebang --server=false
//> using scala 3.3.1
//> using option -explain
//> using jvm zulu-jre:21.0.0
//> using file bnc/Encryption.java

import java.nio.file.Files
import java.nio.file.Path

import bnc.Encryption

val usage = """
  Usage: encryptor ([-e] | [-d]) ([-in filename] | <arg>) > <filename>
"""

def encrypt(string: String): String =
  Encryption.encrypt(string)

def decrypt(string: String): String =
  Encryption.decrypt(string)

def encryptor(args: Array[String]): Unit =
  if (args.isEmpty || args.length != 2 || args.length != 3) {
    println(usage)
    sys.exit(1)
  }

  val e: Boolean = args(0) == "-e"
  val d: Boolean = args(0) == "-d"
  val in: String = if (args(1) == "-in") args(2) else ""
  val str: String = if (args(1) != "-in") args(1) else ""

  if (e && str.length() > 0)
    println(encrypt(str))
  else if (e)
    println(encrypt(Files.readString(Path.of(in))))
  else if (d && str.length > 0)
    println(decrypt(str))
  else if (d)
    println(decrypt(Files.readString(Path.of(in))))
  else {
    println(usage)
    sys.exit(1)
  }

  sys.exit(0)

encryptor(args)

关于你写的:
1.如果您有Scala CLI,则不需要再安装Scala。这是一个所有在一个包:scala + scalac + build工具,几个旧工具的 * 替代品 *。

  1. Scala版本可以通过标志和指令来更改
  • 如果你正在构建一个“程序”而不是一个“脚本”,你需要使用.scala扩展-程序有入口点,它告诉JVM从哪里开始(@main),而脚本从上到下评估你正在执行的文件中的所有内容(所以它们不需要任何main)。删除@main,并使用args自己调用方法,然后返回到“脚本”模式
  • 如果有人感兴趣,为什么@main存在,如果Scala CLI是脚本:它不仅适用于脚本。在一个目录中创建几个.scala文件,在其中一个(最好是project.scala)中放置带有Scala版本,JVM版本,平台,依赖关系等的using指令。然后scala-cli compile .将构建一个普通的项目,如果您使用scala-cli run .,则需要一个入口点。这些Scala文件确实需要.scala扩展名。
  • 然而,从上到下评估的单个Scala文件,不打算作为JAR分发,也不打算在IDE中打开,(可选地引用其他.scala.java文件),可以编写为脚本,其中它们的整个主体是一种主类型。这些文件使用.sc扩展名,尽管对于shebang,您也可以根本不使用扩展名。
  • JVM版本可以通过标志和指令来更改。Scala CLI使用coursier,其coursier java --available允许打印所有可以在那里使用的版本。Bloop确保在连续调用之间使用服务器来保持JVM的温度。您可以使用--server=false标志禁用它。
    1. -您的个人风格偏好是一个非技术问题。另外:您不需要使用-classpath--classpath-有一个--extra-jars标志用于将JAR(或.class es)添加到运行时,以及//> using jar///> using jars指令用于添加JAR。因为您有一个独立的.class,它不属于xml 2的一部分,但也没有源代码(您可以使用//> using file filename.java添加)的情况相当罕见。
vtwuwzda

vtwuwzda2#

显然,scala-tool的做事方式还没有跟上速度:
1.我不得不在Scala安装中单独安装scala-tool。

  1. scala-1.0版本只有3.3.0。我的Scala安装在3.3.1。
    1.我必须在脚本文件名中使用.scala扩展名。
    1.可笑的“bloop”服务器中的JVM使用的是Java 17。我的Java安装使用Java 21。不知道如何修改JVM。为什么我需要一个“bloop”服务器?
    1.我不得不用这个荒谬的东西,而不是一个正常的shebang:#!/usr/bin/env -S scala-pushebang-S 3
    1.看起来你必须使用--classpath而不是--classpath。不,CP,真实的吧.
    嗯,也许Groovy是一个更好的选择。

相关问题