25 comments

[ 4.4 ms ] story [ 67.6 ms ] thread
Also recommend checking out Fennel https://fennel-lang.org/
Projects like these motivate me to finally start learning emacs and move on from VSCode. That would be my third attempt...
Doom Emacs is worth a try. Comes with Vim bindings by default but these can be disabled.

https://github.com/hlissner/doom-emacs#doom-emacs

I recently moved to doom-emacs, and I love it. I had been piecemealing together an emacs config for a few years, and sometimes it was fun and sometimes frustrating. But, doom-emacs has so many of the things I need already, and adding a new packages is the same as adding them to regular emacs if you need something it doesn't already have.
Yeah, I had the same (also with the i3 window manager and the fish shell): it came with sane[1] defaults to allowed me to chuck out my previous big, grown-over-the-years config and start over much smaller.

[1] very subjective but they were mostly similar to my tastes

If it helps - I moved from Emacs to VSCode. It's not as simple as "objectively better you just need to know how".

I had invested a lot of work into my emacs config in order to get things working in a usable way. The problem is that every new thing I added needed a whole lot more work. VSCode plugins usually work pretty well out of the box - e.g. I just installed the Elm plugin and it was working immediately with errors shown inline, autocomplete etc. If I had been able to get that going well in Emacs in less than an hour or two I'd have been pleasantly surprised.

VSCode also has two things that Emacs doesn't. Live workspace sharing so you can pair program remotely (it's fantastic) and the ability work on a repo that's the other end of an SSH link (yes Emacs has tramp, not it's not in the same league). The SSH stuff works amazingly seamlessly, it's been my primary development mode since the start of pandemic.

One proviso I will give to my Emacs opinions is that the Language Server Protocol was only just beginning to come in when I switched away. That abstraction level is exactly what Emacs needs (particularly given the threading restrictions) and a lot of language setup might be easier and more uniform if you can take advantage of it.

I think Lumen is also the name of a WASM-based BEAM implementation or something along those lines so I was very confused here
Don't worry, it is also something related to Laravel. These things happen :)
Lumen is also the name of a new Unreal Engine feature.
I have had this discussion with (I believe) one of the maintainers of lumen before: but why the paren-free let?

In the beginning of my lisp journey I would have probably jumped on this, but then I found SRFI-71 that extends the regular scheme let with multiple values support in a backwards compatible way. I myself extended SRFI-71 in a small project with support for pattern matching in the multiple values form.

None of this would have been possible using a clojure-style let.

Clojure's style *let* is probably a limitation of the JVM's inability to do proper tailcalls.
You must have misunderstood. I was referring to the binding syntax. Clojure does

    (let [a 5 b 6] ...)
whereas scheme and common lisp does

   (let* ((a 5) (b 6)) ...)
SRFI-71 trivially extends this to do multiple values:

    (let ((a b (produces-2-values X y))) ...)
Which I extended to to pattern matching:

    (let ((a (head . tail) (produces-an-atom-and-a-list ...))) ...)
Clojure absolutely supports this. (let [[a b] lst]) will destructure lst, binding a as the first element and b as the second. The destructuring then recurses to implement your second example.
That was not my complaint.
Well, OK then. Rereading your post hasn't made it clearer.
I never claimed clojure couldn't do destructuring. That should be pretty clear. My complaint is that it isn't extensible without resulting to syntax that is very unlispy.

My complaint is the de-parenification of let. Why this form? It is easier to type, maybe, but visually it removes the distinction between binding, and makes any future extensions (like if clojure would gain multiple value support - however unlikely) impossible.

The strength of it is clearly visible SRFI-71 for scheme. Regular old let was trivially extensible to handle multiple values. And I trivially extended that to have pattern matching, without breaking any backwards compatibility.

I don't think it's just the syntax that's a roadblock - Clojure is not intended to be extensible in that way. For better or worse, it has batteries included and is highly opinionated.

From that perspective, including parens in let just to enable some hypothetical extension makes no sense.

> None of this would have been possible using a clojure-style let.

Why? Clojure already supports pattern matching in its `let`, e.g.

    (let [[head & tail] (produces-a-list)] ...)
That was not my complaint. My complaint is that the [id expr id expr ...] form has no benefits except for people disliking parens at the cost of making the let for impossible to extend in a backwards compatible way.

SRFI-71 for scheme extends let with support for values, like so:

    (let ((q r (quotient/reminder 10 3))) ...)
This for is then also extensible (I have added pattern matching on top of it).

Clojure's is not.

    (let [q r (hyptohetical-2-value-quotient/reminder 10 3)] ...)
Makes no sense in clojure.
In Clojure land we're more picky about paren usage and we're used to variants of let that are named explicitly. if-let, when-let, reagent/with-let, letfn, etc.
I would say that all of those are different than what I am saying (if-let and it's ilk are a conditional form.

But sure. Rich has done many great decisions with regards to clojure. This part is one of the few I don't agree with (and maybe regular bit-tries instead of rrb-trees).

“Lumen was conceived and designed with Daniel Gackle”, Daniel Gackle is Dang on HN! Good job Dang!!