Hacker News new | ask | show | jobs
by StellarScience 335 days ago
You're absolutely right that "procedural", at least as I understand the word in 2025, is a poor label for 6.001.

6.001 taught 'define' and 'let' but didn't teach 'set!' until week 6 or so. So we learned functions, variables, scopes, recursion, lambdas, strings, numbers, symbols, lists, map, filter, flatten, and more - all without ever modifying a variable. That's very "functional".

Once we learned that it was possible modify existing variables, we learned object-oriented programming; objects were just lambdas with closures that took messages indicating which function to call. We then learned a fake assembly language written in scheme that had both an interpreter and a compiler, also written in scheme. While "procedural" feels wrong, I'm not sure what label one could apply to all this...

4 comments

Given their definition of procedural, the term makes sense. The book is about processes and procedures that describe how they're executed or things are computed, versus describing what is computed (mathematical sense, declarative or more declarative, closer to some popular meanings of functional programming today).

They define functional programming as "[p]rogramming without any use of assignments". Which would be a subset of procedural programming in the sense that they mean it.

They also contrast imperative and functional programming (the first being with assignments and mutations, the latter without). Both imperative and functional programming can reasonably fall under procedural programming using their definitions.

The fuller excerpt concretely put in ยง3.1.3 "The Costs of Introducing Assignment":

"So long as we do not use assignments, two evaluations of the same procedure with the same arguments will produce the same result, so that procedures can be viewed as computing mathematical functions. Programming without any use of assignments, as we did throughout the first two chapters of this book, is accordingly known as functional programming."

Btw, I've just read the first section of Chapter 5 [Computing with Register Machines] for the first time, and think it's the best introduction to assembly that I've seen (and I've seen a few).

Calling it 'fake' is dismissive. Also, it isn't written in Scheme, but merely described in the native data format: lists of symbols.

The next section builds a virtual machine that is written in Scheme to run the code. One of the beauties of Scheme/Lisp (and source of much of its power) is the simplicity of the syntax. It allows it to be incredibly succinct.

The last section in the chapter builds a compiler to translate Scheme into this virtual machine assembly code so you can run it in the virtual machine simulator. An ouroboros.

SICP is a gem. Thank you Hal and Gerry!

I can see how 6.001 was a bit like jumping into the deep end to learn to swim.

Starting from, "To design a register machine, we must design its data paths (registers and operations) and the controller that sequences these operations." In less than 5,000 words it proceeds to implementing recursive procedure calls in what amounts to assembly:

  (controller
    (assign continue (label fact-done))   ; set up final return address 
   fact-loop
    (test (op =) (reg n) (const 1))
    (branch (label base-case))
    (save continue)                       ; Set up for the recursive call
    (save n)                              ; by saving n and continue.
    (assign n (op -) (reg n) (const 1))   ; Set up continue so that the
    (assign continue (label after-fact))  ; computation will continue
    (goto (label fact-loop))              ; at after-fact when the
   after-fact                             ; subroutine returns.
    (restore n)
    (restore continue)
    (assign val (op *) (reg n) (reg val)) ; val now contains n(n - 1)!
    (goto (reg continue))                 ; return to caller
   base-case
    (assign val (const 1))                ; base case: 1! = 1
    (goto (reg continue))                 ; return to caller 
   fact-done)
A translation of:

  (define (factorial n)
    (if (= n 1) 
        1
        (* (factorial (- n 1)) n)))
It's quite a jump in knowledge, but explained very clearly through a series of guided examples. It's close to equivalent code in x86 or arm, but much easier to read.
"Programming Should Eat Itself" by Nada Amin https://www.youtube.com/watch?v=SrKj4hYic5A

The future of AI code generation?

https://neurosymbolic.metareflection.club/

Strange Loop Language Panel - Hickey, Sussman, Wirfs-Brock, Pamer, Alexandrescu, Ashkenas (2011)

https://youtu.be/zhZMaF8vq5Y?t=297

Sussman:

well it's really very hard to find the worst idea because there are so many bad ideas in programming languages. of course the ones that bother me the most are the ones that are designed to keep me from doing what i want. i was after all a libertarian programmer. okay. and so i don't want anybody to tread on me, but the worst features of languages that i can think of -- the really worst thing -- is complex syntax. okay. and as alan perlis quipped, syntactic sugar yields cancer of the semicolon. okay. the problem with complex syntax is that it hides possibly important to understand mechanisms, but more importantly it makes it very difficult to write programs that manipulate programs -- that read them, that write them and analyze them. and that, in fact, i often have programs that write programs that i want to run in-line. for example, numerical programs that are constructed from symbolic algebra expressions. okay. so that's a nice feature of lisp, for example, which has lots of parentheses, is a uniform representation of programs as data and the ability to execute code that you've just constructed. and as a consequence i would say my mantra here is syntax without representation is tyranny.

It's very "functional" in the "functional programming" sense, but not at all in the sense that 6.003 is about the "functional" descriptions of LTI systems (i.e., that the "signal" output of a "system" is a function of the input, which you can do things like take the Laplace transform of). "Procedural" is the term used in the class's textbook, and the "functions" in Scheme are called "procedures" in the Scheme standard.
Wizardry!