4 ms·
In my opinion the best sequence looks something like this: - Machine language (not assembler) — Assembler for a couple of different architectures (i.e: Von
by robomartin 5y ago
In my opinion the best sequence looks something like this:
- Machine language (not assembler)
— Assembler for a couple of different architectures (i.e: Von Neumann vs. Harvard, CISC vs RISC, etc)
- Forth (written from scratch with one of the above)
- C
- LISP
- APL
- C++
I think of everything else beyond these mostly as C/C++ cousins or derivatives. With languages like Javascript and Python it’s far more about learning the libraries than a massively different programming paradigm.
Learning each of the languages is my list —in the suggested sequence— will provide someone with a deep understanding of different ways to solve problems with computers.
- mjevans 5y agoThe machine an assembler should probably be taught together. Where possible either emulations of real chips, programmable logic simulated chips, or real chips should be used. I recall the class which used a 6800 derivative in one of my college courses had a _very_ well written developer's spec manual for it. Complete with a (large) table that showed the logical relationship between the binary value of an instruction and the assembly mnemonic. Today that might be RISC-V. 'x86' and ARM should also be used, and at least a taste of very constrained systems for super cheep stuff and very low level state machines for components would help round out the package. Forth should be a semester project for one of the classes. This should include some practical case where either a manually clocked serial link, a set of dip switches and memory transfer captures, or some other constrained input method (maybe that 'boot sector forth' I recall seeing recently?) are used to trickle the core into RAM and then add higher level instructions. This might also include a small boot blob that inits the platform and opens an external data link; a useful example for subsystems.
- robomartin 5y agoThe intent behind making a distinction between machine language and assembler is because one can offer a deeper understanding of what actually goes on at the lowest level of computing. The way I would prefer to teach machine language would be to start from scratch. This means you would create and define a simple set of instructions in the context of an equally simple 4 bit processor the students would build on a breadboard out of simple chips. And, yes, the microcoded instructions would be coded by hand using a diode matrix. I truly believe such an exercise has enough value that it should be the starting point of a real education in computer science. From there it's on to assembler on preexisting processors. The reason Forth follows assembler on my list is that you can easily bootstrap Forth from scratch on any processor. Building the language from scratch is, again, to repeat myself, a worthwhile exercise. You would use assembler to get started and then switch to the embryonic Forth to build upon that. At some point you write your own code editor in Forth. From there there are a number of interesting applications (PID motor controller?) that could be implemented with the language you just built from scratch. C offers an entry point into a world of languages that look and feel like C. It provides a tool that is close to the hardware, yet high level enough to allow for much greater freedom of expression. Doing arrays in Forth is a very hands-on proposition. In C it's pretty easy. Once you are good with C you can easily pick-up languages like Javascript and Python. Not the same thing but you "speak" the same words to the computer to achieve pretty much the same thing. A "while" loop and an "if" conditional are the same incantations. LISP opens the mind to an entirely different paradigm. It is well worth learning. The same is the case for APL. I don't think of these languages as "career level" languages. That may have been the case ages ago. No longer the case. However, the perspective gained is invaluable. As we try to solve more and more complex problems the limiting factor might very well become our ability to express ideas for a computer to solve these problems. Having the perspective of languages such as LISP and APL makes someone realize there are other valuable approaches to solving problems computationally. Finally, C++, well, it's the entry point into object-oriented programming. This, BTW, was pretty much my path through computing. I can't complain.
- _huayra_ 5y agoAs someone who has taught (or TAed) undergrad courses in all but APL and machine language, I would suggest a different sequence: - LISP / Scheme - Python - C - Assembler / machine - whatever else beyond here maybe leave out the LISP depending on how religious one feels about it (I'm a fan, from a pedagogical approach at least). Most students have a very weak understanding of what a computer does (i.e. Von Neumann arch, executing an infinite tape of instructions, etc). I like LISP / Scheme because it really helps bridge the gap between expressions (which students can pretty intuitively grok from high school math education) and it really has no language design warts; you can write a metacircular evaluator in ~10 lines. Python is a next step because it goes from "how does coding work?" to "okay how can I do stuff with this?". The language itself is pretty straightforward (although certainly has its warts too, e.g. the odd methods of variable scoping), but there are a ton of libraries and it is pretty much useful straight away for anything one wants to design a course around. Many unis combine "learning Python" with programming some robot, doing an AI thing, or other such practical outcomes. Importantly, whenever I taught a "relatively beginner Python course", I would always spend a huge amount of time on teaching students about ipdb / pdb. Allowing students to explore the state and stack of a running program is a critical doorway for them to step through to not only learn how to debug their own problems (less of a load on me!), but also really start to grok the "program is a sequence of instructions that change state" thing. C before assembler, although I have found it's often useful to "combine" them so that the concept of a pointer seems less odd and more useful. Also, C still has tools that students can use to explore their code (e.g. gdb), whereas they're much more on their own with assembler. After that, it really depends on what students want to do. They can stick with systems stuff and do Rust / C++ / Go or go to Javascript or go crazy with the PL stuff with Haskell, etc. Certain people (perhaps yourself) really understand this "program is a sequence of instructions that mutates state" thing, but in my experience, most of my students really don't get that. If I were to throw them into that deep end of the pool where they lack the tools to debug their own problems, I would get a lot of bad reviews / people switching out of the major. On top of that, students often like to really be able to produce cool stuff, which they can in Python very easily. Many students may bounce off the lower level stuff if they just want to do front end too, which is perfectly fine in a "top down" approach from higher-level languages.