For Clojure the interactive debugging experience is just plain dreadful and for a dynamic language this is pants on head crazy imo. For me a dynamic language has to have a good interactive debugging experience because you have foregone the support of a static compilation and instead wish to reason about your program at runtime. But with the JVM stack traces and lack of interactive debugger Clojure just does not support you in this regard. And as a side note the lack of an identity print is annoying as well e.g. (+ (print 4) (print 4)) "4" "4" 8 (yes, it's easy to add...)
Clojure's decision to use persistent data structures is good but it's really the only standout thing for me other than some syntax sugar like hash maps.
Here's a 39 second video about it https://www.youtube.com/watch?v=A3JAlWM8qRM
That's something different.
In a Lisp system I would have an arbitrary amount of code and can halt and inspect/debug any code without any prior need to 'instrument' code.
You mean the stepper using break-instrumented code? That's just a part of what one would call 'debugger' in Lisp.
What CIDER calls 'debugger' would be mostly called 'stepper' in Lisp.
http://franz.com/products/allegro-common-lisp/stepper_dialog...
http://www.lispworks.com/documentation/lw70/IDE-M/html/ide-m...
> Adding breakpoints is somewhat easier with cider, you don't need to call break but you can just add a breakpoint to any sexp by pressing b.
LispWorks does that, too. Usually via a break icon in the window toolbar or the context menu.
As a Smalltalker ("the other heroin of the programming world") I'm used to a highly integrated and responsive development environment; from what I heard from other Lispers, the quick feedback and gradual building up of your program is a shared aspect, but the thing that Smalltalkers always bring up and Lispers less so is also that your program and your IDE are basically indistinguishable, which is quite powerful because it makes it trivial to adapt your IDE to your project as you go. In the Lisp environments I've tried - latest being Emacs+SBLC - the split between editor and REPL seems unnatural to me, more so because in the standard case you work with two different dialects of the language. It seems that only ACL and LW have more unification.
Am I wrong and are the $$$$ versions not better in that respect and should I just drop my Smalltalk habits/arguments when learning CL?
Lisp provides that,too. But you can also deliver programs with the IDE and much of the development tools removed.
Examples for integrated IDEs:
Allegro CL on Windows/Unix+Gtk, Clozure CL (free) on Macs, LispWorks on Windows/Macs/Unix+GTK/Unix+Motif. There the IDE and the user code runs in one Lisp. Other examples: Lisp Machines, CMUCL on X11, ... there is also the McCLIM project where some ideas from the Symbolics GUI are used.
There are also countless other implementations from the past, which are now mostly forgotten, which had an integrated IDE (Golden Common Lisp for Windows, Corman Lisp for Windows, Macintosh Common Lisp, Medley, Open Genera for X11...),
I've used Squeak Smalltalk and DrRacket in the past. As someone who finds slime/swank/sbcl in Emacs a pleasure, I can only imagine how great some of those other environments can be.
I read this article on your site:
http://lispm.de/why-lisp-is-different
Quote from it:
[ When in doubt design software to be introspective.
when in doubt design software to be reflective. ]
What is the difference between introspective and reflective? I've used introspection in Python and know about and used (a bit) reflection in Java earlier, but thought they were roughly the same sort of thing. Please explain the difference if possible.
* find me the class, typically by name or by some relationship
* what are the fields of that class?
* find me a function
* what are the arguments of the function? does it have documentation? Who wrote it? Where is its source? What values does it return?
* where is the function used? what functions does it call?
* what are the values of a field of some object? What class does it have?
This and more for example enables you to inspect a program at runtime and find out what it does, how it does it and what its state currently is.
Reflection means that elements of the programming language are itself exposed and we can change/extend them.
Two examples of the Lisp world. Very unusual is the reflective tower, where a Lisp program is run by some kind of machine, which for example is a Lisp interpreter. This Lisp interpreter is itself a Lisp program. Thus you can not only write the program, but you can change/extend the interpreter running the program. A certain Lisp dialect allowed also to look at the interpreter running the interpreter running the interpreter running the interpreter ...
In Common Lisp a typical form of reflection is the Meta-Object Protocol of CLOS. It allows you to program the object system to implement new variants: persistent objects, transactions over objects, different inheritance mechanisms, classes which record their instances, ... Thus the MOP exposes classes, methods, generic functions, slot descriptors, ... as CLOS classes and methods - and protocols about them. Thus CLOS can be programmed in itself. Even at runtime.
More primitive reflection would allow you to create/change/remove things like user classes and user methods. Task: create a new subclass of an existing class at runtime.
> Introspection should not be confused with reflection, which goes a step further and is the ability for a program to manipulate the values, meta-data, properties and/or functions of an object at runtime.
I think what it really comes down to is that writing and maintaining an editor (especially a good one) is a very large task. A language that lets you use an editor you already like thus has a double advantage, with the possible downside that the integration won't be as good as possible. SLIME is pretty nice though.
* The common lisp condition system [3, 0] is a way better way to do errors.
* Tune-able compilers [1] allow you to make better trade offs than even gcc allows for c, let alone Clojure's very opaque compiler.
* CLOS [2] is a very powerful object system which clojure does not replicate (they have multi methods, and java classes, but not a meta class system; think python's meta class features but better (because of macros and compiler access) and with multi methods designed in).
* Nice native interoperability (Clojure generally being on the JVM, and common lisp capable of direct calls and memory manipulation).
That being said. Clojure's unparalleled concurrency features are amazing. I would compare them as: if Clojure is the Java of lisps, then Common Lisp is the C++ of lisps.
[0] http://www.gigamonkeys.com/book/beyond-exception-handling-co...
[1] http://franz.com/support/documentation/current/doc/compiling...
[2] http://www.laputan.org/pub/papers/MOP.pdf
[3] http://axisofeval.blogspot.com/2011/04/whats-condition-syste...
- Defined by a standard (the text of the standard is available for free online as the Common Lisp HyperSpec [1]), not by a reference implementation led by a BDFL
- Multiple mature implementations, both free and proprietary
- Wholeheartedly multi-paradigm; has FP features, but also provides plenty of tools for imperative (notably including a powerful macro for loops) and (meta)object-oriented approaches
- "Lisp-2" rather than "Lisp-1"; functions and variables are in different namespaces, which reduces name clashes but requires disambiguation in some places
- Designed for implementation in a wide variety of environments, including being embedded as an extension/scripting language in C or C++ applications (see ECL [2])
[1] http://www.lispworks.com/documentation/HyperSpec/Front/index...
How does this help, compared to Clojure?
> Multiple mature implementations
Why wouldn't one free mature implementation be good enough?
> Wholeheartedly multi-paradigm
Exactly like Clojure.
> "Lisp-2" rather than "Lisp-1"
I can't remember which one Clojure is :) But I haven't had any problems with namespaces and the like.
> Designed for implementation in a wide variety of environments
So is Clojure, right? There's the CLR version, and ClojureScript too.
Clojure:
Clojure 1.8.0
user=> (/ 3 4)
3/4
ClojureScript cljs.user=> (/ 3 4)
0.75
Looks like these are different languages...Common Lisp implementations OTOH implement most of the standard. There is also more choice in implementations:
* native implementations AND hosted implementations
* actual Lisp interpreters or a mix of interpreters and compilers, interactive compilers, batch compiler
* compilers written in Lisp itself with good error messages, forms of compile-time type checking/inference, and advanced error handling (like SBCL, CMUCL)
* compilation to C, full embedding into C programs (ECL and others)
* full embedding in C++ (CLASP)
* compilation to shared libraries, embeddable into other applications
* whole program compilers for delivery of compact applications (like mocl)
The main Clojure compiler is written in Java and it shows...
https://github.com/clojure/clojure/blob/master/src/jvm/cloju...
If one targets a certain host environment (JVM, Javascript, ...) then this range of options and choice might not matter, even hinder - besides getting a poorer version of interactivity.
If we see a Lisp as a language on its own, then it matters a lot.
> Exactly like Clojure.
Clojure is definitively not multi-paradigm. The only blessed by the developers/community paradigm is functional.
If I work on a project where functional programming with emphasis on purity is required I will much rather go to ML family, which I think offers more natural way to express ideas in functional paradigm with beauty and integrity not even Lisp can match.
I guess you're not familiar with ClojureScript and/or Clojure CLR?
- I don't want a door here.
- Ok, you don't like the wooden door here. You can have a plastic one or a steel door.
With CL you're not tied to _any_ platform.
Look at lispm's comment: https://news.ycombinator.com/item?id=13984011
It's not just the platform libs, but the semantics of things that really should be portable.
Easy access to the tens of thousands of person years worth of effort put into the Java/JavaScript ecosystems in return for dealing with a bit of ugliness is a win in my books.