I've been teaching my 11 y.o. son programming with Julia and Project Euler. My personal opinion is that Julia is the best language to introduce to new programmers. First of all, it has very good "IDE" support in various editors with LSP (VS Code being a great newbie choice). It supports a nice mix of language features, mainly imperative constructs, but it also excels as a functional programming language.
I was considering Haskell as a language, but unfortunately Haskell often feels like it gets in the way of your learning sometime. Want to teach for-loops for instance, well you gotta break out Monads.
Python is a popular choice, but I think it's a horrible pedagogical language. I don't want to teach OO concepts, instead I rather have him think about the algorithm and basic computer science principles. The only reason I think people choose Python is that it's super easy to get started, but I think all that simplicity is just a wrapper around a fairly complex runtime. With Julia the abstractions are generic enough that they can stay as abstractions. With Python, I'd feel like I'm just teaching a package (i.e. numpy) and the concept of generic programming would just get ignored.
If you eventually reconsider the decision to not teach OO concepts, I recommend Pharo as a awesome language, including for teaching OOP as it was meant to be. It has firm roots on Smalltalk, very easy to install, with a superb IDE and proven track record on children education. There's a MOOC on https://mooc.pharo.org/ See also https://news.ycombinator.com/item?id=27368962 For a example of a nice educational project done with it, see https://news.ycombinator.com/item?id=30562009
Thinking about it some, I agree. I'd have (and have in the past) disagreed about it being the best language for self-learning as a new programmer - it's decent, on par with most other languages, but not the best language for that purpose. The error messages can be inscrutable (for now), the types can get complex and messy (though they're are getting better, easier-to-read signatures over time), it might not have the library for what you have the impulse to build (which is an important motivator for new programmers - though this is again a "for now" problem).
But with someone to guide you, it absolutely can be the best first language, because of the breadth of programming concepts it introduces you to. Python is a good first language if, say, you're in college and just want to get started with doing things in programming - where the focus is on programming as a tool to get the results you want, and less so on the shape of the tool itself and how it shapes your mind. At younger ages, when there's time to lay a firm foundation and explore the tool itself, Julia makes for a much better foundation, being a better jumping-off point for many more diverse paths in the programming landscape.
I like Julia as a teaching language because it has a good model for computation. The same is true for C BTW which is also an excellent first language. For example, take a look at these lecture notes on Optimizing Serial Code (https://book.sciml.ai/notes/02/). You can walk through details about memory layouts, stack vs heap allocations, different levels of compiler IR and optimizations, etc. all in a way that flows easily. Then talk about parallelism, code generation, type inference, etc. Julia is both "explicit" and "concise" in some sense: it can look simple, but it's also easy to peel back the abstractions and really show what's working and why. C is a good teaching language because it has a similar explicitness to its computing model.
I really dislike Python as a teaching language because students can leave a course without really knowing much about computation itself. They might know how to "make Python do a thing", but they don't leave with an appreciation of computation itself. The details of memory models, cache levels, AVX, distributed computing, etc. are just a whole different universe and students have to almost relearn from scratch with a new model if they want to advance. Things like Bjarne's "Why you should avoid linked lists" (https://www.youtube.com/watch?v=YQs6IC-vgmo) are incomprehensible to the programming model provided in the Python universe: it has a better O(n) so why would it be worse? While you always need to make simplifications while teaching, I believe that starting people on Python goes a bit too far and sooner or later they have to unlearn bad habits or relearn a new programming model.
I believe it's much easier for students to learn something explicit and then later say "yeah Python automates the heap allocation of objects by boxing like this, and from what you have already learned, that's obviously slow which is why the language has overhead but it's pretty nice ain't it?"
"Python is a popular choice, but I think it's a horrible pedagogical language."
Something like this occurred to me when I learned Javascript. Python is so easy initially, but its interesting how the CS principles of it are not so easy.
I think this popular cause someone with a CS background can quickly get the ideas of variables and printing to terminal, but look at how javascript vs Python handle objects.
Javascript it is just setting a variable to a bracket of values, like an array. Python you have to tackle concepts like what a class and self are.
Not saying Python is better/worse than any other for learning, but I am certain its popularity for beginners is how easy you can go from 0 to something. Not how easy it is to learn CS and programming principles.
> Javascript it is just setting a variable to a bracket of values, like an array. Python you have to tackle concepts like what a class and self are.
Python objects are pretty much the same thing under the hood. Though the OP mentions that, surprisingly, static type systems are easier to work with than dynamic ones, so perhaps we should really be considering Python with type annotations and TypeScript.
Python the language itself, perhaps not. The standard library, on the other hand, is a random hodgepodge of imperative, OOP, and functional styles, and the greater library ecosystem is no different.
It doesn't. Python is actually a pretty good language for teaching algorithms, you never need to type "defclass" unless you want to. You do, kind of, have to use methods, but that's not a huge burden for a learner compared to the other things they have to learn. Also, if you're using a language-agnostic algorithms textbook (in a course, solo, or as a mentor) then Python is very close to the pseudocode in most of those.
Python's closeness to pseudocode is one reason why it makes a fantastic choice for whiteboard coding interviews.
I've personally had interviewers frustrated that I solve problems correctly so much faster than they expected. And not only correctly, but to the point where I could type what I wrote verbatim into the interpreter and prove that it actually works.
Python is pretty much zoomer BASIC. I think it's a pretty good choice for those early painful bits of learning how to program, when you have to understand that a program is sequenced instructions to a computer, that the effect of an instruction depends on what happened before, etc. You can write a complete Python program without defining a class or invoking an object. These concepts can be introduced after the learner has the basics down pat.
I was considering Haskell as a language, but unfortunately Haskell often feels like it gets in the way of your learning sometime. Want to teach for-loops for instance, well you gotta break out Monads.
Python is a popular choice, but I think it's a horrible pedagogical language. I don't want to teach OO concepts, instead I rather have him think about the algorithm and basic computer science principles. The only reason I think people choose Python is that it's super easy to get started, but I think all that simplicity is just a wrapper around a fairly complex runtime. With Julia the abstractions are generic enough that they can stay as abstractions. With Python, I'd feel like I'm just teaching a package (i.e. numpy) and the concept of generic programming would just get ignored.