Shriram Krishnamurthi, a Brown University computer science professor, writes about programming languages, teaching, and Scheme macros.
HN links his PLAI textbook, his paper on automata via macros, and Brown PLT's work such as Flapjax, mostly as teaching resources.
There are people working on this rigorously, try going through Prof Krishnamurthi's papers: https://cs.brown.edu/~sk/ he teaches higher-order functions because they've found it helps students understand how an API works, he designed his own learning language from scratch (Pyret) and I went through much of his older CS19 Brown course here: https://learnaifromscratch.github.io/software.html because the course uses a web browser IDE, they were able to take stats of all students to see when they started to write code VS when they wrote examples and tests. The tests he teaches are property-based not typical cs101 style tests just plugging in edge cases and hoping for the best. His goal is to turn the teaching of programming from absolute guesswork and wishful thinking into something proven to work which is admirable, most CS professors that I had just taught whatever they felt was best for them when they first learned, not what is provably best for everyone in a large class.
Of course the answer to everything is 'just be motivated and dig deep into X then you will learn as you go' like building a program from scratch, or how some mathematician's learned by being fascinated with various topics and purely researching them on their own for hours on end. For some people this will work others will just give up when it gets too difficult, I find it's something you can do after 1/2 of a course, you have just enough education to be able to read the documentation and now you can actually…
> But starting out with something that is not Python, with the goal of ending up doing Python, seems like a funny way to approach things.
Another project in this space is Pyret [0]. The Pyret language has been developed with the express intention of taking completely novice programmers, teaching them how to program in a language with reasonable semantics [1], and progressively add language features until they eventually switch to Python. The language is integrated into the DCIC course [2].
The idea of a language that can progressively gain features was (to the best of my knowledge) pioneered by Racket. The idea is that a particular file can be declared at a specific "language level" (I think that's the terminology), which restricts the set of features available to the user. Over the course of the semester, new features can be added as they are taught. The advantage of this approach is that students do not accidentally encounter surprising semantics that they inadvertently internalize to the detriment of their long-term learning.
The Pyret project is actually spearheaded by Shriram Krishnamurthi at Brown University, who was on the original Racket team. His career has focuses on the application of PL theory and tooling to computer science education. One of his most recent publications is particularly interesting with regard to the present topic, which is an experience report detailing what happens when students move from Racket to Pyret and from Pyret to Python [3].
[0]…
You don't really need much math for SICP. You can learn a few random pieces of math from SICP, and without background that will be harder and you might feel like you're missing out, but these are just examples; you can just trust the math works and focus on how they implement it in code, it's structure of the code they want to teach you about.
And, it gets better, IIRC from chapter 2 there is much less math.
What happens in the first chapter, is that SICP is exploring various control structures (and abstractions over them) before teaching any compound data structures at all. So all it has to work with is numbers.
But as number theory teaches us, numbers actually have a rich internal structure, and SICP uses that to make "interesting" examples!
(This aspect of SICP is one of the big critiques in the paper http://cs.brown.edu/~sk/Publications/Papers/Published/fffk-htdp-vs-sicp-journal/paper.pdf
which explains the motivations beyond HtDP textbook. In particular, HtDP shows compound data structures first, and uses those to start with explicit methodology for data-directed design of code.
These are smart programmers and smart educators, and I trust they made a better intro course. I won't recommend SICP for people who don't know any programming at all. But I feel SICP has a magical voice about the art of programming that HtDP didn't replicate — though I haven't read HtDP, only leafed through it a bit.)
So I don't recommend to to cram algebra/calculus before you begin…
I have an intuition that the comment you're responding to has a lot of truth to it, but I am going to have to educate myself to give you an answer.
One thing I do know is that JS and Lisp both treat functions as first-class citizens, allow some degree of meta-programming, and rely heavily on hierarchical (e.g., nested objects in JavaScript vs. s-expressions in Lisp).
Passing functions by reference enables both LISP and JS to compose higher-order functions and, as suggested in another commented, both Lisp and JavaScript's "dynamic stack frames" somehow live updates to running code without requiring a complete restart of the application. The only clear example of this I can find, however, is Bun's --hot mode, which performs a "soft reload," updating its internal module cache and re-evaluates the changed code while preserving global state.
I have some vague notion that this is a favorite feature of Lisp, but it's not clear to me that it's unique to these language families.
---
Edit: Lexical scoping, closures, some tail-call optimization...
---
Edit 2:
> Programming language “paradigms” are a moribund and tedious legacy of a bygone age. (Dave Herman)[0]
---
Edit 3:
> The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?" Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's…
Syntax is tricky and contentious, and our team members do love our Schemes. Members of the Pyret team have actually done some research on the issue of parenthetical expressions in introductory programming, and seen that parens aren't necessarily the best:
http://cs.brown.edu/~sk/Publications/Papers/Published/mfk-val-grow-tree-expr-integ-fp/
One issue is that it's too regular: since open-paren means so many different things (start of a "defun", start of a function application, start of an argument list in a "defun", start of a syntactic form like "cond" or "if", start of a clause of "code", the list goes on), a typo can easily and drastically change the kind of error message you get.
More closely matching syntactic forms to the type of behavior the expression has will hopefully let us improve error messages and grokkability of the difference between concepts. We're collecting data about common syntax errors and actively asking what we can do better in syntax design based on what we observe about Pyret's use.
I would encourage you to view the syntax as "Python, but repaired", for the following reasons:
1. Pyret comes out of Shriram's group's expertise with pinning down exactly what Python and other dynamic scripting languages do right, and (mostly) do wrong. Check out their recent paper Python: The Full Monty: A Tested Semantics for the Python Programming Language http://cs.brown.edu/~sk/Publications/Papers/Published/pmmwplck-python-full-monty/ for more context.
2. Ruby is far and away not the originator of 'end' to end blocks -- this comes from Pascal and is in other languages that have nothing to do with Ruby, like Lua.
3. Languages that aren't Haskell have ADTs too; it happens that they've lifted an ML-style syntax for defining them.
4. Python is widely used pedagogically, so for better or for worse, students are already being familiarized with the colon, which I agree is a bit anomalous.