5 ms·
Jaunt – A friendly Clojure fork
- junke 10y agoTL;DR: forking Clojure to fix namespaces. > Because namespaces are mutable, even if I were to perform a rename correctly, the old name is still present in the namespace. First, ns-unmap your old name (a refactoring tool should do that for your, I guess). (edit: Clojure is a Lisp-1). > What if we gave Namespaces and Vars version numbers? When a Namespace is re-defined (the ns form is evaluated) then the Namespace's version is incremented. When a def is evaluated, the version of the Var bound by the def is set to be the version of the Namespace in which that Var exists. Your environment could keep track of definitions and usages of your symbols (see for example slime-who-calls, etc.). That would be a good improvement for Clojure. There is another problem: define namespace N, define variable N/x, using it in another namespace M, remove namspace N. Then, an old name x is referenced from M which does not exist in any namespace. Also, you redefine namespace N with a new x, and now old-x and new-x are different objects. I don't think version numbers would help you here. I am just thinking aloud, but when remove-ns is called, you could re-parent orphaned names from that package to a global "orphans" table. When you intern a symbol in a namespace, first you try to see if you can recycle objects from "oprhans" based on their fully qualified name. So that new-x and old-x are in fact the same name object. Or, you just use a global map to store fully qualified names in the first place. Maybe the metadata attached to orphaned symbols should be cleared in this approach, to avoid keeping irrelevant data about a name when it is reused. But again, you should be careful when you rename namespaces. Maybe the best answer is to simply be aware of the possible pitfalls.
- moomin 10y agoYou could even keep copies of the version of the file that had your fn definition. If nothing else, it's a pretty interesting idea.
- H0n3sty 10y ago> First, ns-unmap your old name (a refactoring tool should do that for your, I guess). clj-refactor has a cljr-rename-symbol function. https://github.com/clojure-emacs/clj-refactor.el https://github.com/clojure-emacs/clj-refactor.el Here's a full list of its features: https://github.com/clojure-emacs/clj-refactor.el/wiki https://github.com/clojure-emacs/clj-refactor.el/wiki
- dragandj 10y agoAbout the namespace problem: I do a lot of refactoring, and namespaces were never my problem, because the types of errors op is talking about could be handled by the test suite, and/or cider reloading. I really think I would not want versioning of my namespaces - that would make a huge mess. So like many other ideas that sound good and pure and elegant at the first glance, I think this one would be an overly complex mess in practice. BUT, there is a more important thing, and there I support the author: instead on pushing Rich (the author of Clojure) to include any shiny feature that someone thinks would be nice, and then complaining that Rich ignores the request, the OP forked Clojure and tries to prove that his ideas are better. I think Rich does quite well on keeping Clojure sane and useful. I have no doubt that he will include stuff that really proves to be better. But, 99% of stuff is better only while is on scratchpad, but turns out either irrelevant, or, even worse, outright horrible in practice. That's why I think that everything that can be a library should be a library instead a part of clojure.core. Those things that could not be libraries (not many of those come to my mind) should first be proven in some sort of "experimental" clojure. clojure.core should stay as it is :)
- catnaroek 10y ago> test suite Re-running an entire test suite every time I make a tiny change to the code isn't viable. > cider reloading If only it didn't take forever! I really like Clojure the language, but having to restart CIDER every time I want to make the REPL forget my old wrong definitions is killing me. Not resetting the REPL's state is also pretty bad: I might accidentally use an old definition that was supposed to be discarded. The difference in behavior between macros and normal code exacerbates this problem: when you redefine a function, all existing uses of the function now point to the new version; but when you redefine a macro, all existing code that was generated by macro expansion retains its old form. So reasoning about the effects of the old definitions still being there can get quite complicated. There ought to be some way to tell the REPL, in a single instruction: “Please forget that previous versions of my code ever existed. They're all wrong.”
- silentmars 10y agoRestarting is different from reloading. Take a look at `clojure.tools.namespace.repl/refresh` - which in recent versions of CIDER is triggered with `cider-refresh`. It does what you're asking - blows away all the loaded namespaces and re-compiles them from source, synching up the running code environment with what's in your source files.
- _halgari 10y agoThis article is several months old, and the linked repo hasn't been updated in about two months.
- lbradstreet 10y agoThe repo was updated 13 days ago.
- _halgari 10y agoyes, to bump a version number in a build script. the last meaningful change was 3 months ago.
- noelwelsh 10y agoSounds like it fits within the "staged programming" model, which I think is a very interesting and relatively unexplored approach to adding some degree of dynamism into a statically typed language (which is not necessarily the goal here ...) It would be cool to have more of these systems reach the level where they are usable in commercial projects.
- edem 10y agoIs "Jaunt" a reference to "The Stars My Destination" by Alfred Bester?
- zcam 10y agoGood initiative. Clojure developement is driven by the needs of Rich/Datomic these days, it's understandable this might be frustating for users who wish clojure was more community driven, and exploring other areas. I personally gave up on it because of this (I used to do clojure full time).
- _pmf_ 10y agoThe real bummer is that Cognitect drives Clojure, and Cognitect's business is Clojure consulting. Now, if you look at some presentations about how Cognitect consults companies, you'll see that the advice often boils down to "don't use persistent data structures, use Java's", "don't use STM, use Java ConcurrentHashMap". They stay in business by selling the cure to the poisonous snake oil they sell.
- wilkes 10y agoReferences?
- _halgari 10y ago>> "don't use persistent data structures, use Java's" Love to see a reference for this.
- s_kilk 10y agoSeconded, i find this plausible, but need to see a source.
- _halgari 10y agoI find it highly implausible. Most likely OP ignored the full context of the statement. I can't imagine any of my co-workers recommending Java Maps over PHMs except in very rare interop situations. Likewise, I can't remember the last time I even saw a ConcurrentHashMap used in Clojure code, or STM for that matter. Most of the code I write, and work with, is as recommended for years: Persistent data in as few atoms as possible. No ill-will directed at the OP, but it's hard not to take umbrage at the suggestion that I am a snake-oil salesman. So yes, references please!
- sdegutis 10y agoOn the topic of forking Clojure, I've had sort of an interest in writing a pure C version of the core of Clojure for a while; something with similar goals to Lua, namely that it would be self-sufficient, portable, and embeddable; a library first, much like Clojure is in Java. I guess it should be called Clocure if it ever came into existence. But honestly, I have no personal need for this, it's only something I like the idea of, and therefore I don't ever see myself actually writing it. (I guess I might use it for some small-ish scripts that I might otherwise go to Python or Ruby for. But I hardly write such small scripts anymore.) Either way, I still like the idea and will probably continue dreaming about it for a while to come. That said, I have to second the other opinions in this thread, namely, that Jaunt is solving a problem in Clojure that already has other solutions. When I'm writing Clojure for work (I use it full time), I use Cider, and I often make use of C-c u, which is cider-unset, allowing me to make sure I remove a var from a namespace. That plus cider-reload gives me assurance that my namespace mutations are pretty reliable.
- juliangamble 10y agoThe author of this article started his first day on the job after University at Twitter today. Please send him your best wishes!