编程初学者应先学习函数式还是命令式编程?答案取决于学习者的背景。教学应从学习者熟悉的概念出发,逐步引入新知识。例如,从自然数感知(subitizing)到算术学习的过渡。MIT的SICP课程侧重函数式编程,但并非适合所有人。了解晶体管等底层细节对某些学习者至关重要。建议早期接触多种编程范式,并基于学习者现有知识进行教学,培养多层次的抽象思维能力。
📚 学习应从学习者熟悉的概念出发,逐步连接新知识。例如,从自然数感知(subitizing)过渡到算术学习,将具体数量与抽象数字概念关联。
🔬 MIT的SICP课程侧重函数式编程,强调消除副作用,但并非适合所有学习者。一些电气工程师因缺乏底层细节(如晶体管工作原理)而感到困惑。
🔄 对于熟悉数学函数概念的学习者,函数式编程的抽象性可能更易理解。底层硬件细节(如晶体管、门电路)对某些人来说是干扰性而非必要的。
🌐 建议早期接触多种编程范式,培养多层次的抽象思维能力。例如,Haskell程序员需理解单子(monads)的底层实现,而汇编程序员需把握寄存器分配的重要性。
🏰 教学应像建造大教堂一样,既要让建筑师(设计者)了解所用材料(底层实现),也要让石匠(实现者)理解每个部分最终的目标(高层设计)。
In the alum chat for Mirdin, someone posted the following question, "Would it be better to start teaching beginners functional or imperative programming first?"
Pretending for a second that FP and IP are the only choices (they're not), an answer depends on where your beginner comes from.
A meta-pedagogical (teaching about teaching) answer acknowledges that learning starts in a place the learner feels grounded and connects them from there to new knowledge. For example, subitizing is an innate ability. A developmentally normal child can instantly know how many objects are presented, for values up to about 5.

Image: How many dots are there? You just subitized.
From there, you can teach a 5-year-old arithmetic, for example to add, by having them subitize groups of objects alongside numerals and the math symbol +. This connects their innate notion of quantity to the abstract notion of numbers.
The MIT book and course SICP is a masterpiece in programming pedagogy, and it falls heavily on the FP side. Watch Professor Sussman absolutely rip apart side effects in lecture 5A. But not everybody "gets" this approach easily. Even Hal acknowledges in this Corecursive interview that the FP approach didn't work for everyone:
In the very beginning days, we would teach a sort of short courses for MIT faculty and some of the electrical engineers would just get stuck. "You haven’t showed us how the transistors work". ...People think different ways. Some people have to be grounded on where they’re comfortable and for some people, well, it really is transistors.
Contrast that to somebody who knows what a function is, in the math sense. The machinery of a transistor, of gates, sources, drains, and TTL will be an irritating detail, like multiplying matrices by hand.
So in the dichotomy between introducing FP and IP first, the answer might depend on where the learner is coming from. I learned IP and OOP first because that's what material was available. I was first exposed to FP in college in the form of Scheme. It was disorienting. I couldn't count all the parentheses, let alone grok tail recursion. I wish it could have been presented to me grounded in terms of what I was already comfortable with, for example high school algebra.
I say, introduce multiple programming paradigms early, and ground it in what the learner knows. A fundamental programming skill is to think at multiple levels of abstraction. The Haskell programmer needs to be aware that even monads at some point are just bits in a memory hierarchy, just as it's important for an assembly programmer to know that while register allocation is critical to performance, registers are not really what the program is about.
To close, let's ground this discussion in something we all know. To design a cathedral, the architect needs to know what bricks will be used. To build a cathedral, the bricklayer needs to envision the noble end to which each brick is set down.