【踩坑指南2.0 2025最新】Scala中如何在命令行传入参数以运行主函数

news2025/1/7 14:47:00

这个地方基本没有任何文档记录,在学习的过程中屡屡碰壁,因此记录一下这部分的内容,懒得看可以直接跳到总结看结论。

踩坑步骤

首先来看看书上让我们怎么写:

//main.scala
object Start {
  def main(args:Array[String]) = {
    try {
      val score = args(1).toInt
      val s = Students2(args(0), score)
      println(s.toString)
    } catch {
      case ex: ArrayIndexOutOfBoundsException => println("Arguments are deficient!")
      case ex: NumberFormatException => println("Second argument must be a Int!")
    }
  }
}

之后,书上说我们执行下面的编译和运行指令即可运行:

scala students2.scala Start.scala
scala Start Tom

事实上,我们会获得以下报错:

jia@J-MateBookEGo:~/scala_test$ scala Start Tom
[error]  Start is not a scala sub-command and it is not a valid path to an input file or directory.
Try viewing the relevant help to see the list of available sub-commands and options.
  scala --help
Tom: input file not found
Try viewing the relevant help to see the list of available sub-commands and options.
  scala --help

经过检查,已经生成了一系列.class的JVM可执行文件,但似乎scala拒绝执行。

但是出于严谨,我们需要考虑是否是我们的代码编写有问题,因此我们来到scala的官网:

main 方法 | Scala 3 — Book | Scala Documentation

果然,官网在这里提示我们建议使用Scala3的全新语法,它将不需要创建一个object和输入参数列表,而是使用更简洁的语法来完成,这在我们之前的debug中已经体验过,当需要传入参数时,官网的程序示例是这样的:(当然,官网表示针对Scala2的写法仍然支持,就是前面传入参数列表的写法)

@main def happyBirthday(age: Int, name: String, others: String*) =
  val suffix = (age % 100) match
    case 11 | 12 | 13 => "th"
    case _ => (age % 10) match
      case 1 => "st"
      case 2 => "nd"
      case 3 => "rd"
      case _ => "th"

  val sb = StringBuilder(s"Happy $age$suffix birthday, $name")
  for other <- others do sb.append(" and ").append(other)
  sb.toString

然后官网说执行如下编译后运行指令可以得到结果:

$ scala happyBirthday 23 Lisa Peter
Happy 23rd Birthday, Lisa and Peter!

实际上,它又报错了,和之前是一样的:

jia@J-MateBookEGo:~/scala_test$ scala happyBirthday 23 Lisa Peter
[error]  happyBirthday is not a scala sub-command and it is not a valid path to an input file or directory.
Try viewing the relevant help to see the list of available sub-commands and options.
  scala --help
23: input file not found
Try viewing the relevant help to see the list of available sub-commands and options.
  scala --help
Lisa: input file not found
Try viewing the relevant help to see the list of available sub-commands and options.
  scala --help
Peter: input file not found
Try viewing the relevant help to see the list of available sub-commands and options.
  scala --help

根据之前debug的经验,这应该是由于编译器版本更新导致的。我们在之前的文章中使用新的执行指令解决了这个问题,它要求我们显式写出run:前情提要(没错,这个官网仍然是错的)

于是我们尝试使用这条指令运行:

jia@J-MateBookEGo:~/scala_test$ scala run -cp . -M happyBirthday
Illegal command line: more arguments expected

非常好,现在这个程序成功运行了,但如果想要传入参数,它又报错了 

jia@J-MateBookEGo:~/scala_test$ scala run -cp . -M happyBirthday 22
[error]  22: input file not found
Try viewing the relevant help to see the list of available sub-commands and options.
  scala run --help

那么我们现在百思不得其解,是否是这种写法不再被支持了?网上无法找到任何资料。万念俱灰之时,我们又找到了github这个提问Document starting programs compiled by scalac in the current working directory · Issue #3132 · VirtusLab/scala-cli · GitHub

根据回答的内容,我们顺藤摸瓜找到了Scala CLI的官网,没错,这次终于找到罪魁祸首了:

Migrating from the old Scala runner | Scala CLI 

在这里说明,

从SIP-46开始,Scala CLI已被接受为新的Scala命令。

在这种情况下,本指南的目的是强调旧的scala脚本和scala CLI之间的主要区别,以使用户尽可能顺利地进行迁移。

因此,我们之前的命令很多都不再被支持,这是导致错误的根本原因。但是Scala的官网并没有在这里更新使用Scala CLI的指令。

当我们从官网下载最新的Scala,Scala CLI已经作为原生指令被提供,也就是说我们现在使用的scala指令就是以前的scala-cli。

那么我们能不能仍然使用以前的编译器呢,答案是可以,但我们需要使用指令scala_lagacy,这里说明如下

是否可以使用旧的Scala runner?

是的,尽管它的用法已被弃用,但在scala_legacy命令下仍然可以使用它。然而,它很可能在未来的版本中被删除。

 那我们进行测试,看看最新版本是否仍然支持:

jia@J-MateBookEGo:~/scala_test$ scala_legacy -version
scala_legacy: command not found

效率真高啊,说删就删,这种完全牺牲针对旧版本的兼容性的操作令人费解。但也没办法,看来我们只能学习新的指令,看看他们有什么区别,此处我们直接引用一段官网的内容:

老方法

在旧的运行程序中,第一个参数被视为输入源,而第二个及之后的参数被视为程序参数。

@main def main(args: String*): Unit = println(args.mkString(" "))

scala_legacy Source.scala programArg1 programArg2

由于第一个参数之后的所有内容都必须作为程序参数任意读取,而不管格式如何,因此必须在源输入之前传递所有运行程序选项。可以使用下面的语句按照老方法执行:

scala_legacy -save Source.scala programArg1 programArg2

很好,这就是我们尝试使用的方案。显然,他们已经彻底删除了这个针对老方法的支持。 那么新方法是什么?

Scala CLI的使用方法

使用Scala CLI处理参数的默认方式,输入和程序参数必须加上--。两者的数量都没有限制。

def placeholder = println("Example extra source")
scala Source.scala Source2.scala -- programArg1 programArg2

此外,可以在输入部分之前传递一个Scala CLI子命令。例如,要调用上面的例子,显式地指定run子命令,像这样传递它:

scala run Source.scala Source2.scala -- programArg1 programArg2

 Runner选项可以传递到输入部分的任何位置(在--之前)。例如,以下所有示例都是将Scala版本显式指定为3.2的正确方法

scala -S 3.2 Source.scala Source2.scala -- programArg1 programArg2
scala Source.scala -S 3.2 Source2.scala -- programArg1 programArg2
scala Source.scala Source2.scala -S 3.2 -- programArg1 programArg2

 好的,我们试一下执行书上的代码,果然成功了。

jia@J-MateBookEGo:~/scala_test$ scala Start.scala students2.scala -- Tom
Arguments are deficient!
jia@J-MateBookEGo:~/scala_test$ scala Start.scala students2.scala -- Tom aaa
Second argument must be a Int!
jia@J-MateBookEGo:~/scala_test$ scala Start.scala students2.scala -- Tom 100
Tom's score is 100.

另外这个网页也展示了一些别的信息,主要是关于版本的变更导致一些语法不被支持。

比如以下这个代码:

println(args.mkString(" "))

它在3.x的版本中不再支持。

scala script.scala -- Hello world
[error] ./ScriptInScala.scala:1:1
[error] Illegal start of toplevel definition
[error] println(args.mkString(" "))
[error] ^^^^^^^
Error compiling project (Scala 3.2.2, JVM)
Compilation failed

像2.x版本中的object和参数列表法定义main函数仍然支持,但推荐使用@main方法。

总结

Start.scala中的代码:

//Start.scala
object Start {
  def main(args:Array[String]) = {
    try {
      val score = args(1).toInt
      val s = Students2(args(0), score)
      println(s.toString)
    } catch {
      case ex: ArrayIndexOutOfBoundsException => println("Arguments are deficient!")
      case ex: NumberFormatException => println("Second argument must be a Int!")
    }
  }
}

students2.scala中的代码:

class Students2(val name:String, var score: Int) {
  def apply(s:Int) = score = s
  def display() = println("Current core is " + score + ".")
  override def toString = name + "'s score is '" + score + "."
}

object Students2 {
  def apply(name: String, score: Int) = new Students2(name, score)
}

编译和执行命令:(别用scalac了,因为官网都没写scalac后如何执行)

jia@J-MateBookEGo:~/scala_test$ scala Start.scala students2.scala -- Tom
Arguments are deficient!
jia@J-MateBookEGo:~/scala_test$ scala Start.scala students2.scala -- Tom aaa
Second argument must be a Int!
jia@J-MateBookEGo:~/scala_test$ scala Start.scala students2.scala -- Tom 100
Tom's score is 100.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2271865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Excel VBA 自动填充空白并合并相同值的解决方案

文章目录 Excel VBA: 自动填充空白并合并相同值的解决方案问题背景解决方案1. VBA代码实现2. 代码说明3. 使用方法4. 注意事项 扩展优化总结 Excel VBA: 自动填充空白并合并相同值的解决方案 问题背景 在Excel中经常会遇到这样的数据处理需求&#xff1a;一列数据中存在多个空…

SpringSecurity中的过滤器链与自定义过滤器

关于 Spring Security 框架中的过滤器的使用方法,系列文章: 《SpringSecurity中的过滤器链与自定义过滤器》 《SpringSecurity使用过滤器实现图形验证码》 1、Spring Security 中的过滤器链 Spring Security 中的过滤器链(Filter Chain)是一个核心的概念,它定义了一系列过…

【STC库函数】Compare比较器的使用

如果我们需要比较两个点的电压&#xff0c;当A点高于B点的时候我们做一个操作&#xff0c;当B点高于A点的时候做另一个操作。 我们除了加一个运放或者比较器&#xff0c;还可以直接使用STC内部的一个比较器。 正极输入端可以是P37、P50、P51&#xff0c;或者从ADC的十六个通道…

Postgresql 命令还原数据库

因为PgAdmin打不开&#xff0c;但是数据库已经安装成功了&#xff0c;这里借助Pg命令来还原数据库 C:\Program Files\PostgreSQL\15\bin\psql.exe #链接数据库 psql -U postgres -p 5432#创建数据库 CREATE DATABASE "数据库名称"WITHOWNER postgresENCODING UTF8…

Backend - C# 的日志 NLog日志

目录 一、注入依赖和使用 logger 二、配置记录文件 1.安装插件 NLog 2.创建 nlog.config 配置文件 3. Programs配置日志信息 4. 设置 appsettings.json 的 LogLevel 5. 日志设定文件和日志级别的优先级 &#xff08;1&#xff09;常见的日志级别优先级 &#xff08;2&…

急需升级,D-Link 路由器漏洞被僵尸网络广泛用于 DDoS 攻击

僵尸网络活动增加 &#xff1a;新的“FICORA”和“CAPSAICIN”僵尸网络&#xff08;Mirai 和 Kaiten 的变体&#xff09;的活动激增。 被利用的漏洞 &#xff1a;攻击者利用已知的 D-Link 路由器漏洞&#xff08;例如 CVE-2015-2051、CVE-2024-33112&#xff09;来执行恶意命…

[ubuntu-22.04]ubuntu不识别rtl8153 usb转网口

问题描述 ubuntu22.04插入rtl8153 usb转网口不识别 解决方案 安装依赖包 sudo apt-get install libelf-dev build-essential linux-headers-uname -r sudo apt-get install gcc-12 下载源码 Realtek USB FE / GBE / 2.5G / 5G Ethernet Family Controller Softwarehttps:/…

WinForm开发-自定义组件-1. 工具栏: UcompToolStrip

这里写自定义目录标题 1. 工具栏: UcompToolStrip1.1 展示效果1.2 代码UcompToolStrip.csUcompToolStrip.Designer.cs 1. 工具栏: UcompToolStrip 自定义一些Winform组件 1.1 展示效果 1&#xff09;使用效果 2&#xff09;控件事件 1.2 代码 设计 编码 UcompToolStrip.…

Hypium纯血鸿蒙系统 HarmonyOS NEXT自动化测试框架

1、什么是Hypium Hypium是华为官方为鸿蒙操作系统开发的一款以python为语言的自动化测试框架。 引用华为官网介绍如下&#xff1a; DevEco Testing Hypium(以下简称Hypium)是HarmonyOS平台的UI自动化测试框架&#xff0c;支持开发者使用python语言为应用编写UI自动化测试脚本…

基于Spring Boot微信小程序电影管理系统

一、系统背景与意义 随着移动互联网的普及和用户对个性化娱乐需求的不断增长&#xff0c;电影行业迎来了新的发展机遇。然而&#xff0c;传统的电影管理方式存在信息不对称、购票流程繁琐、用户体验不佳等问题。因此&#xff0c;开发一个基于Spring Boot微信小程序的电影管理系…

软件工程实验-实验2 结构化分析与设计-总体设计和数据库设计

一、实验内容 1. 绘制工资支付系统的功能结构图和数据库 在系统设计阶段&#xff0c;要设计软件体系结构&#xff0c;即是确定软件系统中每个程序是由哪些模块组成的&#xff0c;以及这些模块相互间的关系。同时把模块组织成良好的层次系统&#xff1a;顶层模块通过调用它的下层…

深度学习blog- 数学基础(全是数学)

矩阵‌&#xff1a;矩阵是一个二维数组&#xff0c;通常由行和列组成&#xff0c;每个元素可以通过行索引和列索引进行访问。 张量‌&#xff1a;张量是一个多维数组的抽象概念&#xff0c;可以具有任意数量的维度。除了标量&#xff08;0D张量&#xff09;、向量&#xff08;…

JMH338-剑侠情缘2【开服端】-2017版【剑荡三界】+服务端+客户端+登录器+外网

资源介绍&#xff1a; 激情服&#xff1b;剑荡三界基本上可以直接开服玩&#xff0c;总之每个服都有他的特色&#xff1b;云中&#xff0c;红莲山&#xff0c;葬雪城三大地图三种世界BOSS每个小时刷一次 云中押镖劫镖&#xff0c;出城就是PK模式 剑荡烟云副本分为普通和难度…

QML自定义滑动条Slider的样式

代码展示 import QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Controls 2.1Window {visible: truewidth: 640height: 480title: qsTr("Hello World")Slider {id: controlvalue: 0.5background: Rectangle {x: control.leftPaddingy: control.topPadding …

什么是.net framework,什么是.net core,什么是.net5~8,版本对应关系

我不知道有多少人和我一样&#xff0c;没学习过.netCore&#xff0c;想要学习&#xff0c;但是版本号太多就蒙了&#xff0c;不知道学什么了&#xff0c;这里解释下各个版本的关系 我们一般开始学习微软的时候&#xff0c;都是开始学习的.netframework&#xff0c;常用的就是4…

【2025最新计算机毕业设计】基于Spring Boot+Vue影院购票系统(高质量源码,提供文档,免费部署到本地)

作者简介&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容&#xff1a;&#x1f31f;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…

matlab中高精度计算函数vpa与非厄米矩阵本征值的求解

clear;clc;close all tic %并行设置% delete(gcp(nocreate));%关闭之前的并行 cparcluster(local); c.NumWorkers50;%手动设置线程数(否则默认最大线程为12) parpool(c, c.NumWorkers); %并行设置%w1; u2.5;N30;valstozeros(2*N2,100); v10linspace(-3,3,100).;parfor jj1:leng…

Linux第101步_了解LCD屏驱动“panel-simple.c”

了解LCD屏驱动“panel-simple.c”有助于修改屏驱动。自己另外单独写屏驱动&#xff0c;这是不现实的&#xff0c;所以学会在源程序的基础上修改&#xff0c;才是最佳的学习方法&#xff0c;这就是我们学习框架的主要原因。在Limux系统中&#xff0c;主流的显示框架有两种:DRM(D…

TI毫米波雷达原始数据解析之Lane数据交换

TI毫米波雷达原始数据解析之Lane数据交换 背景Lane 定义Lane 确认确认LVDS Lane 数量的Matlab 代码数据格式参考 背景 解析使用mmWave Studio 抓取的ADC Data Lane 定义 芯片与DCA100之间的数据使用LVDS接口传输&#xff0c;使用mmWave Studio 配置过程中有一个选项是LVDS L…

2-markdown转网页页面设计 --[制作网页模板]

页面设计 将Markdown转换为网页页面设计通常涉及以下几个步骤&#xff1a; 编写Markdown内容&#xff1a; 首先&#xff0c;你需要创建或已有以Markdown格式编写的文档。Markdown是一种轻量级的标记语言&#xff0c;它允许人们使用易读易写的纯文本格式编写文档&#xff0c;然…