Hacker Newsnew | past | comments | ask | show | jobs | submit | hlship's commentslogin

I've been working in Clojure now for about 12 years. Maybe 12+ years of Java prior to that.

I've created some great apps, and great libraries (in both Clojure and Java).

I often describe Clojure as "the least worst programming language", which is an off-handed complement, but I think accurate. Things you don't like can generally be fixed (at least locally) using macros and libraries. The core is strong, a good basis for building things ... and as described all over this thread, stable.

As you master your tools, you gain a level of speed and precision in your work that I have not found elsewhere. The REPL-oriented workflow is a central value proposition in Clojure, and many features (and a few limitations) of the language exist to properly support it.

Working in Clojure feels like I'm working "with" my code, molding it like clay. My prior experiences in Java and Objective-C were so much slower, with long code-compile-test-debug cycles that are compressed down to instantaneous responses in the running REPL.


I gave Clojure a shot some years ago and even wrote an important tool used daily by all employees at our company in Clojure. The problem for me was maintenance. If I had to make any change to that code, I had to dive into the REPL just to understand it. Whereas with something like Java, even if something is poorly written and not documented, I can get at least a minimum understanding of the code just looking at the types.

I've been working on a large modern Java application lately and have never really felt the need for a REPL workflow even after having been exposed to it in Clojure. I tend to structure my Java code so it can be easily unit-testable and then just run the suite of unit tests (several thousand) in a few seconds as needed.


maintained a few clojure code bases at my old company for 10+ years

i find core.spec did wonders for that problem.

also, i have a tendency to write a lot of in-code documentation, whichever language i use. so it probably helps too.


Built a significant system in Clojure (from several smaller systems). Same experience.

I wish Hickey had built gradual typing in to the language.

I still love Clojure anyway.


What about core.typed. I find gradual type systems to be hard to work with for some reason.


core.typed main problem for many years was that it was maintained by 1 (busy) student.

i don't know about nowadays though, he probably has graduated long ago!

nowadays i'd just use core.spec/malli/other honestly (for what i use clojure for).


> Things you don't like can generally be fixed (at least locally) using macros and libraries.

What macro do I use to make it not run on the JVM? :)


That's one of it's best features!

But it runs on other things—Microsoft's CLR, Dart's runtime, JavaScript's runtime, Erlang's runtime, and with Jank, on top of LLVM.


Babashka!


Haven't worked much in Clojure, but I have the same experience with Common Lisp. The malleability and live image workflow is just very pleasant to work with.


Clojure is like that, but because data structures are default immutable, and all of the standard library (and the vast majority of 3rd party libraries) are also default immutable, the stress level is much lower.

You can still get mutability and I do this on every project. But it's a very small percentage of the code, less that 1%, and also well-defined.

Something like FlowStorm [0] isn't really practical in anything but Clojure, and things like Clerk [1] are easy and very natural.

[0] https://www.flow-storm.org/ [1] https://clerk.vision/


I know. What I just miss in other implementations is the live reflection in the SBCL REPL via Sly/Slime for example. And conditions.

When I do CL, I try to code it in a more immutable style and avoid things like self until I get my own version bootstrapped.


How does the REPL approach scale in very large codebases? I.e. code that talks to multiple services, complex configurations, etc..


Scales very well.

Immutable data pairs great with REPL.

Because data are immutable, you don't need to care about where that data come from and where it will go. Just focus on what you need to do with that data at the point you work.

Everything is localized due to immutability.


I’ve started learning clojure recently and I haven’t quite grasped the REPL yet. I really like it, but so far the type of feedback it provides feels similar (and sometimes inferior to) a static type system. I mostly use it as a tool for answering “wait what data does this return?” And of course trying functions as I’m building them.

Are there any tricks or habits you learn with the REPL that go beyond what a static type system gives you?


I worked with a 60K LOC thing* that talked to multiple services and had complex configuration. Ran fine on my laptop pointed at the company's dev env.

The REPL let me test my changes while inside the thing as it ran. No problems. Someone wrote a nice *recording* debugger too which helped immensely -- no more "oops, I'm past the interesting part and have to start over"

* in prod we usually give it a small number of large instances


Forgot to add: multiple threads ... multiple DBs ... multiple topics on more than one kind of message queue ... hitting and serving REST endpoints -- all no problem for the REPL and the debugger[0].

If the thing was in Java, each fix attempt would mean waiting for startup and state re-creation. And each successful debug could have meant multiple sessions (vs visiting any mix of spots in a single recording)

[0] https://www.flow-storm.org/


I use Integrant to make systems out of components that are tied together at runtime. I have the option of running real versions or mock versions in tests or the REPL, with config drawn from the environment or config files or parameters. I can boot or reboot any combination of components at will. It’s fairly easy to divide and conquer this way.


I like integrant, but I feel like a lot of the examples I see use it for each web endpoint, which seems like a massive amount of overkill to me. I tend to use it just for the router, but it sometimes feels like I'm not using the library to its full potential with that.


Do you have an example? On the face of it I agree that seems like a baffling thing to do.


Even better than in small ones, because you don't need to spend 60 seconds building and restarting the application after changing one line: You simply redefine a single function at runtime and them can test the effect immediately.



I played with Clojure just a bit in 2014 because I wanted to write GUIs in Om, and this gave me a seriously warped habit of calling React.el('div',...) for a while. Sorry not sorry.

I'm used to using TDD for fast feedback as I'm molding my code. Do you miss unit testing? Or, do you find that the REPL in no way obviates unit testing?

And, do you miss static typing?


REPL code is copy/pasted straight into tests. So really, REPL is for helping write tests.

BTW, when Clojurians talk about REPL, it's not about that separate window where you type and run the code as in other language such as python. They are talking about an invisible REPL running behind the scene, to which they send code within their editors, and the results show up in the editors too.

There's no need to "miss static typing" in Clojure. If I need static typing, I just write deprotocol and deftype in Clojure, as many Clojure libraries do.


Neither defprotocol nor deftype introduce static typing into Clojure. Errors in their usage are not checked statically and are only discovered at runtime.


No, defprotocol and deftype have the same properties as Java interface and Java classes, and the types are checked at compile time. This is static typing. Period. Clojure is a compiled language, it does check typing during compilation.


Protocols do not work like Java interfaces or classes. Their methods are compiled into regular functions which lookup the implementation to use at runtime based on the runtime type of the receiver. Compilation will check for the named function but doesn't do any further checking. Given the following protocol and implementation:

  (defprotocol P
    (method [this ^Integer i]))

  (extend-protocol P
    String
    (method [s i] (.substring s i)))
both (method "test" "call") and (method 1 2) will be accepted by the compilation phase but will fail at runtime.

Of course there's no requirement for Clojure code to be AOT compiled anyway so in that case any name errors will still only be caught at runtime when the compilation happens.

Type hinted bindings are only converted into a cast and are not checked at compilation time either e.g.

  (defn hinted [^String s] (.length s))
  (hinted 3)
will be accepted but fail at runtime.

deftype is only used for Java interop an is also not a form of type checking. The methods will be compiled into Java classes and interfaces, but the implementations defer to regular Clojure functions which are not type checked. You can only make use of the type information by referencing the compiled class files in Java or another statically typed language, using them from Clojure will not perform type checking.


deftype IS a Java class, it's not compiled into something else. What is a Clojure function? A Clojure function is a Java class. Clojure is a compiled language, so it does check types, just like Java check types.

So if you use defprotocol and deftype for every domain objects in your code, your code won't compile if there's a type error. Try it.

BTW, that's the way many Clojure libraries are implemented. These libraries rely on dispatch on type to work, so they are taking advantage of the type checking.

Of course, you will say, "oh, clojure is not normally AOT, so it's not dong the checks.", but that's another issue. The issue at hand is this: can you write Clojure such that types are checked at compile time. The answer is YES.

The compiler may run only when you run the program, that's a different issue. You are confusing these two issues.

If you want a separate compile stage, then basically you are already excluding runtime compilation, i.e. you are arguing against runtime compilation. So it's not really about typing, but about how you want to run the program. Isn't it? You want AOT for everything, you don't want runtime compilation. That's it. It has nothing to do with types.


Of course Clojure has to ultimately be compiled into a native format for the host platform, bytecode in the case of the JVM implementation, but that doesn't require type checking in the same way Java does.

Clojure functions are compiled into implementations of clojure.lang.IFn - you can see from https://clojure.github.io/clojure/javadoc/clojure/lang/IFn.h... that this interface simply has a number of overloads of an invoke method taking variable numbers of Object parameters. Since all values can be converted to Object, either directly for reference types or via a boxing conversion, no type checking is required to dispatch a call. With a form like

  (some-fn 1, "abc", (Object.))
the some-fn symbol is resolved in the current context (to a Var for functions defined with defn), the result is cast (not checked!) to an instance of IFn and the call to the method with required arity is bound. This can go wrong in multiple ways: the some-fn symbol cannot be resolved, the bound object doesn't implement IFn, the bound IFn doesn't support the number of supplied arguments, the arguments are not of the expected type. Clojure doesn't check any of these, whereas the corresponding Java code would.

Protocol methods just get compiled into an implementation of IFn which searches for the implementation to dispatch to based on the runtime type of the first argument, so it doesn't introduce static type checking in any way.


But if you add type hint in the signature, it does check the type. Basically, if you specify the type, it will check type. Just like any language that is not automatically inferring types, e.g. Java. So it is the same as Java.

You guys make it out like Clojure is doing something extra to hide Java types, but it doesn’t. What Clojure does is really minimal on top of Java. It barely hides anything.

If you give it type, it will check type. If you don’t give a type, it falls back to a default type, Object, which IS a TYPE. The fact that Clojure compiler cannot deal with GraalVM SVM Pointer type tells you that it’s checking type, because Pointer is not an Object! I found this out the hard way: https://yyhh.org/blog/2021/02/writing-c-code-in-javaclojure-...

“One limitation that one needs to be aware of when writing native image related Clojure code, is that most things in the GraalVM SDK inherit from org.graalvm.word.WordBase, not from java.lang.Object, which breaks the hidden assumption of a lot of Clojure constructs.”


I've already shown that type hints do not constitute type checking:

  (defn f [^String s] (.length s))
  (f 3)
is a valid Clojure program that fails at runtime with a cast error.

  class X { public static int f(String s) { return s.length(); } }
  X.f(3)
is not a valid Java program at all. Clojure compilation generates bytecode to dispatch dynamically and all but the most basic checks are handled at runtime by the JVM. This is fundamentally different to the static type checking that languages like Java and Scala do. It's not that Clojure is hiding something from Java, but rather that it isn't doing the considerable amount of effort the Java type checker does to analyse the program before execution. This is by design - Clojure has deliberately avoided adding a static type system in favour of things like spec.


So what happens at runtime if errors are found?


you get runtime errors with a long JVM stacktrace


If you paste into Claude, it will instantly tell you what's going on.


If the core team had ever addressed the decade of surveys showing that error messages/stacktraces were people's top complaints, you wouldn't need Claude.


Thank you, this is the most concise description I've seen for the REPL. That gets often lost due to the curse of knowledge.

It's a completely different thing to be coding "from within your running program" and it's hard to signal that to who has never tried.


> copy/pasted

When I've seen it done, it's seemingly executed in-place, which is very cool.


Not the OP but:

One can develop with TDD in Clojure quite smoothly depending on choice of tooling; with CIDER in Emacs there are keyboard shortcuts to run tests for the current namespace or the entire project, so feedback can be very fast (if your tests are fast). I've also used (some time ago) test runners that stay running and re-test when a file is saved.

In fact, it can be nice to do one's explorations in the REPL and then reify one's discoveries as tests.

Regarding types: I will say that working on larger Clojure (and Python) projects with somewhat junior teams made me more curious about type systems. Clojure's immutable collections and the core abstractions they are built around are great, but it can take some skill and discipline to keep track of exactly what kind of data is flowing through any particular part of your program. But, there is some support for à la carte strictness in the language via Spec, Malli, structured types, etc.


> In fact, it can be nice to do one's explorations in the REPL and then reify one's discoveries as tests.

This is how I wrote unit tests when I worked on Mathematica: try out every edge cases of the function in a notebook, and then use a tool to extract all the input/output cells and convert them to tests. I didn't know the term reify for this practice, I like it!


Reify is a general term, it means to "make concrete" (or to "make real" depending on the usage) something that is previously fuzzy or abstract.

When you make a concrete subclass of an abstract class, you are "reifying" that class. When you made the abstract class from the concept of something, you are "reifying" that concept.

It's a fun word.


And, possibly, Clojurists are more likely to use the word, because of: https://clojuredocs.org/clojure.core/reify


I picked up Clojure recently after a 10 year hiatus. My early complaints were around tooling - a Lisp-specific IDE felt all but required to get the benefits of the REPL and structural editing. And leiningen, god how I despise that tool.

With clojure-lsp, deps.edn, and more REPL tooling (conjure in neovim in my case), the situation is better now. I find myself reaching for Clojure for almost everything these days - from scripting to data crunching to quick web apps to database work. Clojure is an amazing tool once you grok it - closest thing to a super-power we can get.

> working "with" my code, molding it like clay

This the best description. Clojure feels very fun/interactive but simultaneously feels rock solid for production work. There is no gap between "notebook" and "prod". Zero compromises. Most other languages pick one or the other (Python - interactive but plagued by runtime errors, Rust - rock solid but clunky to iterate and experiment)


Not the same thing, but having something like JRebel can get quite close, and even if jshell isn't the best example of REPL, it isn't that bad either.


Maybe I miss what REPL really is, but...

If REPL is the main value proposition, how is it better from average JavaScript development? Dev tools allow you to basically interactively work with your code.


One important detail is that in Lisps like Clojure, printed values can usually be read back as code. So, the REPL is really a read-eval-print-LOOP.

Another detail is that the whole culture of the language, oriented towards immutable data, makes it very easy to evaluate almost any sub-expression in your code, which makes the whole code introspectable in a very playful and dynamic way.


I never got deep into any lisp like language but this was one of my favorite aspects of them - homoiconicity.


It's totally different. The R in REPL retains its original reference to the Lisp READer which is special when your code is structured as an AST as in all Lisps. Only in Lisps can you select the left paren of a deeply nested function and hit Eval. Other language REPLs are really just shells by comparison.


You can keep a JVM running in the background with your project loaded and send stuff there from your IDE/editor.

I don't think this is possible with JavaScript.


So they try to make the least-worst JVM environment which is great if you're dead-set on using the JVM, which has a lot of pros.

For most people Python/Javascript also does the job and you don't need to learn another paradigm — a Lisp — to code for it, which also makes sense.

However, learning a Lisp also makes you a better coder because of immutability and less side-effects. Hence why Clojure is still around.


> For most people Python/Javascript also does the job

True, and people should use whatever works best for them/for the job, no questions asked.

But they also have nowhere near the same experience even though they technically have REPLs. The way a JS/Python dev typically use a REPL is experiment in the REPL itself, then when happy, write the "real code", while a Clojure developers write "real code" all the code, sending selections of code to a REPL in the background, viewing the results in their editor, and just saves the file when they're happy. It might sound similar, but very different experience.

> However, learning a Lisp also makes you a better coder because of immutability and less side-effects. Hence why Clojure is still around.

I don't think "immutability" and "less side-effects" is something lisps in general/all lisps promote/facilitate, it's mostly a thing that Clojure (and children) sticks out for caring a lot about. Scheme/Common Lisp is about as immutable as JavaScript is, and lots of CL programs/code out there spreading mutation all over the place, while in Clojure it's pretty common to just have small "pieces" of mutation in somewhat centralized location.


> learning a Lisp also makes you a better coder

It can do, but it also can make you a worse coder. Specifically in typed languages.

One of the issues I've ran into with Clojure devs doing Java is that instead of relying on a type, they tend to want to write stuff like `Map<String, Map<String, Object>>`. Even when the key sets in both maps are well known.

This becomes worse when you mix that with Immutability. Immutability can be fine except when you need a mutation. In applications that require heavy mutation of data a `Map<String, Map<String, Object>>` is one of the worst ways to represent structured data, copying that structure is EXTREMELY expensive.

This isn't to say that you shouldn't usually strongly prefer Immutability. But it's also to say you shouldn't underestimate the cost of allocations and copying data.

Theres always tradeoffs. Part of being a good programmer is knowing when those tradeoffs are best applied.


Clojure data structures implement structural sharing which minimises copying overhead.


True, but persistent data structures are still 2x-4x slower than mutable structures on average.


I think it's "around" because it's quite productive and sits on a rock-solid runtime with support for an astonishing amount of libraries.

Around these parts it's common to have read and appreciated Paul Graham's old writings about becoming a better software developer through Lisp, and that would be Common Lisp, i.e. very mutable, commonly object oriented.


You can eval strings in Javascript, so pretty sure that's possible.


Looking around I don't find any maintained projects for this purpose.


It's just a native function named eval(), so I wouldn't expect to find projects built up around it.


That's not enough, there ought to be IDE/editor integration and so on.

Here's one such project: https://github.com/swank-js/swank-js


Quokka.js would probably be the nearest JS equivalent.


"...not as clumsy or random as AI, an elegant weapon from a more civilized age."


The cli/deps.edn tooling is different from Leiningen, and far, far less complicated IMO. I've written a good number of Leiningen plugins and it was always brutal to get anything to work properly, especially in combination with other plugins.

Leiningen attempts to be everything to everyone in terms of building, testing, and packaging Clojure code. It's Clojure's version of Maven.

cli/deps.edn effectively reduces things down to a) what should be on the classpath and b) what should get executed. Working inside an IDE? You just want it to download the dependencies and build a classpath. Running nREPL? Add that to the classpath, and set the starting namespace to start nREPL. Packaging an application? Run dependencies that do that work, based on the clojure.tools.build library.

I was there myself; I used Leiningen and didn't take the time to figure out deps.edn --- until I did, saw the light, and converted all of Walmart's projects to use deps.edn, which greatly sped up our build and improved our dev experience.


tools.deps is less complicated mostly because it just flat-out does much less. To mimic everything lein can do required adopting half a dozen other libs and writing your own build scripts.

It's better now, but people are pretty uncritical of the core team, and adopted tools.deps before its surrounding ecosystem was ready to fully replace lein.

The upshot was, everyone got to rebuild the wheel for a couple years. And I say this as someone who once lost a week debugging a subtle lein/maven classpath AOT bug.


~ > time bb -e '(println "Hello World")' Hello World bb -e '(println "Hello World")' 0.01s user 0.03s system 18% cpu 0.212 total

bb is Babashka: a pre-compiled (using Graal), interpreted, scripting language version of Clojure.

In terms of realistic work:

~/workspaces/github/pedestal/tests > time clj -X:test {:in user/eval2321, :line 13, :thread "main", :dev-mode? false}

Running tests in #{"test"}

...

Testing io.pedestal.test-test

Ran 391 tests containing 1180 assertions. 0 failures, 0 errors. clj -X:test 30.15s user 2.04s system 203% cpu 15.838 total ~/workspaces/github/pedestal/tests > java -version openjdk version "23.0.2" 2025-01-21 OpenJDK Runtime Environment Corretto-23.0.2.7.1 (build 23.0.2+7-FR) OpenJDK 64-Bit Server VM Corretto-23.0.2.7.1 (build 23.0.2+7-FR, mixed mode, sharing)

That's on my Intel MacBook Pro. Pedestal's test suite loads a good amount of Java classes and Clojure namespaces.

To make things faster, there's ahead-of-time compilation (which basically captures the read-eval-create-bytecode part of loading a Clojure namespace as Java .class files that can be packaged into your app).


So close to describing the Dialog IF language it’s almost prescient.

https://linusakesson.net/dialog/index.php

Dialog is a Prolog dialect: it’s like Markdown and Prolog had a baby.


It's neither Prolog nor a "dialect". From the intro:

> Dialog is a domain-specific language for creating interactive fiction. It is heavily inspired by Inform 7 (Graham Nelson et al. 2006) and Prolog (Alain Colmerauer et al. 1972), and substantially different from both.


It's based on unification, like a Prolog. It does backtracking, like a Prolog. It has something akin to Prolog "cuts". It's equally not Markdown. What it is, is the sensibilities of Prolog (for parsing words into player intent - actions) and for implementing a world model, and for inferring facts from other facts ... and also the text-foremost sensibility of Markdown.

I love it. I've put considerable effort into building tools around it, and to building up a library of extensions.


Backtracking and unification do not make a languge Prolog. What makes Prolog, Prolog. is that programs are sets of definite clauses, executed by proving Horn goals with SLD-Resolution.

There is so much confusion about that and I blame textbooks like Structure and Interpretation of Computer Programs and hackers like Gerald Sussman who have taught generations of programming students that Prolog is about backtracking with unification. It isn't and I've had many awkward conversations with folks who know about logic programming and Prolog from SICP and other similar texts until I realised that we are talking about completely different things.

If I remember correctly SICP doesn't even mention SLD-Resolution, or Resolution at all and most people I've spoken to who have learned about Prolog and "logic programming" from SICP have not even heard the words "SLD-Resolution". It's like a Prolog from a parallel universe based on dictionaries and partial unification with LISP variables.

As to Dialog in particular- it's a Domain Specific Language for writing IF games. Ver cool but not Prolog.


First I've heard of this one. I never got into Inform7 because I didn't find the language very discoverable; it felt like writing AppleScript. Do you know of any links to larger examples of Dialog code, like a full open source game written in the language?


That was my frustration as well; and it comes up in discussions. Simple to medium complex things are easy in Inform7, but when you start hitting the edges, you find out that its expressive English-like syntax is in the uncanny valley and exactly how you phrase things becomes vitally important and difficult to discern, even from the mounds of documentation it generates from your story file and from the standard library and extensions.


Lol, so its like playing an interactive fiction game.



The creator of Dialog, Linus Åkesson, went ahead and used it to create the winning entry for the IF Comp 2019. Does not look as if the source code was published, but I think winning that contest is the best indicator that a language for I-F is good enough to use in practice that I can imagine.

https://www.linusakesson.net/games/the-impossible-bottle/ind... https://ifcomp.org/comp/2020?compact=0


I feel like I knew about this at some point but thank you for reminding me especially now that I've got more prolog under my belt.


I’ve been building some friendly CLI and web tools around the terrific Dialog interactive fiction language.

https://github.com/hlship/dialog-tool

Learning Svelte for the web UI part.


Clojure's slow, deliberate development pace confuses people. The core team takes backwards compatibility very seriously. What you see with each new Clojure release is generally improved performance, better Java interop, and a smattering of new features. This is doubly true for 1.12 which is doing quite a bit of invisible work to make interop considerably better.

So what you don't see is a constant flux of "innovation" followed by a community having to adapt to those innovations. People pull Clojure examples out of books that are 12 or more years old and they still run.

I think there's some very exciting things in the Clojure space, such as Clerk (https://github.com/nextjournal/clerk) for live notebooks, and Babashka (https://github.com/borkdude/babashka) for amazing (and amazingly fast) scripting.


I guess that the GP didn't talk about the language itself, but the users. For me it looks like Scala and Clojure had lost many of its users because of Kotlin and newer Java versions. Generally I see a decline in the usage of functional languages since their heyday in the 2010s. I guess that's because imperative languages either get "functional features" or are "functional enough" - new ones like Rust or Swift.


Clojure is more lindy than Scala.

If someone tells you their project is written in Scala, Golang, Groovy, Coffeescript it almost dates the project doesn't it? Not so much in Clojure.

It's niche but I can bet it's still going to be there 10 years from now, going at least as strongly as now.


I'm not so sure. I wish it were as you say but there are currently 5600 job postings mentioning Scala on LinkedIn in the USA, vs 82 that mention Clojure. 82! In the entire USA. So even in its state of relative decline, Scala might be about 70 times as used in industry as Clojure is.

Even as I flip through the 7 postings mentioning Clojure in all of Canada, only 4 of them seem to indicate the job itself makes use of the language (rather than mentioning it just as an example language as in "* Fluency in one or more languages like Ruby, Clojure, Scala, ReactJS, JavaScript, TypeScript, Java, Python - Deep understanding of internet protocols and standards.")


What Clojure dev uses LinkedIn to find jobs?

I certainly wouldn't.


Nubank purchased Cognitect (the consulting company behind Clojure) in 2020, as well as Platformatec (employers of Jose Valim); the latter was for access to Platformatec's project management expertise (see https://building.nubank.com.br/tech-perspectives-behind-nuba... there is no Elixir code running at Nubank AFAIK.

There is Python on the "other side" of the ETL pipeline, but everything user-facing is (again AFAIK) Clojure on the backend and TypeScript in the Android and iOS apps.


In traditional databases, only the database engine has a scalable view of the data - that’s why you send SQL to it and stream back the response data set. With Datomic, the peer has the same level of read access as the transactor; it’s like the database comes to you.

In this read and update scenario, the peer will, at its leisure, read existing data and put together update data; some careful use of compare and set, or a custom transaction function, can ensure that the database has not changed between read and writes in such a way that the update is improper, when that is even a possibility - a rarity.

At scale, you want to minimize the amount of work the transactor must perform, since it so aggressively single threaded. Off loading work to the peer is amazingly effective.


It's actually quite a bit more than REBL; the description downplays something quite significant ... it can run as a client against a running Clojure in a separate process. Although that sounds simple ("it's just data") the number of edge cases involving everything from infinite lists, to dealing with functions as elements in the data, to differences in what's on the classpath between client and server, has impacted the implementation.


That's not a very helpful, or accurate, comment.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: