The functional paradigm is a bit uncomfortable at first, but it does make problem solving feel... different. I personally find OOP to be the most intuitive for large scale systems design, but that's just me.
Most models do not perform particularly well in Clojure, but OpenAI models fully utilize the power of the language. Subjectively, it kind of seems to match the personality. Data at https://gertlabs.com/rankings?provider=openai
As everyone knows, you are not a true lisper until you have written your own static site generator.
It gave me such a great high with how easy it was to add my own "templating engine" on top, implemented all using macros. The downside is that the crash came hard; there is so much more to a good static site generator such as optimizing the output, supporting scoped CSS, server-side rendering of SPA framework components, and of course integration with the Node ecosystem (for better or for worse there is just so much useful stuff). I have since moved over to Astro. It's still fascinating how far I was able to push my own SSG all by myself though.
Funny, learning Janet I exactly did that. Was quite a fun experience with the built-in PEG, so I did markdown parsing from scratch. Maybe eventually I will be a true lisper (fell in love with Scheme over 20 years ago but could never really use any lisp professionally. Now I at least do some small things in Clojure and babashka. I love babashka)
> As everyone knows, you are not a true lisper until you have written your own static site generator.
I think that part is quite normal. I use ruby for the same purpose,
though the only difference is that the code I use is also to be
used for dynamic websites at the same time (cgi, rack, sinatra, in
theory ruby on rails but I just can't stand rails and DHH these
days, so I am in the opposition crowd). Using static websites, though,
always feel as if I have significantly less flexibility. I do generate
some static .html files as well, but they feel less useful to me, aside
from being displayed faster, of course.
With respect, this topic in particular has been beaten to death.
I too liked Clojure when I tried it some years ago (agreed on the composition and data structures; both are _great_). But the real value-add is in the runtime, not the syntax. Java has a solid runtime but it's not yet as good as Erlang's, maybe even not up to the standards of Golang -- I am talking concurrency / parallelism here (for memory management I have no doubts Java is very good). And I know: green threads and stuff. Well, call me when you can do what Erlang / Golang can do. Then I'll look again, very seriously too.
Programming language syntax scarcely matters. It does to some extent but we the programmers tend to over-romanticize it. The runtime and its properties are the much better thing to optimize for.
> the real value-add is in the runtime, not the syntax. Java has a solid runtime but it's not yet as good as Erlang's, maybe even not up to the standards of Golang
won't lie, this is hilarious. you got me from nodding along to being the spitting out food meme guy in a span of couple seconds.
JVM runtime is undeniably the most well researched and optimized runtime in history of runtimes, specifically in realm of concurrency and parallelism, it literally carries like half the world on it's back.
not to throw any shade on erlang vm - i've been a fan for well more than a decade, but other than making some interesting, but limited in practice, tradeoffs with regard to concurrency architecture, it doesn't really offer much more.
go's runtime is just a different beast altogether designed with different goals in mind and with no baggage of backward compatibility with legacy.
one particular detail i'm very grateful to Clojure for, is exactly the ability to use JVM runtime without having to touch any Java.
> Programming language syntax scarcely matters
on the contrary, it matters quite a lot.
you might be drinking some of that AI koolaid, conflating our suddenly hypertrophied abilities to produce code regardless of our familiarity with the syntax or the APIs with ability to produce and deliver good quality products, but this delusion is getting reality check as we speak.
a realization is propagating through the industry that being able to produce more code than you're able to review, comprehend and internalize is actually not a great thing.
and that's where syntax matters - it has to be high signal/noise, it has to expose you to right abstractions and it has to be pliable to allow the codebase reflect the problem in a way that minimizes cognitive load both during production and during consumption.
LLMs are language models and syntax is a crucial part of any language.
> With respect, this topic in particular has been beaten to death.
Yes and no. From the discussion here I've learned about the existence of jank, which wouldn't have come up a year or so ago and might be an interesting solution to a problem for me as it evolves (that problem mainly being me not wanting to use C++ or any of the other directly supported languages in a plugin ecosystem). So these things are worth bubbling up every now and again just for the discussion to have a chance to play out.
The JVM is perfectly capable of Golang-style green threads now. As for Erlang, the creator of Clojure have commented in the past on why he dislikes the Actor model, and I think it is a fair criticism. Sometimes I see people praising Erlang VM as some panacea in which all the VMs should strive to be like. This is overly simplistic in my opinion, and ignores the huge trade-offs that the Erlang VM has.
I think one of Clojure's main strengths for concurrency / parallelism is structural sharing of immutable data across threads, which you simply cannot do in Erlang.
Other than that, I agree, CL is baroque yet needs some hole filling here and there.
> Lisp: everything is a list
But that's wrong. Not even a little. Unless you mean LISP 1.5...
> Too much syntax
Funnily, I'm mostly okay with the new vector/set/hash-table literals, my big problem and that of some other people is the use of vectors in macros/special operators instead of lists. `(let [a b] ...)` instead of `(let (a b) ...)` is _not_ okay.
> `(let [a b] ...)` instead of `(let (a b) ...)` is _not_ okay
it is however quite consistent, clojure uses vector form for most macros that require a "control" form before a "data" form: argument list in defn, names list in let, iteration descriptors in for, etc. you get used to consistency quite easily.
Clojure’s abstraction is a bit more far-reaching than Common Lisp’s SEQUENCE, implemented as interfaces rather than types.
A Clojure sequence is anything “seqable” (either implements the Seqable interface, or special case handling for host platform collections), not just lists and vectors. Hash maps, sets, Java Iterables, etc. are all seqable and work with the same standard collection functions.
e.g. you can `(map (fn [[k v]] …) {:a 1 :b 2})`, rather than needing a separate MAPHASH function.
I wonder if the author is familiar with Smalltalk - it has a very small syntax. In some ways so does Lisp, in other ways it has more than every other language, depending on what you think about operators versus functions.
Once you learn Clojure's syntax and semantics, you're no longer bound to the JVM. There's ClojureScript (JS), ClojureCLR, ClojureDart, jank (C++), Basilisp (Python), babashka (SCI), and many others. This means that, if you don't know Java or don't like the JVM, you can likely use Clojure wherever you already feel most comfortable.
For the most part, any Clojure code which doesn't use host interop will work on all dialects. Clojure also has support for conditional code, depending on the current dialect.
The page you have tried to access is not available because the owner of the file you are trying to access has exceeded our short term bandwidth limits. Please try again shortly.
Details:
Actioning this file would cause "www.acdw.net//clojure/" to exceed the per-day file actions limit of 80000 actions, try again later
;; This is real syntax!
(loop for k being the hash-keys
using (hash-value v) of hash-table
...)
Still lisp. Although the blog author has a point -
clojure is probably cleaner lisp than common lisp.
I think the issue is heavily due to syntax though.
Naturally the (())()()()(), but I think even aside
from the (), the syntax does not seem super-efficient
to me. Perhaps I have spent too much time with ruby
and python, but it feels as if lisp is a legacy
regression, purely syntax-wise.
Paredit / Parinfer ruined other languages for me. It lets you navigate up/down/in/out of the Clojure AST with keyboard commands and mutate those expressions, e.g. "Split" will split open the current data structure you're in: `(a| b)` =Split=> `(a)| (b)`, where | is caret. Join is the inverse, and it works for all data structures.
I spent a week with Clojure and coming from other functional languages my problem was not Clojure, it was dynamic typing. I got strange bugs in the standard library because I accidentally sent in nested incompatible instances of objects and it was really hard to figure out what was wrong in a quick way. With typesafe languages you are stopped at compile time.
> The page you have tried to access is not available because the owner of the file you are trying to access has exceeded our short term bandwidth limits. Please try again shortly.
>
> Details:
> Actioning this file would cause "www.acdw.net//clojure/" to exceed the per-day file actions limit of 80000 actions, try again later
37 comments
[ 2.9 ms ] story [ 60.8 ms ] threadMost models do not perform particularly well in Clojure, but OpenAI models fully utilize the power of the language. Subjectively, it kind of seems to match the personality. Data at https://gertlabs.com/rankings?provider=openai
As everyone knows, you are not a true lisper until you have written your own static site generator.
It gave me such a great high with how easy it was to add my own "templating engine" on top, implemented all using macros. The downside is that the crash came hard; there is so much more to a good static site generator such as optimizing the output, supporting scoped CSS, server-side rendering of SPA framework components, and of course integration with the Node ecosystem (for better or for worse there is just so much useful stuff). I have since moved over to Astro. It's still fascinating how far I was able to push my own SSG all by myself though.
I think that part is quite normal. I use ruby for the same purpose, though the only difference is that the code I use is also to be used for dynamic websites at the same time (cgi, rack, sinatra, in theory ruby on rails but I just can't stand rails and DHH these days, so I am in the opposition crowd). Using static websites, though, always feel as if I have significantly less flexibility. I do generate some static .html files as well, but they feel less useful to me, aside from being displayed faster, of course.
I’m not quite sure what this means. How is it different/worse than all parens..?
fyi I use paredit and just hit ) and it moves me past any kind of paren/bracket. But even without that you can just hit left and right..?
I too liked Clojure when I tried it some years ago (agreed on the composition and data structures; both are _great_). But the real value-add is in the runtime, not the syntax. Java has a solid runtime but it's not yet as good as Erlang's, maybe even not up to the standards of Golang -- I am talking concurrency / parallelism here (for memory management I have no doubts Java is very good). And I know: green threads and stuff. Well, call me when you can do what Erlang / Golang can do. Then I'll look again, very seriously too.
Programming language syntax scarcely matters. It does to some extent but we the programmers tend to over-romanticize it. The runtime and its properties are the much better thing to optimize for.
won't lie, this is hilarious. you got me from nodding along to being the spitting out food meme guy in a span of couple seconds.
JVM runtime is undeniably the most well researched and optimized runtime in history of runtimes, specifically in realm of concurrency and parallelism, it literally carries like half the world on it's back.
not to throw any shade on erlang vm - i've been a fan for well more than a decade, but other than making some interesting, but limited in practice, tradeoffs with regard to concurrency architecture, it doesn't really offer much more.
go's runtime is just a different beast altogether designed with different goals in mind and with no baggage of backward compatibility with legacy.
one particular detail i'm very grateful to Clojure for, is exactly the ability to use JVM runtime without having to touch any Java.
> Programming language syntax scarcely matters
on the contrary, it matters quite a lot.
you might be drinking some of that AI koolaid, conflating our suddenly hypertrophied abilities to produce code regardless of our familiarity with the syntax or the APIs with ability to produce and deliver good quality products, but this delusion is getting reality check as we speak.
a realization is propagating through the industry that being able to produce more code than you're able to review, comprehend and internalize is actually not a great thing.
and that's where syntax matters - it has to be high signal/noise, it has to expose you to right abstractions and it has to be pliable to allow the codebase reflect the problem in a way that minimizes cognitive load both during production and during consumption.
LLMs are language models and syntax is a crucial part of any language.
All Clojure (lisps) do is remove the stupidity of syntax.
Even if syntax is the minor thing, why wear a stupid, uncomfortable shirt while running when you could wear one so comfortable you scarcely feel it?
Yes and no. From the discussion here I've learned about the existence of jank, which wouldn't have come up a year or so ago and might be an interesting solution to a problem for me as it evolves (that problem mainly being me not wanting to use C++ or any of the other directly supported languages in a plugin ecosystem). So these things are worth bubbling up every now and again just for the discussion to have a chance to play out.
Eh? That's completely lifted from CL (https://www.lispworks.com/documentation/HyperSpec/Body/t_seq...). Same for AREF/NTH, there's ELT.
Other than that, I agree, CL is baroque yet needs some hole filling here and there.
> Lisp: everything is a list
But that's wrong. Not even a little. Unless you mean LISP 1.5...
> Too much syntax
Funnily, I'm mostly okay with the new vector/set/hash-table literals, my big problem and that of some other people is the use of vectors in macros/special operators instead of lists. `(let [a b] ...)` instead of `(let (a b) ...)` is _not_ okay.
it is however quite consistent, clojure uses vector form for most macros that require a "control" form before a "data" form: argument list in defn, names list in let, iteration descriptors in for, etc. you get used to consistency quite easily.
Clojure’s abstraction is a bit more far-reaching than Common Lisp’s SEQUENCE, implemented as interfaces rather than types.
A Clojure sequence is anything “seqable” (either implements the Seqable interface, or special case handling for host platform collections), not just lists and vectors. Hash maps, sets, Java Iterables, etc. are all seqable and work with the same standard collection functions.
e.g. you can `(map (fn [[k v]] …) {:a 1 :b 2})`, rather than needing a separate MAPHASH function.
Tcl: everything is a string
Lisp: everything is a list"
Python: {"everything":"dictionary"}
For the most part, any Clojure code which doesn't use host interop will work on all dialects. Clojure also has support for conditional code, depending on the current dialect.
This is one of Clojure's superpowers.
Correct me if I'm wrong, but isn't babashka's "host"... um.. "native", for lack of a better word? It's compiled with Graal VM native, no?
Yes, there is SCI (Small Clojure Interpreter) in the middle, but that's beside the point, no?
https://github.com/babashka/babashka
https://github.com/babashka/sci
The page you have tried to access is not available because the owner of the file you are trying to access has exceeded our short term bandwidth limits. Please try again shortly. Details:
Actioning this file would cause "www.acdw.net//clojure/" to exceed the per-day file actions limit of 80000 actions, try again later
This is why I am found of the community, the symbiotic approach of two language communities working together.
I think the issue is heavily due to syntax though. Naturally the (())()()()(), but I think even aside from the (), the syntax does not seem super-efficient to me. Perhaps I have spent too much time with ruby and python, but it feels as if lisp is a legacy regression, purely syntax-wise.
If he means navigating the AST, there is Parinfer: https://shaunlebron.github.io/parinfer/
Paredit / Parinfer ruined other languages for me. It lets you navigate up/down/in/out of the Clojure AST with keyboard commands and mutate those expressions, e.g. "Split" will split open the current data structure you're in: `(a| b)` =Split=> `(a)| (b)`, where | is caret. Join is the inverse, and it works for all data structures.
Going back to code as bunch of carefully arranged ascii chars feels like a regression.
> Too Many Requests
> The page you have tried to access is not available because the owner of the file you are trying to access has exceeded our short term bandwidth limits. Please try again shortly.
>
> Details:
> Actioning this file would cause "www.acdw.net//clojure/" to exceed the per-day file actions limit of 80000 actions, try again later
Can't even reply inline and have to reply in the main thread.
I found them informative.
Lots of Clojure haters here I guess?
[0] https://news.ycombinator.com/item?id=48375393#48387700
[1] https://news.ycombinator.com/item?id=48375393#48387382