Joe Marshall writes about Lisp, tail recursion, first-class environments, and Lisp machine history.
Commenters recommend it as a good Lisp series, citing posts on tail calls and first-class environments, and a reply to Guido van Rossum on tail recursion.
I came to ruby from the perl side. It was "here's a Redmine server, here's a feature request for one of the in house built plugins." I forget the specifics (it was 2011) ... but trick of the feature was to add a function to the object being created so that it would have the function some other module was expecting. And it worked...
Things like that made me give it the sideye for anything more than I could keep in my head at once... if I started needing to look at other files to determine if there was anything odd there... "can I create a function here in this parameter passed to me? What if someone else created a function of the same name before they passed it to me and expected it to remain?"
It can work... but it requires a bit more discipline than the developers I was working with had as a baseline (for that matter, a decade and a half later at a different job with a lower baseline and AI code - the idea of that terrifies me).
It's a "powerful" language, but I think it has too much power.
I like groovy for much the same reason that I liked perl and ruby (to an extent) - but it too is too powerful. It's great for writing scripts where it's a file or two or three... but if the "what does it do" gets too large to keep in my mind at once then it requires more discipline. I like to think that I have that discipline when working solo in groovy (and people will tell me I don't need to be that explicit in the objects... creating a class file rather than just shoving…
Do you need to be "good at math" in the typical sense? Certainly not. Learning away certain mathematical concepts, however, helps.
To answer your question more precisely, I'll ask you a question: do you code in any high level language (Python, Ruby, Perl, PHP)? If so, chances are you're using 'associative arrays', 'dictionaries' or 'hashes'. How do they work under the cover? What is special and unique about them (A: hash tables and hashing functions).
Now, can you use the concept that's used by the hash-table primitives in your language, to sort an array of size N in a time proportion to N? What are you giving up to gain that speed advantage, how can you offset that by giving up slight speed advantage?
Now if someone is studying the same mathematical topics without having already programmed they won't have the same appreciation and attentiveness. To them "hash function" don't immediately click with programming techniques right away. Essentially my advice is start coding anyway, so the relevant topics in maths will "just click".
This is also a very different kind of math: it's largely discrete and even the continuous portions of it are elegant. This isn't sitting for hours and doing symbol manipulation or number crunching. You don't need to know what continuous and discrete mean: just pick up a discrete mathematics textbook and see how far you can work through it.
Attempt calculus, if only thing, just because the first elegant example SICP provides deals with a tiny…
This is such a great thread, I'm excited to begin reading quite a few of the linked blogs (such as this one: https://acoup.blog/).
These ones are some of my favorites:
- www.wall.org/~aron/blog/ (physics, theology, history, philosophy)
- http://xahlee.info/ (math, emacs, keyboards, etc.)
- https://matt.might.net/articles/ (academy, compsci, etc.)
- https://www.joelonsoftware.com/ (programming, companies, etc.)
- https://danluu.com/ (technical topics)
- Mailing list in https://practicaltypography.com/
- http://paulgraham.com/
- https://math.ucr.edu/home/baez/ (math, physics)
- https://www.gwern.net/index (interesting articles)
- https://slatestarcodex.com/ and https://astralcodexten.substack.com/ (science, psychiatry, philosophy, rationality, etc.)
- http://steve-yegge.blogspot.com/ (programming)
- https://creativegood.com/blog/ (UX, and more)
- https://daringfireball.net/ (Apple)
- https://backreaction.blogspot.com/ (physics)
- https://thelastpsychiatrist.com/
- https://historyforatheists.com/ (historical myths)
- http://funcall.blogspot.com/ (programming, compsci)
- https://blog.fawny.org/ (accessibility, design)
- https://blog.jessfraz.com/ (technology)
- https://use-the-index-luke.com/blog (databases)
- https://weekendfisher.blogspot.com/ (God, love)
I can list some of my favorite articles from one of these blogs if anyone is interested.
And indeed, in Scheme (the language that originally made tail recursion famous) you can get stack traces from loops too! Well, at least in one Scheme implementation, MIT Scheme.
The MIT Scheme debugger has a notion of "reductions and subproblems" [1], which basically correspond to tail calls and non-tail calls. You can step "backwards" to the previous reduction, or "upwards" to the previous subproblem. In terms of other programming languages, that corresponds to going back to the previous loop iteration, or going up to the previous call frame.
Behind the scenes, this is implemented using a "ring-buffer or ring-buffers" [2], which stores the values of local variables for, e.g., the last 10 iterations through a loop. So if you step back further than that you will lose history and jump back to the start of the function call.
(The second link goes to the same blog as OP, I guess he has been writing a lot on this topic!)
[1] https://www.gnu.org/software/mit-scheme/documentation/stable/mit-scheme-user/Subproblems-and-Reductions.html#Subproblems-and-Reductions
[2] http://funcall.blogspot.com/2009/05/you-knew-id-say-something-part-iv.html
A couple of years ago I finally started to understand the Waters series facility [1], which was offered as an alternative to Loop. It's a bit finicky, and the error messages are often mystifying, but I have come to quite like it for some more complicated looping situations. The thing that finally made it accessible to me was a blog post by Joe Marshall, Series tips and tricks [2]
Ironically enough, once my use of it advanced enough, I found myself writing producing forms which are just a restricted form of Loop invocation - Series turns out to compile down to Loop. It's just that I (and others, apparently) find Series expressions more pleasant to deal with than Loop expressions.
[1] https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node347.html#SECTION003400000000000000000
[2] http://funcall.blogspot.com/2022/07/series-tips-and-tricks.html
> A common refrain is that Emacs is an operating system (OS). This isn’t true, but what invites comparison to an OS is its ability to orchestrate applications and utilities above the OS kernel level.
Only because Lisp Machines, or variations thereof didn't took off in the mainstream.
"Symbolics Lisp Machine demo"
https://www.youtube.com/watch?v=o4-YnLpLgtk
"Emacs and Lisp"
https://funcall.blogspot.com/2025/04/emacs-and-lisp.html
While Emacs was forked by Lucid as XEmacs to make one of the very first ideas of LSP, nowadays most features have been integrated back into Emacs
https://dreamsongs.com/Cadillac.html
"Lucid Energize Demo"
https://www.youtube.com/watch?v=pQQTScuApWk