Is it similar to what's going on the JS world where people just want to use one language for client, server, and build tools? (and for this case, even the terminal shell?)
Is it similar to what's going on the JS world where people just want to use one language for client, server, and build tools? (and for this case, even the terminal shell?)
The JS everywhere crowd is rather narrowminded and don't seem to be aware that they are reinventing a wheel that others have already done better.
But if you spend most of your day writing JS and you find yourself needing to write complex bash scripts, give your head a shake and use JS instead. It is better to use a real programming language where you have test frameworks, build tools and so on.
I think you're right about the one language thing. If you're developing a system in Scala, you might as well do scripts in the same language, with API access to your system. (Real world example: server deployment script prompts for initial admin password, computes and persists hash using server API).
I imagine piping in bash feels similar, so there's at least a common problem/solution between them
It is. Piping is akin to an untyped subset of working with Scala's collections, and there's a similar workflow between the two, e.g.:
In bash, you build up a command line with something like (as a stupid example, the number of unique file sizes in a directory):
Step 1) $ ls -l
Step 2) $ ls -l | awk '{print $5}'
Step 3) $ ls -l | awk '/\d+/ {print $5}'
Step 4) $ ls -l | awk '/\d+/ {print $5}' | sort -n
Step 5) $ ls -l | awk '/\d+/ {print $5}' | sort -n | uniq
You can see the correspondence with collections--typically building up in the editor in a similar staged manner ending with something like: Process("ls -l").lines // ls -l part
.map(_.split("\\s+")) // awk part {
.filter(_.length > 4) // ...
.map(_.apply(4).toInt) // }
.sorted // sort -n part
.distinct // uniq part
The tradeoffs between the two are essentially verbosity versus data safety (perhaps not important with a throwaway inspection, but more important when working on larger programs...).However, the building process is the same--you don't write the latter all at once, you gradually mold the pipeline until you get the output you want.
[1] pry(main)> `ls`
=> "README.md\n" + "_build\n" + "config\n" + "lib\n" + "mix.exs\n" + "test\n"
[2] pry(main)> `ls`.split
=> ["README.md", "_build", "config", "lib", "mix.exs", "test"]
[3] pry(main)> `ls`.split.map(&:upcase)
=> ["README.MD", "_BUILD", "CONFIG", "LIB", "MIX.EXS", "TEST"]
[4] pry(main)> `ls`.split.map(&:upcase).select { |x| x.match(/E/) }
=> ["README.MD", "MIX.EXS", "TEST"]Scala is also less verbose, easy todo FP with and its very natural to do system/db work with.
Its basically a better java for me.
Personally, I try to use Groovy for any semi-complicated sort of script. It has many features that are similar to Scala, and usually ends up being very concise and readable.
Even though I think that's the wrong approach I certainly have had many instances where I've whipped something quick up in language X even though it was wildly inappropriate simply because for me it was going to be faster