6 ms·
From (2016) at least. https://web.archive.org/web/20161219045343/https://clojure.org/reference/transducers https://web.archive.org/web/20161219045343/https://c
by thih9 6mo ago
From (2016) at least.
https://web.archive.org/web/20161219045343/https://clojure.org/reference/transducers https://web.archive.org/web/20161219045343/https://clojure.o...
- adityaathalye 6mo agoI'd reckon most of Clojure is from ten years ago. Excellent backward compatibility, you see :) cf. https://hopl4.sigplan.org/details/hopl-4-papers/9/A-History-of-Clojure https://hopl4.sigplan.org/details/hopl-4-papers/9/A-History-...
- whalesalad 6mo agoIt's a blessing and a curse that zero innovation has occurred in the Clojure space since 2016. Pretty sure the only big things has been clojure.spec becoming more mainstream and the introduction of deps.edn to supplant lein. altho I am still partial to lein.
- seancorfield 6mo agoClojure 1.9: Spec. Clojure 1.10: datafy/nav + tap> which has spawned a whole new set of tooling for exploring data. Clojure 1.11: portable math (clojure.math, which also works on ClojureScript). Clojure 1.12: huge improvements in Java interop. And, yes, the new CLI and deps.edn, and tools.build to support "builds as programs".
- whalesalad 6mo agoThings have surely happened and the language has improved, but would you consider any of this to be innovative?
- jwr 6mo agoHmm. I'm not sure what you are looking for — myself, I write software that supports my living, and I'm not looking for thrills. What I get with Clojure is new concepts every couple of years or so, thought through and carefully implemented by people much smarter than me, in a way that doesn't break anything. This lets me concentrate on my work and deliver said software that supports my living. And pay the bills.
- waffletower 6mo agoBabashka is definitely innovative and useful
- whalesalad 6mo agoAgreed, that is huge for the ecosystem. I have a side project actually that has a unified codebase: central library and api server in clj, and the cli client is babashka.
- iLemming 6mo ago> would you consider any of this to be innovative? JS got optional chaining, nullish coalescing, async/await, decorators, pattern matching proposals - all borrowed from other languages. Python got type hints (borrowed), structural pattern matching (borrowed from ML/Haskell), walrus operator. Rust got async/await (borrowed). Go got generics (very late, borrowed from everywhere). Almost every "feature addition" in any mainstream language since roughly 2010 is a synthesis or import from prior art - usually from ML, Haskell, Lisp, or Smalltalk lineages. Comparatively, there's been quite some good amount of innovation in Clojure-sphere. Anyone who ever tried Hyperfiddle/electric, generated tests based on Specs or Malli, or even used nbb for scripting - knows that. So let's either apply pressure everywhere equally, or nowhere. What's your point of singling out Clojure? Are you asking for a higher standard being applied because of Clojure's stated philosophy (simplicity and careful design, etc.), or this is a proxy complaint about something else?
- vaylian 6mo agoAnd we can look forward to Jank https://jank-lang.org/ https://jank-lang.org/
- pjmlp 6mo agoYes, although if one cares about Jank, they can also use a traditional Common Lisp or Scheme compiler, if compatibility with existing Clojure code isn't a requirement.
- iLemming 6mo ago> zero innovation has occurred in the Clojure space since 2016. Oh, really? Zero, eh? clojure.spec, deps.edn, Babashka, nbb, tap>, requiring-resolve, add-libs, method values, interop improvements, Malli, Polylith, Portal, Clerk, hyperfiddle/electric, SCI, flowstorm ... Maybe you should've started the sentence with "I stopped paying attention in 2016..."?
- instig007 6mo ago> clojure.spec Tape-patches for self-inflicted language design issues isn't innovation, lol
- iLemming 6mo ago> lol Joke's on you. You seem to be so invested in moving in a single direction that you developed "an expert blind spot". Have you ever thought that it's possible that the knowledge you've so far "accumulated" has become an obstacle to seeing simpler or orthogonal ideas clearly? Every type system, schema library, and validation tool in every language is in some sense "patching" the lack of built-in guarantees. Haskell's typeclasses patch the lack of ad-hoc polymorphism. Rust's borrow checker patches the lack of memory safety. Python's type hints patch the lack of static types. You can retroactively frame any additive language feature as patching a prior omission - it's not an argument, it's a framing choice. Spec isn't even so much about patching - it's about runtime generative testing, instrumentation, and data specification in a dynamic context where static types would be the wrong tool anyway. That's a genuine design space with genuine ideas in it, regardless of whether you like dynamic typing. You just can't see it, because you already have decided "isn't innovation, lol", etc. One more reason to love the language is its community. I appreciate that Clojurians engage with diverse ideas from different tools and languages, freely borrowing the best ones without prejudice, owing to their deep and widespread understanding of language design. And they do it with the focus on pragmatism. Something maybe we can learn from them, even if we don't like the language and tools they make.
- instig007 6mo ago> Every type system, schema library, and validation tool in every language is in some sense "patching" the lack of built-in guarantees. > Spec isn't even so much about patching - it's about runtime generative testing, instrumentation, and data specification in a dynamic context where static types would be the wrong tool anyway. it's amazing what people can claim when they don't have to prove it. But I wonder, how exactly does your runtime generative tests are different from statically derived strategies that I get via QuickCheck or Validity? > And they do it with the focus on pragmatism "pragmatism" is defined in terms of values that one desires to practice. I am in no position to argue that your and their desires don't exist, but please don't claim that their preferences of transducers and schemas are somehow more pragmatic just because they ignored types and effectful/pure evaluation distinction in their language philosophy.
- JoshCole 6mo agoI know others already pointed out a ton of things, but having worked with Clojure in 2016 and doing active Clojure development for my startup now I feel like I have to chime in too. In 2016, Clojure was not great for serious data science. That has changed substantially and not just via Java Interop. - It now has cross ecosystem GPU support via blueberry libraries like neanderthal, which in benchmarking, outperform some serious Java libraries in this space. - It has columnar indexed JIT optimized data science libraries via cnuernber and techascent part of the Clojure ecosystem. In benchmarking they've outperformed libraries like numpy. - The ecosystem around data science is also better. The projects aren't siloed like they used to be. The ecosystem is making things interoperate. - You can now use Python from Clojure via the lib-pythonclj bindings. In general, CFFI is a lot better, not just for Python. - The linters are way better than they used to be. The REPL support too. Clojure already had one of the best efficiency scores in terms of code written to what is accomplished, but now you also get REPL integration, and LLMs have been increasingly capable of leveraging that. There are things like yogthos mycelium experiments to take advantage of that with RLLM calls. So its innovating in interesting new ways too, like cutting bugs in LLM generated code. It just doesn't feel true to me that innovation isn't occurring. Clojure really has this import antigravity feel to it; things other languages would have to do a new release for, are just libraries that you can grab and try out (or maybe that's the python)
- uxcolumbo 6mo agoCan you talk more about why you chose CLJ for datascience / ML. Are there any benefits of using it over Python? And how is the interop with Python libs?
- JoshCole 6mo ago> Can you talk more about why you chose CLJ for datascience / ML. I use Python for a lot of machine learning. My vision transformers, for example, are in Python. There is a lot to like about the Python ecosystem. Throwing away libraries like ablumentations and pytorch because you move to a different ecosystem is a real loss. You probably ought to be using Python if you're doing machine learning of the sort that one immediately thinks of when they see ML. That said, data science and machine learning are words that cover a lot of ground. Python often works because it serves as glue code to more optimized libraries. Sometimes, it is annoying to use it as glue code. For example, when you're working on computational game theory problems, the underlying data model tends to be a tree structure and the exploration algorithm explores that tree structure. There is a lot of branching. Vanilla python in such a case is horrifically slow. I was looking at progress bars in tqdm reporting 10,000 years until the computation was done. I had already reached for numba and done some optimizations. Computational game theory is quite brutal. You're very often reminded that there are less atoms in the universe than objects of interest to correctly calculating what you want to calculate. Most people use C, C++, and CUDA kernels for the sort of program I was writing. Some people have tried to do things in Python. > Are there any benefits of using it over Python? There is an open source implementation of a thing I built. It solves the same problem I solved, but in Python and worse than I solved it and with a lot of missing features. It has a comment in it, discussing that the universe will end before the code would finish, were it to be used at the non-trivial size. The code I wrote worked at the non-trivial size. Clojure, for me, finished. The universe hasn't ended yet. So I can't yet tell you how much faster my code was than the Python code I'm talking about. > And how is the interop with Python libs? Worked for me without issue, but I eventually got annoyed that I had to wait for two rounds of dependency resolution in some builds. Conda builds can sometimes have issues with dependency resolution taking an unreasonable amount of time. I was hitting that despite using very few libraries.