Ammonite: Scala Scripting
lihaoyi.com
lihaoyi.com
On the other hand, I hate to be that guy, but
1. website is not https, no guarantee it's not modified or any authenticity
2. to install I need to download a file from a shorten URL then make it executable, then run it, no questions asked. I'm sorry but no.
3. no checksum to validate the binary
Great start, but these small security things are going to inhibit adoption, at least in my case.
Still don't let that stop you. Better ship early than never, and it looks very polished and well thought. Good luck!
If you want to run Ammonite on Windows the only way is to clone the repo, patch it and build it.
You are right to be careful, even paranoid, but the security issues are not a showstopper.
I import it using sbt/ivy and load the console/run an ssh session!
I remember spending a couple of hours one weekend getting this to work in Cygwin. I lost energy to pursue it further after getting it to work, which is typical with me :-) (Then I revisit things after 6 months or so, with some luck and free time).
Anyway, here are my notes from that attempt, in case someone else runs into the same issues:
a) I fixed the height and width in ammonite/repl/FrontEndUtils.scala so that it doesn’t go down the hell hole of Cygwin tput and tty issues
b) hard-coded repl.frontEnd() = ammonite.repl.FrontEnd.JLineUnix in ammonite/shell/Configure.scala
c) sbt '~shell/test:run' to run the fully-loaded REPL
re: the rm -rf "$STEAMROOT/"* there is much simpler way to avoid it:
set -euo pipefail
IFS=$'\n\t'
This would prevent this bug and many others. For whole overview on that see: http://redsymbol.net/articles/unofficial-bash-strict-mode/import $ivy.`org.typelevel::cats:0.9.0`
And then I play with it. Or when I read a scala book and copy past example/exercise to benefit from the syntax coloration and don't want to recompile everything every time I change something.
The only question I want to ask to @lihaoyi : why does ivy import has such an ugly syntax ? (import $ivy2.`com::lib:version`) rather than the more sbt like (import $ivy2 "org.scalatest" %% "scalatest" % "2.2.6") ?
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?)
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
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 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"]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).
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.
Li has a patreon I advise anyone using ammonite to checkout!
ls.rec! cwd |? (_.ext == "class") |? (_.size > 1024) | (_.last) | println
Compare to (I think this is roughly equivalent Powershell) ls -rec |? {$_.Extension -eq ".dll"} |? {$_.Length -gt 1024}This is the one thing keeping me away from Scala programming in general, by the way, to be honest.