[HN Gopher] Babashka Clojure nREPL as a system interface
___________________________________________________________________
Babashka Clojure nREPL as a system interface
Author : Borkdude
Score : 97 points
Date : 2022-11-27 10:22 UTC (12 hours ago)
(HTM) web link (yogthos.net)
(TXT) w3m dump (yogthos.net)
| gemstones wrote:
| One nice thing about this setup is that it's not specific to
| Clojure/Lisp; any scripting language with a REPL will do this
| well:
|
| _Python:_ import subprocess import
| json def osquery(query): return
| json.loads(subprocess.check_output(["osqueryi", "--json",
| query])) #>>> osquery("select * from routes
| where destination = '::1'") #>>>
| [{'destination': '::1', 'flags': '2098181', 'gateway': '::1',
| 'hopcount': '0', 'interface': 'lo0', 'metric': '0', 'mtu':
| '16384', 'netmask': '128', 'source': '', 'type': 'local'}]
|
| _Node:_ const { execFile } =
| require("child_process"); async function
| osquery(query) { return new Promise((resolve, reject)
| => { execFile("osqueryi", ["--json", query], (error,
| out, _err) => { if (error) {
| reject(error); return; }
| resolve(JSON.parse(out)); }); }); }
| //> await osquery("select * from routes where destination =
| '::1'"); //> [ //> { //>
| destination: '::1', //> flags: '2098181', //>
| gateway: '::1', //> hopcount: '0', //>
| interface: 'lo0', //> metric: '0', //>
| mtu: '16384', //> netmask: '128', //>
| source: '', //> type: 'local' //> }
| //> ]
|
| _Ruby:_ require "open3" require "json"
| def osquery(query) out, err, exit_status =
| Open3.capture3("osqueryi", "--json", query) if
| exit_status != 0 raise err end
| return JSON.parse(out, symbolize_names: true) end
| #irb(main):1:0> osquery("select * from routes where destination =
| '::1'") #=> #[{:destination=>"::1", #
| :flags=>"2098181", # :gateway=>"::1", #
| :hopcount=>"0", # :interface=>"lo0", #
| :metric=>"0", # :mtu=>"16384", #
| :netmask=>"128", # :source=>"", #
| :type=>"local"}]
| user3939382 wrote:
| I hear near universal praise for repl development but in my very
| limited experience with it, found it nearly impossible. Maybe
| someone can clarify?
|
| What I saw was that the repl leads to a runtime state that is
| invisible and therefore hard to predict. For example, you define
| a function in the repl, or assign a value to a variable. You're
| just supposed to keep the existence of those declarations in your
| head? I must be missing something.
| nlitened wrote:
| > What I saw was that the repl leads to a runtime state that is
| invisible and therefore hard to predict
|
| I'd also add to what Borkdude said: it also helps that Clojure
| strongly encourages you to keep runtime state localized (not
| spread all over the places).
| nanomonkey wrote:
| In the case of Clojure and many other Lisps one makes changes
| to your source code, and evaluate each one of those changes
| automatically, or through some key command (ie highlighting the
| s-exp and evaluating it directly).
|
| This allows you to hot reload changes to the source code, or
| fire off events directly from your editor. In Clojure one often
| has commented out code that one can test functionality, or make
| state changes directly.
|
| Very little work is done at the REPL command line, instead it
| is fired off to the nREPL (network accessable REPL).
| TacticalCoder wrote:
| > For example, you define a function in the repl, or assign a
| value to a variable. You're just supposed to keep the existence
| of those declarations in your head?
|
| If you're using a LSP server, which btw uses the "clj-kondo"
| which borkdude mentioned, it's totally independent from the
| REPL and will tell you immediately if your source file is
| missing a function definition or a variable.
|
| Now it could be argued that you could have a wrong version of a
| function declared in the source file (and hence LSP / clj-kondo
| would still be happy) while the correct version got only
| defined at the REPL but...
|
| That's not how I develop: typically I test stuff at the REPL
| but only define my functions in the source file. And from the
| source file, I "eval" the function and its hence available
| directly in the REPL.
|
| Now I don't know about others but in my case I regularly write
| _anonymous_ functions at the REPL, which I test directly on
| some data at the REPL, and then I copy /paste the anonymous
| function to the source file and give it a name there.
| REPL> ((fn [x] (* x 2) 21) 42
|
| OK, good, it works now, I cut/past (fn[x] (* x 2)) to the
| source file and change the anonymous _fn_ to a _defn_.
|
| But I'll also sometimes just directly write the function in the
| source code file.
|
| In addition to that, unit tests can help too.
|
| So it's REPL + unit tests + LSP (which uses clj-kondo) and all
| three are totally independent.
|
| And yet although they're independent, when LSP tells me
| something like: _" Function x is called with only argument but
| expects two"_, I can fix it, eval the correct function, and the
| REPL is immediately aware of the correct version.
|
| I've always got both the REPL and the Clojure LSP server
| running, independently, simultaneously.
|
| > or assign a value to a variable.
|
| Clojure really tries to put the emphasis on functional
| programming so you don't typically have lots of mutable
| variables to juggle with. I'd say I have more of a "global
| application state" at the REPL than different variables.
|
| > I must be missing something.
|
| Maybe you're simply not aware that you can code in the source
| file, eval there, and the eval'ed functions are directly
| available from the REPL?
|
| I'm not sure my explanation are very clear but I hope it helps.
| Borkdude wrote:
| In Clojure, you don't typically type code into the REPL, but
| write code in a file and then evaluate that code in a REPL
| connected to your editor. We don't just type into a console
| window, then reboot for some OS updates and forget about our
| previous efforts :). Combining this with a static analysis tool
| / linter like clj-kondo will also help since it will remind you
| that you removed certain functions, while they may still be
| there in the REPL.
| sph wrote:
| Babashka looks great (and perhaps the one thing that will make me
| try Clojure. I am allergic to the JVM), and I didn't know of
| osquery.
|
| But am I blind, or is there no documentation of what osquery
| modules/tables are available?
|
| https://osquery.readthedocs.io/en/stable/
|
| EDIT: rewritten the comment so it's less of a rant
| hiyer wrote:
| The list of tables is available here -
| https://www.osquery.io/schema/5.5.1/
| jwr wrote:
| > I am allergic to the JVM
|
| Ok, I have to admit I am "allergic" to this take. Why do you
| mind (or even care about) the JVM? Do you care about the
| innards of Python's VM, or any other language's runtime?
|
| Leaving aside which language you use on top, the JVM is likely
| the single most-developed and most-improved VM ever created.
| Uncounted bazillions of man-hours of development went into it.
| Corner cases were found, performance was tweaked, just-in-time
| optimization was implemented, novel garbate collectors were
| developed. It is an impressive piece of machinery, which is why
| I find it slightly annoying when it gets a dismissive treatment
| "just because".
|
| Of course I might be wrong and you might just be that person
| that spent the last three weeks chasing an obscure JVM issue
| that happens in 0.01% percent of production servers, in which
| case you do have legitimate reasons for being "allergic" to the
| JVM.
| bmitc wrote:
| I can speak to this a little, as I have the same aversion to
| the JVM. Despite wanting to get into Clojure multiple times,
| I always get hung up on getting going with it. How do I
| install Java? Is this the "right" Java? How do I now install
| Clojure? Which project management thing do I use? There's
| this Leiningen thing but also this new Clojure CLI. Then it
| comes to IDEs, and they all work rather differently.
|
| The first time I tried Clojure, I tried with Leiningen, but
| it dumped literally hundreds of lines of Java stack traces
| when something went wrong. So I stopped.
|
| As a comparative example, how do I install F#? Well, you
| install the .NET SDK, and then you get F# automatically. When
| something goes wrong, I get good error messages that are
| tailored to F#.
|
| I think it's a little misleading to ask "why do you care
| about the JVM?" because the answer is that "Clojure makes you
| care about the JVM".
|
| Of course, maybe it's me. But I have no trouble using F#,
| Racket, Elixir, Erlang, or several other languages. Yet, I
| have struggled every time to get going with Clojure.
| __jem wrote:
| I don't mean to deny your experience or sound rude, but it
| genuinely baffles me that you would have difficulty
| installing Java. I do not understand how it is different
| than installing literally any other programming runtime.
| How is installing the .NET SDK any easier than installing
| Java?
| bmitc wrote:
| That's not exactly what I said though. For Java in
| particular, is it Oracle JDK or OpenJDK, what's the
| difference, and why should I care? The latter is the same
| sentiment of the person I responded to. I don't care, but
| I'm presented with the different options depending upon
| which Clojure install guide I am following.
|
| It's really the experience in totality. There are
| choices, but for someone new to the Java ecosystem, it's
| confusing why and why should I care. Because in the end,
| I don't care. I just want to use Clojure, but there's
| decisions to be made at every step of getting going that
| aren't clear to someone new to the ecosystem.
|
| This same thing happened with .NET as well. At one point
| in time, there was .NET Framework, .NET Core, and Mono
| and a question of how to get F# in all that. That was
| just as, if not more so, confusing. However, it's since
| been cleared up: install .NET 6 or higher.
| kaba0 wrote:
| > For Java in particular, is it Oracle JDK or OpenJDK,
| what's the difference, and why should I care?
|
| I know it's mostly about a sentiment, but if you or
| anyone is curious -- there is basically none, OracleJDK
| is a fork of OpenJDK (which is the reference
| implementation) with basically negligible changes.
| License wise OpenJDK uses the same one as Linux so you
| can use it as you seem fit, while the current LTS
| OracleJDK (17) is free to use until the next LTS release
| + 1 year, but unless you need corporate support, you
| really have no need for that.
| kaba0 wrote:
| <your-pkg-manager> install openjdk
|
| Pretty much whatever you do, you will get OpenJDK (all
| these options are forks with minuscule changes for the most
| part). If you do happen to need multiple JDKs I can
| recommend sdkman. But I think the java platform is pretty
| suckless, especially that it has probably the very best
| backwards compatibility.
| user3939382 wrote:
| I have an irrational fear of it because of the days in the
| late 90s/early 2000s when Windows desktop software would
| sometimes require booting a Java VM which guaranteed two
| things: the UI would be weird / not native, and the boot time
| would be super slow. I'm still scarred.
| [deleted]
| the-alchemist wrote:
| That's fair. I remember those damn Java applets that froze
| the entire computer for a minute while they started.
|
| But that was 20-30 years ago, literally. A few things
| happened: SSDs, and Java startup time.
|
| A warm-start Java "Hello World" is 200-300ms. A babashka
| (bb) "Hello World" is 30-40ms, which is faster than Python3
| "Hello World" (40-50ms).
| askonomm wrote:
| I'd still say that even today Java desktop apps are much
| slower, laggier and generally still look worse than their
| native counterparts. It's just that, yes, hardware is so
| much better which sort of hides most of the Java
| problems.
| kaba0 wrote:
| Uglier is relative, but I will give you that neither
| unthemed Swing or JavaFX are too fine looking.
|
| But I would say that e.g. IntelliJ looks quite good and
| that is a basic theme available without much tweaking,
| plus it can be very snappy (when jetbrains doesn't ship
| it with a decade old JVM with shitty default settings. It
| is fixed in recent versions).
| sph wrote:
| I did not expect anyone to be offended because I have never
| been a fan of the Java world. I have no real reasons, never
| had a need to use the language, I always saw it overly
| verbose and associated with boring corporate culture and
| didn't enjoy my time configuring Tomcat and other Java
| projects 15 years ago.
|
| I am well aware it is a very productive ecosystem, though I
| feel I am entitled to like or dislike any technologies I wish
| to, however irrational it might be. It was a figure of speech
| mostly intended as tongue-in-cheeck, not a statement of fact
| that I need to defend.
| __jem wrote:
| I mean, you said you were allergic to the JVM, not to Java
| syntax. Those are clearly different things, and especially
| nonsensical in this context as Clojure is not Java (indeed
| Clojure tends to be one of more terse languages in
| practice).
___________________________________________________________________
(page generated 2022-11-27 23:01 UTC)