Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

That last feature is certainly one of my favorite parts about Clojure. It's one of my favorite parts about Lisps in general actually, but Clojure has a very good handle on it. Having to compile a program before seeing if the changes you made work can be a nuisance. Interpreted programs are slightly better, but being able to make micro-changes to a running instance of a program and seeing in real-time how it affects the whole program is the best. The feature that Clojure misses here is the ability to load new libraries (jar files) on the fly, but that's not Clojure's fault, but rather the JVM's fault.


What I find really surprising is that other languages that have pretty decent REPL support have not embraced it so fully as Lisps have. Connecting to the live[0] instance a Rails or Django app, examining its internal state and making updates that don't involve more or less restarting the app is unusual at best.

Ruby and Python borrow a lot from Lisp, including the REPL, but some of the most popular applications of those languages barely take advantage of it. Why?

[0] I'll stipulate that you might want to be very conservative about doing this with a production system.


The work done at Xerox PARC with Smalltalk and Interlisp was great.

Imagine having a REPL to your complete OS, not the just the basic CLI that most systems have.

There are a few videos of those days showing up the systems.


+1 I still think fondly of the InterLisp environment on the Xerox 1108 Lisp Machine my company bought me in 1982. You can find emulators for InterLisp, but the experience is not the same.


Everything I know is from the documents, papers and videos that I manage to scrap from the Internet.

My experience with Oberon, lead me to track down how Wirth learned about such systems.

Additionally, I got to learn Smalltalk in the form of VisualWorks before Java was known to the world.

So I extrapolate my experience to how it might have felt back then and find it sad we are still trying rediscover it.


I'll stipulate that you might want to be very conservative about doing this with a production system.

No kidding. I knew at least one guy who hosed a product launch by doing that. You even have to restart your development instance from time to time to make sure that your application state remains consistent. I've been scared to try, but I suspect that you could live-patch a server though if you were systematic about it and tested the patch ahead of time.


You even have to restart your development instance from time to time to make sure that your application state remains consistent.

There are ways around that. Stuart Sierra uses a scheme wherein the entire application is treated as a value, which can be re-generated on the fly. Of course, that's not terribly different in practice from restarting the whole environment, but it's faster and more convenient.

http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-r...


Back in 2001, We had a corner case bug in our ORM that impacted a scheduled demo. So I connected with the live Smalltalk app server and changed the state of the DB locks during the demo.

There are technologies deigned to enable live updates. VisualWorks Smalltalk had one, though it was not widely used. There are real time OS that can update the kernel without going down.


You might like Flask. It has an interactive REPL on debug screens.


I have used Flask. I do like it.


I admit to still not understanding what goes on with function definitions in clojure, but this idea of just making a micro change in clojure and evaling that and seeing the real time effects never seems to pan out for me.

I do lots of small functions that build on each other. If I make a change to one of the base functions, the higher functions seem to hold a reference to the old definition and I end up having to re-eval everything or go figure out every place I used that function.

I'm sure there is a better way but I haven't found it yet. I've tried using some ideas from Stuart Sierra about reloading namespaces, but I spend more time trying to orient my code to work with their ideas than just getting something done.

And documentation in clojure code in general is very poor. People think their code is self documenting. It is not.

While clojure is wonderful to write in, it's not nearly as enjoyable to read. The more macros and syntactic sugar people add to their programs, the less likely someone is going to be able to read, understand, and use that code.


If macros are used properly, they should make the code easier to read, not harder. If you can't figure out what it does from it's signature and docstring (maybe with a reference to some documentation for more complex or abstract things,) there's a problem. You shouldn't have to read a macro's definition to be able to use it.

Also, redefining a function should cause every function which directly references it to use the new version. You can sometimes run into issues if the functions are defined in separate namespaces or if the redefined function was passed to the other as a higher order function during the latter's definition.

If it's a macro you're redefining, yes you'll have to redefine functions which depend on it, but you should be defining too many macros.


"If macros are used properly, they should make the code easier to read, not harder."

Well, I think macros often play the role of jargon. They let you spell out a particular concept succinctly and precisely and make the whole much easier to follow once you are familiar with the jargon, but people unfamiliar won't fully understand.

Much like jargon in spoken language in any field it can be picked such that those otherwise familiar with the language draw conclusions (that are hopefully correct), or picked so that they recognize that they are unable to draw substantial conclusions (which may be incorrect). There are upsides and downsides to both approaches (which isn't to say one doesn't dominate, but from my limited perspective it's not clear).

I should note that, to some extent, this is true of most kinds of abstraction.


I suppose. If you don't know what a for loop does you can't really be expected to use one. But you shouldn't have to understand how a for loop is implemented in order to use it correctly is really my point.

Macros can be used to implement some pretty novel abstractions so there can be some temptation to try to understand them by reading the implementation. However, if an abstraction is novel enough, it really should be documented somewhere very thoroughly.

So, to some degree your analogy makes sense. You can use macros (and functions too, really) to express concepts that are unclear unless you have a better familiarity with the topic or the program in question. But I feel that that's what docstrings are for.


All certainly the case. Any sort of jargon should be well defined and well documented. Standardizing on jargon between groups eases transitions between groups, but may mean it fits individual problem domains slightly less well. &c, &c.


>And documentation in clojure code in general is very poor. People think their code is self documenting. It is not.

Clojure functions and macros have docstrings you can query with the "doc" function. Honestly I've started keeping a repl open all time like I used to do in C with a terminal + man, so I can use (doc whatever) or (source whatever) to see the documentation + implementation details of most of the functions I use.


I do appreciate the doc strings. If only more people would write them. Weavejester's code I think is a fine example of doing this well. https://github.com/weavejester/compojure/blob/master/src/com...


You can use Alembic[1] to add dependencies at run time, not just adding them to the path, but downloading them from clojars or maven central, eg. using the example from the docs:

(alembic.still/distill '[org.clojure/tools.logging "0.2.1"])

Or something like clojure/tools.namespace[2] to edit your project.clj and then reload/refresh all namespaces to be current.

[1] https://github.com/pallet/alembic [2] https://github.com/clojure/tools.namespace


> Having to compile a program before seeing if the changes you made work can be a nuisance.

Not being able to compile a program to check if the changes you made are even coherent is also a nuisance.

Also, nothing says that compiling a program has to take a long time (eg. go).


I could load jars on the fly in Java.


This has been possible in Grails and Play for many years.

You can make a code change and refresh the browser and your changes are reflected.


TIL that that is possible. Just googled it apparently requires custom class-loader. Thanks for this.


Check out JRebel [1] which works with a plugin to your favorite IDE if you want to make it really easy.

[1] http://zeroturnaround.com/software/jrebel/


Or you can simply use OSGi.




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

Search: