Cool scripting language feature: install your own dependencies
Babashka scripts are capable of downloading and starting pods at runtime. (Pods are programs that can be used as a Clojure library by babashka)
#!/usr/bin/env bb
(require '[babashka.pods :as pods])
(pods/load-pod 'org.babashka/fswatcher "0.0.5")
(require '[pod.babashka.fswatcher :as fw])
(fw/watch "." prn {:delay-ms 5000})
(println "Watching current directory for changes... Press Ctrl-C to quit.")
@(promise)
I’m not saying it’s something we should be amazed by, but not many languages provide this. It has a sort of “this opens up so many possibilities” feeling: You can just write your script, copy it into any environment, and it will bootstrap with its own dependencies. The same applies when you open your 5-year-old script; you don’t have to fiddle with manually installing all dependencies. As I said, it’s nothing crazy, just a small convenience. Obviously, this wouldn’t be that smart for production either.
So anyway, I was wondering what other languages can do this.
Elixir scripts can install packages and use them:
Mix.install([:jason])
IO.puts(Jason.encode!(%{hello: :world}))
(Too bad elixir’s startup time isn’t that great for scripting)
Deno can import packages from npm directly:
import chalk from "npm:chalk@5";
console.log(chalk.green("Hello from npm in Deno"));
or from any URL, even using data: schema
import { camelCase } from "jsr:@luca/cases@1.0.0";
import { pascalCase } from "https://deno.land/x/case/mod.ts";
import * as module from "data:application/javascript;base64,ZX..."
F# has #r directive
#r "nuget: Newtonsoft.Json"
open Newtonsoft.Json
let data = {| Name = "Don Syme"; Occupation = "F# Creator" |}
JsonConvert.SerializeObject(data)
Ruby has bundler/inline module:
#!/usr/bin/env ruby
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'httparty', '~> 0.20'
gem 'json', '~> 2.6'
end
require 'httparty'
require 'json'
response = HTTParty.get('https://api.github.com/users/ruby')
puts JSON.pretty_generate(response.parsed_response)
R needs a little bit of helper code if you don’t want to download the package every time, even if it’s already available:
#!/usr/bin/env Rscript
ensure_package <- function(pkg) {
if (!require(pkg)) {
install.packages(pkg)
library(pkg)
}
}
ensure_package("dplyr")
You can possibly shell out and use the package manager in most scripting languages, but I wanted to highlight languages where this feature is a built-in first-class citizen.
That’s it. That’s the post. I think it’s a pretty cool feature.