It's all very well but the Lisp debuggers themselves are, well, buggers. I can't single-step and most of the time I can't even inspect local state. This is my biggest peeve about working in CL (CCL+Slime or SBCL+Slime on OS X). Breaking into sldb feels like breaking into the 1970s. When there's anything at all that a Lisp hacker envies about Visual F--king Studio, that's bad.
Am I doing something wrong? Other CL hackers (mahmud?), what do you do?
This is essentially the same feature that is exposed by MS in languages like C++, C# etc. as "edit and continue".
It's a feature I've never particularly liked, and never wanted to use to any strong degree. I have a strong suspicion that programming in this style is correlated with an aversion to strong typing, and actually amounts to a different way of thinking about programming. Not necessarily better, but different, and its effect on your productivity depends on how you prefer to work.
I have a strong suspicion that programming in this style is correlated with an aversion to strong typing.
Perhaps because the popular languages that support this development style happen to be dynamically typed. Haskell also supports this, and this the language where I make the most use of it. It is strongly typed.
So while there may be a correlation, I don't think there is any relationship.
(Dynamic typing is popular because static typing was done wrong, and people thought the problem was having static types, not that all the existing statically-typed languages were just bad. Haskell has shown us that statically-typed languages are just as easy to develop in as dynamically-typed languages, except easier, because you don't have to deal with runtime type errors.)
There is much wrong with what you wrote, in my personal opinion.
Haskell is not easy to develop in, as measured both by how perplexed programmers new to the functional way of thinking are and their difficulties with monads; and as measured by even experienced functional programmers, who can be surprised by some of the implications of lazy evaluation.
Static typing was not necessarily done wrong. Some folks like it when the type abstractions they're working with map to their mental model of the domain, and for many programmers, in many domains, C#, Java and their ilk are pretty decent.
Finally, Haskell, and other functional languages, generally are not hugely amenable to dynamic linking and changing the code executing at runtime.
What I believe you got wrong aside, it remains my suspicion that it is the people who believe that static typing "was done wrong" are more likely to enjoy edit and continue / Lisp-style programming.
Haskell is not easy to develop in, as measured both by how perplexed programmers new to the functional way of thinking are and their difficulties with monads; and as measured by even experienced functional programmers, who can be surprised by some of the implications of lazy evaluation.
Every language has surprising features. I was surprised to find that my Perl program was running slowly because of things like "my @result = function" instead of "my $result_ref = function". Returning a list was hugely expensive.
Similarly, Haskell programmers will notice that their app is using too much memory, and then track down the space leaks that lazy evaluation caused and fix them. But most of these are easy to avoid in the first place.
As for monads, the problem is that people think they're hard, so their brain tells them "THIS IS HARD" and drowns out any ability to learn them. Experienced category theorists dislike monads for a few reasons; they are either too generic or not generic enough. Applicative functors and Arrows provide other options for similar control structures. Practicing programmers like monads over arrows because the syntax is nicer; they dislike them because complex monad transformer stacks are unwieldy. This is not something that happens often, though, hence the continued popularity.
Static typing was not necessarily done wrong.
It was done wrong. People think that static typing means "Class class = new Class" instead of "class = new Class". It doesn't, but the damage was done, and people switched to dynamic languages. (Before Java, people hated C because even trivial programs like "read a file containing numbers and return an array of them" was non-trivial. With the "dynamic languages" it was simple matter of "my @numbers = <$file>", and now you had a list of numbers you could compute with. Nothing to do with any type system; simply a bad implementation that correlated with static typing.)
Finally, Haskell, and other functional languages, generally are not hugely amenable to dynamic linking and changing the code executing at runtime.
Nor is Java, or C without unix. This is orthogonal to langauge, although Smalltalk and Lisp ensure that this Works Everywhere. (Ever use xmonad or yi? It is easy enough to make at-runtime code changes appear dynamic.)
With Java, it's surprisingly easy to load new classes and even dynamically generated classes via a class loader. Dynamically linking with C is very easy in Windows too, which is more prevalent than Unix.
I should have qualified that my statement was referring to statically typed functional languages, though; the strategies required for runtime parametric polymorphism are quite different to those required for just compile-time parametric polymorphism, and statically typed functional languages generally encourage flow of types throughout the forest of functional expressions, by which I mean that compile-time parametric polymorphism is very much sufficient before dynamic linking and polymorphic - runtime polymorphic - APIs have been considered.
I have tried neither xmonad nor yi, though yi looks interesting. The choice of testimonials for xmonad on their site is amusing, though - "I have to say, the greatest thing about xmonad thus far is its insane stability... I have zero issues with xmonad". Stability is the absence of certain kinds of defects, not a positive feature - I for one have never suffered from e.g. lack of stability in the Windows window manager.
I develop in both languages and I don't find them similar at all. If you modify a python module, for example, how do you easily re-import that module in your REPL? Python caches modules once imported and doesn't let you easily re-import a module that's been changed, right? And how do you modify a function and hot-swap it in while the rest of your code is still running?
Anyway, modern web applications(python/ruby + javascript) are very different and very similar: to debug them, you run, edit and re-run one "page" at a time, just by reloading the page you are working on in browser.
It's kind of pointless to even discuss this topic at this time.
Then why does the python repl still "print" errors and return you to the prompt, instead of a debugger? The python shell has no concept of restarts: it prints errors as a side-effect and stops further processing. Lisps pause evaluation at the point of error and give you options to proceed.
Am I doing something wrong? Other CL hackers (mahmud?), what do you do?