I wonder if there are still undergraduate CS programs that use a functional programming language in the intro course? MIT switched away from SICP (Scheme) to Python back in the late 2000s, and Berkeley switched away from Scheme sometime afterwards. Shriram Krishnamurthi has heavily promoted Racket in education and continues to do so, but for introductory CS he has moved on to Pyret, which has Algol-like syntax as opposed to S-expressions and doesn’t require programmers to think in terms of functional programming; for example, Pyret has loops and mutable variables.
At my institution (Ohlone College in Fremont, California), we teach the intro courses in C++. However, for discrete math, a sophomore-level course, each instructor is allowed to choose the language. I chose Haskell the last time I taught the class, and I plan to use Haskell again, since I believe it’s a great vehicle for coding discrete math, plus I believe it’s a great thing teaching undergraduates functional programming early on.
Grinnell College's (my alma mater) CS program first intro course is entirely in Racket. The program basically has three sequential intro courses: functional programming with Racket, imperative programming with C, and OOP with Java.
UBC’s CPSC 110 uses Racket. It was built around How to Design Programs when I took it years ago, and at a glance I think it still is.
I don’t necessarily feel the need to ban loops and variables, but I do kind of wish schools didn’t start with object-oriented languages. My undergraduate program started with Scheme but I actually think a proper procedural language would be a fine choice too.
(Or even - and I know this is a spicy take - assembly language. An intro-level course that takes students through games like TIS-100 and Human Resource Machine might have a lot of pedagogical value.)
What I’ve observed is that people who have had to spend some time working in a language that maintains a clean separation between functions and data tend to be better at domain modeling, which ultimately enables the to produce designs that are simpler and easier to maintain. OOP can be a powerful mechanism, but it seems like, perhaps ironically, people who only know OOP tend to have a harder time reasoning about information flow, control flow and state. Perhaps because object-oriented language features are mostly meant as a way to abstract over those concerns. Which does have some value, but maybe also discourages learners from thinking about them too deeply.
I know I am biased both by my education and my chosen path. My first computer class was pascal based,my second course was intel based assembler. These were both in community college. When I started my degree in Computer Engineering, the microprocessor course was essentially an assembly course using the Motorola 6800 chip. I was lucky that the main CS courses were taught using C, course work was compiled on Vax mainframes running some unix variant. I used Borland C/C++ 3.0 to do my homework, then would have to figure out what changed when I used the Vax compiler to turn in my work. I really think it is worthwhile to get an understanding of the low level workings of computing. Every now and then I see a nice article comparing different access times for disk, ROM, DRAM, cache which is also important to know for critical code. Embedded for Telecom, Medical,etc.
My school switched to C++ for intro stuff right before I enrolled, and egad, I still think it's a horrid choice. It required learning, or at least memorizing, a significant amount of boilerplate before a freshman could even start to consider writing their logic. I'd already written an awful lot of programs before I got there so it wasn't too awful for me to make the leap. I spent a lot of time helping my fellow students get over the massive speedbumps they faced so they could start learning.
At Brown university there are 3 intro courses you can choose from. Two use functional programming languages.
Your discrete mathematics class has programming and is taught by the CS department? I can't say I have seen that. My Discrete mathematics class was taught in the Math department, no programming, and we had a few CS theory courses in the CS department which are basically Discrete++ but they were all sans programming.
my high school still uses simply scheme and SICP for the fall semesters of its CS sequence I believe, but granted it's in an affluent city in the Bay and its recently retired teacher came from UCB
Northeastern held out for a long time, only switching away from Racket, despite the protest of students and professors alike, in the last year or two.
There's an interesting historical angle here: Church's lambda calculus actually predates Turing machines by a few months (both 1936), and they're provably equivalent in computational power. Church even proved undecidability of the Entscheidungsproblem first, using lambda calculus.
Yet despite this head start, the Turing machine formalism became the dominant framework for CS theory—complexity classes, computability, formal verification. Whether that's path dependence, historical accident, or something deeper about how humans reason about computation, I'm not sure.
But it does make me wonder: if the imperative, state-based model proved more tractable even for theorists, maybe FP's learning curve isn't purely about unfamiliarity. There might be something genuinely harder about reasoning in terms of pure functions and recursion vs. "do X, then Y, update Z."
Fully acknowledge this is handwavy—curious if others have thoughts.