First steps with Scala, say goodbye to bash scripts… (playlatam.wordpress.com)

23 points by opensas ↗ HN
Playframework 2.0 is right around the corner, and it’s core is programmed in Scala, so it’s a wonderful opportunity to give this object-oriented / functional hybrid beast a try… Like many others, I will pick a very simple script to give my first steps…

25 comments

[ 3.6 ms ] story [ 66.0 ms ] thread
A nice article, but its worth mentioning that scala for bash script usage is a non-starter for most stuff you might use bash for because JVM startup overhead, even for the client VM, is so substantial
True, but: 1. There are a ton of long-running/cron-style tasks where JVM startup overhead just isn't relevant (and Scala's type safety, access to Java libraries and logging tools rinse Bash), and: 2. If you are using Scala scripting in "live operator" mode, here's a good SO answer on how to speed that up: http://stackoverflow.com/questions/4237863/improving-scala-s...
I don't get how the bash scripts are not used. It's still used at

    #!/bin/sh
    exec scala "$0" "$@"
/bin/sh is probably a symlink to something other than bash though. It's not using any features/functions of the shell other than to execute scala. It's a stretch calling that a script.
That's a one-line Bash wrapper to invoke Scala (line 2) with the original arguments sent to the Scala script, compiling the Scala code which follows below. You can read more at the bottom of the man page here: http://www.scala-lang.org/docu/files/tools/scala.html
I wonder why they don't use

#!/usr/bin/env scala

as the first line instead. If there's some hack to support #!/bin/sh in the scala interpreter... ew.

I tried it, and got:

sas@ubuntu:~/devel/apps/playdoces/documentation/1.2.4/manual/tmp$ ./status.scala error: script file does not close its header with !# or ::!# one error found

If you do:

    #!/usr/bin/env scala
    !#
it appears to work.
I still prefer a simple shell script for these use cases. Here's a snippet for the translated file size calculation:

  translated_files=$(grep "todavida no ha sido traducida" *)
  total_size=$(du --summarize . | cut -f 1)
  translated_file_size=$(du --summarize --total $(echo translated_files) | tail -n 1 | cut -f 1)
  echo "translated size: ${translated_file_size}KB/${total_size}KB $(($translated_file_size/$total_size))%"
I find that much more elegant; four lines of bash script which would run on nearly any Unix-like system, versus 49 (or a bit less if you drop the whitespace) of Scala, which won't. Even the shebang is three lines instead of one!

I guess this example is nice as an introduction to Scala, but it doesn't seem like Scala is a particularly appropriate replacement for any of the things one would normally use a shell script for.

> which would run on nearly any Unix-like system

Did you mean on nearly any Unix-like system which has the output of du in the same format as the one on your machine? I don't believe those can be treated as standard if you want any kind of portability.

Okay, I'm not an expert on variations between different Unices, that may well be the case. The point I was trying to make was more that it would run without having to install a great wodge of Java/Scala dependencies which aren't on most systems by default.
Two nitpicks: grep by default returns lines that match, not files, you need the '-l' option; and you're passing the string "translated_files" to du instead of the actual files, you need just $translated_files instead of the echo.

And that breaks with files with spaces on them, which is a bane of shell scripts.

By the way, in Python:

    import os
    total_size = sum([os.path.getsize(filename) for filename in os.listdir('.')])
    matches = [match for match in os.listdir('.') if "todavida no ha sido traducida" in open(match).read()]
    translated_file_size = sum([os.path.getsize(filename) for filename in matches])
    print "translated size: %dKB/%dKB %d" % (translated_file_size, total_size, translated_file_size / total_size)
Good catches

The spaces in filenames can be handled by having grep and du communicate with null delimited strings instead of newline delimited, e.g.

  grep --files-with-matches --null "todavida..." *
  du --summarize --total --files-from=<($(echo $translated_file_size))
nice article, but they could have removed the last part of the title. Its a nice way to learn scala, but a poor way to say goodbye to bash.