I also see this mentioned often and have wondered the same. I can sort of envision this working in a single threaded application, but how would this work in a web application for example? If a problematic function needs to be debugged, can you pick what thread you're debugging? If not, do all incoming requests get blocked while you debug and step through stack frames?
Being paused in the debugger is per-thread. If the server's using a thread-per-request model, and you're stopped in the request, then other requests can proceed just fine. If some of those requests also trigger the debugger, they'll pause and have to wait, they won't interrupt your current debugging view. Extra care should be taken in any sort of production debugging, of course. (At a Java BigCo, production debugging was technically allowed but required multiple signoffs, the engineer wasn't the one in control but had to direct someone else, lots of barriers to prevent looking at arbitrary customer data, and of course still limited to what you can do with a standard JVM restarted in debug mode. (Mainly setting breakpoints and walking stack traces.))
But the nicest part is that once you connect to the production application, apart from network lag it's no different than if you were developing and debugging locally on similarly specced hardware to the server, you have all the same tools. Many of the broader activities around "debugging" don't need to happen in a paused thread that was entered with an explicit breakpoint or error, they can happen in a separate thread entirely. You connect, then you can start inspecting (even modifying) any global state, you can define new variables, you can inspect objects, you can define new functions to test hypotheses, redefine existing functions... if you want all requests to pause until you're done, you can make it so. Or if you want to temporarily redirect all requests to some maintenance page, you can make that so instead. A simple thing I like doing sometimes when developing locally (and I could do it on a production binary too) is to define some (namespaced) global variable and redefine a singly-dispatched method to set it to the self object (possibly conditionally), and once I have it I might redefine the method again to have that bit commented out just so I know it won't change underneath me. Alternatively I can (and sometimes do) instead set this where the object is created. Then I have a nice variable independent of any stack frames that I can inspect, pass to other method calls, change properties of, whatever, at my leisure without really impacting the rest of the program's running operation. Another neat trick is being able to dynamically add/remove inherited mixin superclasses to some class, and when you do that it automatically impacts all existing objects of that class as well. Mixin classes are characterized by having aspect-oriented methods associated with them; you can define custom :before, :after, or :around methods independent of the primary method that gets called for some object.
I'm not a fan of dynamic typing at all (currently maintaining a decade's old e-comm monolith written in Ruby on Rails), but instead of arguing about what bugs are caught where, I've instead switched to arguing from a position of developer experience. The _tooling_ that statically typed languages have is levels above those found in dynamic languages. Runtime errors are runtime errors, but knowing at typing-time that the shape of thing A is what thing B needs is a huge benefit.
>If you mess up, redo the part you messed up correctly 5 times in a row.
I think it may be important to note _when_ to redo this. I started off this way, but after working with a guitar teacher (a Berklee graduate), he recommended that I continue on with the song and return to the problematic parts afterwards. If you constantly stop at the problematic parts to replay them and get it right, you'll have no idea what other parts you'll have trouble with further into the song until much later. In addition to that, being able to move on and continue playing the song after making a mistake is an important skill itself. If you build that skill, it's usually only other musicians that will notice -- a regular audience won't.
I can be pretty bizarre without even trying, I'll take both ;)
Practice makes perfect is a thing, but that's not exactly rehearsal.
With practice you expect to improve, broaden, or maintain instrumental or musical ability for the long term. There should be no deadlines or need for actual listenability.
OTOH rehearsal is the run-up to a smooth listenable performance with a decidedly short-term objective by comparison. Unless you are rehearsing to absolute perfection, you do not halt for anything, the show must go on and that in itself requires you to practice covering up and compensating for your mistakes or shortcomings as you go along.
With practice you are actually trying to become a better player overall, but rehearsal is more about making the next performance as good as it can be and that's it.
If you're not actually as good as you would like in either regard, having a bit of commitment to simulating what you need most can give some direction itself to add to the mix.
When learning a new piece you should play all the way through once. You should play through it again, stopping at all the problematic areas and making note of them, but continuing. After that there are a lot of ways to go about practicing a piece. I think repetitions on the problematic areas in conjunction with working backwards, especially if you want/need to memorize the piece, is fastest.
Playing through the whole song from the beginning over and over again is not an efficient way to learn a new piece of music.
Not the whole song, just the part you mess up. For instance, in the guitar part for Under the Bridge by RHCP, there's the simple melodic part that only requires learning the chord forms and picking patterns.
That transitions into a more rhythmic chord progression with a few embellishments, which also isn't terribly difficult at first, but then a few verses later that ramps up a good amount and becomes moderately difficult.
If you stumble on that transition / passage, then that is where you would stop and then practice until you do it correctly 5 times.
The next day, once you've rested and let your brain absorb the info, try it again and you'll find it much easier to get right on the first try.
Stopping and working slow is the only way you'll find and improve hard things. If you just blunder past them each time, you're only learning to blunder. Able to play the easy things but never improving the hard.
But if all you do is stop at every mistake, all you're learning is how to stop at every mistake. Live music doesn't stop, you need to know how to pick up and keep up, no matter what. (This was my mistake for decades.)
There's a lot more to learning a piece of music, but I think both kinds of passes are necessary. Well, unless you're good enough to fly through that piece prima vista with results that you're happy with. Then you get to hone the expression or interpretation or just cash in, I guess.
>easy for agents to write and beautiful for humans to review
What's left unspoken here, and something I've brought up in other threads that have mentioned Ruby + LLMs, is that they continue to struggle _comprehending_ Ruby (and Rails) style code. In a fresh project, agents writing code for humans to review is a solid approach, but when the codebase grows and the project starts suffering from the downsides of dynamic typing, you're not going to be able to lean on that LLM to aide you in refactoring.
LispWorks and Allegro are both interesting, but I've found their IDE offerings to be very limited. I haven't used either since I was playing around with CL during Covid, but from what I recall, even the basic IDE experience of writing code was severely lacking: poor autocomplete, poor syntax highlighting, clunky interfaces. In most discussions I see about them, they're only recommended for their compilers, not for their IDE offerings.
I think LispWorks is fine (also look at these plugins https://github.com/apr3vau/lw-plugins - terminal integration, code folding, side tree, markdown highlighting, Nerd Fonts, fuzzy-matching, enhanced directory mode, expand region, pair editing, SVG rendering…) but I had this feeling with the newer web-based Allegro IDE (the poor syntax highlighting surprised me, did I do sthg wrong?).
This is the perfect way to create a code-base that's incomprehensible. Claude may be good at generating Rails code, but every LLM I've tried to date has struggled immensely with parsing and understanding an existing Ruby on Rails code-base.
I've seen more praise than criticism from employers.
I've seen more positive reflection than regrets from students.
(also true of Scheme based 6.001 and CS61A and HtDP)
This discussion at lobsters suggests the decision to change the curricula was political and business driven, not based on the merits of the "Fundies" course series:
reply