When we hear the scripting language, bash or batch scripts come into our mind. They come preinstalled in Linux or Windows. We can start writing scripts using bash(.bash) or batch(.bat). We don’t need to install anything else, and they can do most basic tasks.
I have researched some of the most popular scripting languages like Python, PHP, JavaScript, Groovy, and so on. However, I found statically typed languages like Scala very interesting to use as a scripting language, it gives us power because it uses JVM and we can have huge libraries to use.
So, we focus on ways we can write scripts and run them using Scala.
- Using Scala Command
We can use Scala command to run scripts, and it is the simplest method to write and run scripts. We simply run the script using
scala script_file.scala
Classical way (Scala 2)
object Hello {
def main(args: Array[String]): Unit = {
println(s"Hello ${args.mkString(", ")}!")
}
}
Scala 3
@main
def hello(args:String*):Unit= println(s"Hello ${args.mkString(",")}!")
So far so good, we can run these scripts using simply
scala script_file.scala
We can modify the script by adding a Shebang line as follows:
#!/usr/bin/env scala
@main
def hello(args:String*):Unit= println(s"Hello ${args.mkString(",")}!")
We make this file executable, and now we can simply run like a normal bash or shell script.
chmod +x script_file.scala
./script_file.scala
The file should have any extension (you can simply rename it with .sh extension or event without any extension). I used .scala so that I could use code intellisense in my VSCode.
Limitations:
It is perfect to write simple scripts, but I have not found how we can import external libraries from maven repository.
2. Using scala-cli
There is very nice tool called “scala-cli” and this is best suited for using scala as a powerful scripting language. While you can use static typing of scala, you can also use libraries from the maven repository. We can have lots of customizations to fine tune the running of scripts. The full information, github respository and the documentation can be found in the following scala-cli link.
https://scala-cli.virtuslab.org
Installation: the preferred way of installing scala-cli is using sdkman. If you have installed sdkman, then simply running the following command will do the job.
sdk install scalacli
You can check the installation of scala-cli using the following command
scala-cli -version
Note: we can run all valid scala script mentioned number 1 above using scala-cli. Also, if the file is saved in .sc format, we can directly run the lines in the file. For me, this is very cool, and helps testing the scala code without creating any class, no main method required. The lines work as if they in the main block.
Another very interesting thing of scala-cli is we can not only run scala codes, but also java codes too
//> using jvm "16"
public class Main {
public static void main(String[] args) {
System.out.println(System.getProperty("java.version"));
}
}
This code can be simply run using
scala-cli Main.java
The official scala-cli site claims that the compilation time is faster which I am also noticing.
Directives: There is a very interesting feature called directives, which are the first lines in the code, where can tweak many things including the scala version, java version and libraries.
//> using scala "3.2.1"
//> using dep com.lihaoyi::os-lib:0.9.0
Using multiple files
You can add source file using the directive //> using file
in Scala scripts.
main.sc
//> using file Utils.scala
println(Utils.message)
Utils.scala
object Utils{
val message="Hello World"
}
scala-cli main.sc => Hello World
If we have multiple scala files, to avoid writing multiple directives and redundancies, the recommended method is to write a centralized file (project.scala or project.sc) and write all directives and startup code there. We can simple include the other files “//>using file” directive.
Example:
project.scala
//>using scala "3.5.2"
//>using jvm "21.0.5"
//>using file Utils.scala
//>using file Test.scala
@main
def hello(args: String*): Unit ={
println(Utils.greet("Hello")+Utils.message+ Hello1.value1)
}
project.sc
//>using scala "3.5.2"
//>using jvm "21.0.5"
//>using file Utils.scala
//>using file Test.scala
println(s"Hello ${args.mkString(",")}!")
println(Utils.greet("Hello")+Utils.message+ Hello1.value1)
Running the code
scala-cli project.scala or scala-cli project.sc
Watch Mode
This is also very interesting feature where scala-cli watches the changes and re-runs if any changes are there.
scala-cli Test.sc --watch
There is alternative of –watch => –restart which kills the process instead of waking the sleeping thread.
Self executable Scala Script
#!/usr/bin/env -S scala-cli shebang
println("Hello world")
chmod +x Script.sc
./HelloScript.sc
=> Hello world
Arguments
#!/usr/bin/env -S scala-cli shebang
println(args(1))
./Script.sc hello world
3. Ammonite: scripting in advance
Ammite is more advanced, I am not covering ammonite features here, can be checked using the link above. For me, scala-cli fulfills my requirement of writing basic Scripts in scala.
Final Note: Scala is very interesting, and writing code in scala is fantastic. The mix of imperative and functional programming gives the real test of programming. At the same , we should not forget that, the learning curve for scala is very steep, and developing big projects using scala is even more challenging, in that case I would prefer java.