10 ms·
Seven Deadly Sins of Introductory Programming Language Design (1996) [pdf]
- SavantIdiot 5y ago"if (x=0 || -10<y<10)"... it just feels so right, but nope: smackdown. Your first lesson in how programming languages will conspire against you and your logical thought processes. I think this paper is a great attempt to shake off the curse of knowledge, and I'd gladly read another dozen things that show the language getting in the way of the process. Is there a name for this kind of higher level analysis of programming language?
- DeathArrow 5y agoI presume that if you are learning something, you follow an instructor, a textbook or some kind of tutorial. Before learning conditions you should already know that = means attribution, not testing for equality. I'd rather blame the quality of learning resources or student lack of attention here than the language design if someone mistakes = for equality operator.
- goto11 5y agoBad language design is not the fault of the student. After all, languages exist which doesn't have that problem.
- dunefox 5y ago> Before learning conditions you should already know that = means attribution, not testing for equality. Depends on the language. F# and CL, for example, would like a word.
- SavantIdiot 5y ago> I'd rather blame the quality of learning resources or student lack of attention here than the language design if someone mistakes = for equality operator. I see you don't have much experience with other programming languages, or you would have known that "=" is the equality operator in BASIC, Pascal, SQL and Excel... just to name a few of the most common occurrences where beginners -or- large-scale deployments would encounter this. That is the entire point of this paper, it uses C as an example, but the concepts are the same.
- ModernMech 5y agoMaybe if it were a single student, but this is a problem that has persisted across generations of students. I'm a fan of blaming tools for being poorly designed rather than the sad student who has to suffer using them. All their lives these students are told that "=" means that the left hand side and right hand side are equivalent. Then we give them a tool that throws the well-understood semantic meaning of the symbol out the window (for no good reason, mind you), and then you say we are to blame the student for being confused?
- iudqnolq 5y agoThe other symbol is also behaving in an unexpected way here. I can't think of any language that allows 10 < y < 20.
- pkrumins 5y agoEveryone's first language should be Perl.
- Garlef 5y ago> but fails to take into account the apparently inability of many students to master the concept and practice of consistent indenting I've seen seasoned programmers struggle with this.
- pansa2 5y agoInteresting to contrast this paper’s opinion of significant indentation (“detrimental cleverness”) with “I will never again voluntarily use a language without mandatory indentation for teaching novice programmers”. http://okasaki.blogspot.com/2008/02/in-praise-of-mandatory-indentation-for.html http://okasaki.blogspot.com/2008/02/in-praise-of-mandatory-i...
- ggm 5y agoI generally line up with this. Syntactic confusion is a huge barrier to "thinking" in a new computing language, now add to it by having to "think in new concepts" which lies in the semantics. Its a kind of combinatorial explosion of meaning and power of ideas. The expressive qualities of lambda notations can die in the inherent confusion "am I parsing this sentence-in-lambda left-to-right or right-to-left" -And I really do mean parse, the internal brain-model of "reading the words and symbols" informs how people construct a mental model of what they see. yes a <- b and b -> a could both mean B is transformed into A but one of them is actually "read" as "a is derived from b" which is different, syntactically, and in comprehension terms (I don't mean any computing language does this specific notation. I just mean, that how we comprehend this is subtly different, and in the case of first/new programming language, its a higher-order problem. New concepts, new notation)
- sixstringtheory 5y agoSyntactic synonyms and homonyms (from 3: Grammatical Traps) are some of my all-time peeves in programming languages. I find they're usually bound up with 6: Excessive Cleverness.
- dhosek 5y agoMy experience learning programming languages (starting in grade school): 1980. BASIC (AppleSoft an TRS-80, but later DEC, Waterloo and QBASIC added to the mix) 1982. 6502 Assembler 1982. Pascal (this became my primary high-level programming language in 1986–1992) 1984. C 1985. Rexx (still the best scripting language I've worked with) 1985. FORTRAN 1986. TeX (programming in a macro-expansion language is it's own bizarro world) 1987. PostScript (the joys of coding in a stack-based Forth derivative) 1988. Modula-2 1988. Metafont (Another Knuth macro-expansion language, but one with fewer quirks than TeX) 1994. C++ (it didn't really click until STL came on the scene, there were some awful C++ books published in the 90s) 1995. Perl 1997. Java 1999. PHP 1999. JavaScript 2007. Ruby (I had a diversion from 2002–2006 where I tried to leave programming behind for mathematics) 2009. Groovy 2009. Erlang 2009. Scala 2011. Objective C 2016. Swift 2018. Kotlin 2018. Clojure 2021. Rust I'm by no means an expert in all of these languages (I can really only claim current competency in the JVM languages these days, although my Rust is getting better and JavaScript is not so much a language anymore as it is a foundation for other languages built on top of it through the various libraries), but I do think that BASIC and Pascal still great languages for beginning programmers, although it's hard to go from, say, UCSD Pascal to dealing with OOP or FP which are the dominant paradigms of development these days. It's also somewhat interesting to see that my picking up new languages tended to come in clumps, with things piling on fairly quickly after my return to programming work in 2006.
- fsckboy 5y agoAppleSoft on a TRS-80? is that right?
- dhosek 5y agod'oh, and, not an
- hnzix 5y agoTurboPascal had a lovely IDE which made it really nice for teaching. Whereas teaching Java was a struggle initially for novices because of the relative difficulty in configuring the development environment. This is probably the most important thing PHP also got right for beginners.
- anyfoo 5y ago> The premier example of the adverse effects of cleverness in programming language design (and one which is obvious to programmers at all skill levels) must surely be the C/C++ declaration syntax [10]. On the surface, it seems like an excellent notion: let declarations mirror usage. Unfortunately, the very concept undermines the principle of visually differentiating semantic difference. Does it ever. From today's point of view, C's declaration syntax is just bizarre, especially if you spent some time with a "modern" type system[1]. The result of this declaration-mirrors-usage cleverness is not just the more encompassing insanity like the emergence of the "spiral rule", as found here: [2]. (Isn't it fun that that site promises to enable "any C programmer to parse in their head any C declaration!"? You know you have a problem when that's a novelty.) It's also the emerging little paper cuts, like the fact that it should be "char* c" with the * hugging the char because * modifies the type and so is part of it, but because of the "mirror usage" concept you better actually write "char *c", because that's how the parser groups it, as part of the variable. In effect, multiple declarations in one statement must have confused many novices, when they wrote something like "char* p, q", and surprisingly got a "char* p" and a "char q". > Students have enough trouble mentally separating the concepts of declaration and usage, without the syntax conspiring to blur that crucial difference. Yeah. I learned C in the 90s (and fortunately by now know exactly where to distribute my "volatile"s and "const"s in a complex type), but I still remember how confusing it was that the * practically did the opposite in declaration vs. usage. In a declaration it makes a pointer, in usage it dereferences it. Consider the very important difference between those: char *p = q; *p = q; Fun. [1] "Modern" in quotes, because one prime example, Haskell, is old enough to appear in this 1996 article. [2] http://c-faq.com/decl/spiral.anderson.html http://c-faq.com/decl/spiral.anderson.html
- abecedarius 5y agoThe bigger mistake was to mix a prefix pointer operator in with the postfix [i] and (x). You end up with the spiraling-out parsing even for expressions, not just declarations. With Pascal's postfix ^ everything reads left to right.
- deleted 5y ago[deleted]
- teleforce 5y agoVery insightful paper, thanks for sharing. Firstly, I'm surprised that having no garbage collection did not make to the list of the seven deadly sins. Secondly, someone here also mentioned about the very useful Turbo Pascal IDE and having an excellent IDE can really help in the visual learning approach that's required by all learners [1]. If any programming languages has the intuitive capability for real-time visual interactions as described by Brett Victor it will be great [2]. Thirdly, the paper failed to mention that beginner friendly programming language has a very high chance to be adopted by the industry and becoming extremely popular. This is self evident by the recent exponential popularity of Python. When the paper was written back in 1996, Python was just another scripting programming language with "Jack of all trades, master at none" language. At the time it's playing second fiddle to popular programming languages including Perl, PHP and TCL! The same can be said to D language now but as they've always said, time will certainly tell. Personally I think D language did not tick most of the seven dealy sins boxes and have made the most of the seven significant steps towards more teachable language mentioned in the paper. It has the most Pythonic feel to it compared to other compiled languages. It also the has default garbage collection that will make it an excellent introduction for programming. Of course you can exercise bit manipulation like a madman with D (also cautioned in the paper) but that's only when you really want to after you've considerably comfortable with the language [3]. The only crucial thing that's currently missing is an IDE that is intuitive and beginner friendly. [1] The Biggest Myth In Education: https://www.youtube.com/watch?v=rhgwIhB58PA https://www.youtube.com/watch?v=rhgwIhB58PA [2] Bret Victor - Inventing on Principle: https://www.youtube.com/watch?v=PGDrIy1G1gU https://www.youtube.com/watch?v=PGDrIy1G1gU [3] Bit packing like a madman (DConf 2016): https://news.ycombinator.com/item?id=28522040 https://news.ycombinator.com/item?id=28522040
- bsder 5y agoIn 1996, it wasn't yet clear that GC languages were going to sweep the field. Yes, Perl was at its zenith. But Microsoft treated VB6 like a red-headed stepchild in spite of its popularity. Tcl was ... okay. However, Lisps were on the downswing. Java and Javascript were just getting started. Python was considered one of the many Perl wannabes. Computer memory was just becoming cheap, and overprovisioning of RAM is what allows GC languages to flourish.
- darksaints 5y agoI don't know why this is still being done with new languages, but it really peeves me when I see syntactically privileged data structures. You get them in practically all languages, whether they're records or dicts or arrays or lists. The only language that I've seen that even gets close to the right approach is Scala. You don't use special syntax to create an array that you wouldn't also use for a list or a map or a set. There's no special bracket type, no master data structure that all others must bow to. And the result is that you don't mindlessly default to the wrong data structures for your problem.
- Teafling 5y agoI like the way Kotlin does it: listOf(1, 2, 3) setOf(1, 2, 3) arrayOf(1, 2, 3)
- AnimalMuppet 5y agoBut C/C++, Ada, and Haskell were never intended to be introductory programming languages! Complaining about them violating rules for introductory languages is judging them by the wrong standard. (Yes, I know, instructors have tried to use them as introductory languages. That isn't the fault of the languages, though...)
- nickkell 5y agoThese are still problems developers face when learning that language for the first time, even if they have experience with another language
- przemo_li 5y agoHaskell was intended for academic language on which lazy programming can be researched. It was designed to a small extend to be used during CS studies. Witness some of those functions in prelude that will crash app on incorrect input, which could be trivially improved to total versions. Those where defined they way they are because it ease teaching. I was not there, so I can not tell if Haskell comity had any thought put into teaching younger audiences. However, Haskell was never, ever meant for teaching The Programming. It was always about lazy evaluation and static type system. In deed, here in lies the trap. Python programmer expect different foundation to be laid during programming course to R programmer, to Prolog programmer to Haskell programmer to Clojure programmer. There is no introductory programming course. We specialize from get go, and its only through learning multiple languages and/or advanced concepts that we generalize ;)
- deleted 5y ago[deleted]
- DeathArrow 5y agoOne of the decisions that payed the most in my later programming endeavors was deciding to learn C and C++ in high school, after Basic and Pascal. That taught me a lot about how computers work and how the programs are supposed to run, once in memory. When I've learned higher level languages later, it helped me to know what is under the hood. So, if I'm supposed to teach someone programming, I'll start with C or a sane subset of C++ rather than Python. The other decision that payed a lot was learning algorithms and data structures.
- tester34 5y ago>One of the decisions that payed the most in my later programming endeavors was deciding to learn C and C++ in high school I started with C++ in high school, but probably not $newest_version_at_the_time and it was mess for me I felt like I was fighting language / compiler instead of trying to solve problems. "wtf? I remember that it worked fine week ago! <googling again some basic thing like array length>" or asking teacher about compiler errors Somebody then showed me C# and I instantly switched
- goto11 5y agoSo you learned Basic and Pascal before you tackled C and C++, but you think other students should start directly with C or C++?
- DeathArrow 5y agoYes. Basic and Pascal did not help me much.
- deleted 5y ago[deleted]
- agent327 5y agoI've given this advise before and it may sound really weird but I stand by it. Beginner programmers should read this book: http://www.z80.info/zaks.html http://www.z80.info/zaks.html Yes, it's old. Yes, it's for a non-current CPU. But it explains how a CPU _really_ works, how binary numbers work, etc. It's a fantastic primer for understanding what's really going on inside the machine, and because it is old, it isn't yet burdened by all the complications of modern CPUs. At the same time, learning those will be easy after you understand what was written here. Of course when I read it, I was 15, and sitting behind a Z80-based machine, writing assembly programs by writing them out on a piece of paper, and translating to hex codes by hand... Ah, fun times :-) The biggest thing I ever wrote that way was an RLE cruncher which I had designed myself. You take care of details when you program that way, I can tell you...
- foolfoolz 5y agothe synonyms increasing learning time is huge. i used scala for over a year before i understood for comprehensions were equivalent to nested flatmaps. i also don’t like when people refer to languages as “simple.” this pdf is great it calls out the ones with less rules have more complex logic. brainfuck is simple i think the most important part of learning to program is not the language but having a good teacher
- goto11 5y agoYeah "simple" is one of the most abused words. Everyone agrees simple = good when it comes to programming, but what does it actually mean? Often is means "easy to understand", but what is easy to understand depend on prior knowledge. For example plus(a, b) is simpler in the sense it doesn't special-case arithmetic and reqiore fewer language primitives, but a + b would seem simpler to most students.
- urthor 5y agoThe best definition of simple I've found is "one that takes the least cognitive load to use/comprehend." With programming it's actually hugely complicated, because are you trying to lower the mental effort to read, or the mental effort to write? a + b is simple to write because it reminds you of high school mathematics. However, I'd argue from operator import add, mul def square(x): return mul(x, x) def sum_squares(x, y): return add(square(x), square(y)) result = sum_squares(5, 12) Is an excellent way for newer programmers to read code, and learn what is happening.
- DeathArrow 5y agoI don't believe in the usefulness of a language designed for teaching, unless the student is 7 years old. I think that someone will get much better dividends in long time if they start learning a language designed to be useful, to solve problems.
- goto11 5y agoDo you have experience teaching programming to beginners? Languages are not equally easy to learn. Both Python and C++ are designed to solve problems, but Python is much more approachable for beginners - perhaps because it was heavily inspired by the teaching language ABC.
- DeathArrow 5y agoIf simplicity is good for a learning language, than Brainfuck wins hands down.
- deleted 5y ago[deleted]
- deleted 5y ago[deleted]
- bborud 5y agoLearning programming isn't so much about the language as it is about human beings and motivation. While language enthusiasts are very excited about type systems and technical details like syntax, what beginners need is to get over that initial threshold and to be able to self-motivate. The first question to ask when choosing a language is: is it useful for practical programming? Can the students do something that feels like an actual accomplishment within the first week? If it isn't, then you can't use it as a beginner's language because it has a weak reward mechanism. The reward is to be able to solve practical problems that mean something to the student. And this is critical in the initial weeks and months. Printing a fibonacci sequence is not rewarding for most students. It is for some, but in my experience, not most. Printing a fibonacci sequence with tail recursion even less so because a student will have no idea of why this may be important. Being able to write a program that meaningfully communicates with its surroundings to do work IS inspiring. Whether it is consuming input from the outside and doing something with it, blinking a LED, making an HTTP request, or sending a message. (Or in the case of my nephew: write a Discord bot that honks a horn when his friends are online and try to get his attention. Which didn't just solve a practical problem: it gave him status among his peers, which is a strong motivator) For instance: I tend to recommend Python as a first language. I don't like Python myself, but I recognize that it a) allows you to do practical things, b) it has a relatively simple syntax, and c) it doesn't really force a lot of fluff on you that "this will make sense later". It also allows you to postpone topics that initially just confuse students. Java, JavaScript, C, C++, Lisps and perhaps more esoteric languages are for later. Yes, I know people think some of these are "the right way" to start, but that's often the teachers focusing on their own interests and not focusing on the student. Bad teacher. Let's get people over the first couple of hurdles first, and then we can talk about what's next. But you always have to remind yourself that introductory programming is about humans.
- urthor 5y agoI am a big fan of showing two languages at the start. Statically typed Java/something so that the idea of data types is ingrained. Then rapidly switching to Python after the first lesson. A real problem I've seen (and had) with absolute beginners doing Python, is they really struggle with the types of abstract variables for the first little while when they're "getting stuff done." "Knowing" to use type() to debug your programs isn't something that comes intuitively to a novice who's been programming for all of 25 minutes, They have absolutely no idea that builtin is there or they need to use it. A quick Hello World in something with static types, and a "tour of data types" can go a long way. Also helps sell them on Python. I wonder if Typescript is suitably fun for this. Because I'm convinced that a significant part of the attraction of Python to beginners is pure aesthetics.
- HerrMonnezza 5y agoI wonder if there was any followup, trying to assess languages explicitly addressing programming education (e.g., Logo, Pyret) against the sins and recommendations of this paper?
- p0nce 5y agoI learned with QBASIC because you could put text and pixels on screen immediately. It is beyond useless to start with syntax, fibonacci and prime numbers.
- Someone 5y agoFTA: “A while loop doesn't execute "while" its condition is true, but rather until its condition ceases to be true at the end of its associated code block.” For me, the canonical version of “a while loop” is “while f do … od”, not the “do … while f” that that assumes, and which, I assume, they would like to replace by something like Pascal’s “repeat … until not f” I also disagree somewhat about the use of finite precision numbers. I think people (¿still?) will be familiar with them from using calculators, so having finite precision with propagating error values, IMO, would be fine (for signed int, I would use 0xFFF…FFF for that. As a bonus, it would mean restoring symmetry between negative and positive integers)
- gverrilla 5y agoI'm an eternally novice programmer: I only do prototypes. 15y ago I wrote my first program. Since then I learned a few languages, but never did I want to become an expert: I was always trying to do relatively easy stuff like a website, a numeric algorithm to take some decision depending on some data, or a macro inside some third-party software. It was all very unintuitive, filled with stuff "I would grasp later" - which I never did, because I didn't have the need. I still have zero clues on what a memory pointer is, for instance, and do not intend to learn it - nevertheless, I have successfully built a few working programs. I absolutely hated working with html+css+javascript, and the most intuitive language I've used is Python, but I had a few big surprises/headaches while learning it (to my level) by doing. From the top of my head, the whole scope stuff was completely non-intuitive to learn (actually I didn't learn: I just made sure it was working properly by extensive testing and experimentation), aswell as how assigning and modifying lists work. numbers = [1,2,3,4] my_numbers = numbers my_numbers[0] = 999 I would never expect, at first, numbers[0] to print 999 after these statements, etc. Something else that bothered me was how some methods worked. If I want to make a string uppercase, why wouldn't upper(strvar, other arguments if existant) work, instead of strvar.upper()?, if that's the way the user will implement his function calls? Of course I don't want to dispute how it should be, because I'm not an expert. But it seems to me a much better introductory programming language than those currently available is possible: all it has to do is limit itself to only novices. And also they shouldn't take "novices" as people with PhD in biology trying to get into datascience - these are not novices at all: they know a lot about math, for instance. The focus should be on simple operations, solely. Hackernews breakline editing behavior is also unintuitive btw.
- grumpyprole 5y ago> I would never expect, at first, numbers[0] to print 999 after these statements, etc. You are not alone! I've always disagreed with the idea that imperative programming is "more intuitive", more familiar to many perhaps. In a functional programming language, modifications to lists/collections result in new copies (with maximal sharing) and do not mutate the original. Such "persistent" collections have to be designed and implemented to make these operations cheap. Copying an array is typically not cheap and so Python just creates a new reference (pointer) for my_numbers.
- TeMPOraL 5y agoA very insightful article. Others have commented on its merits, but I have a different question - one I constantly return to: what about languages for professionals? Are there guidelines for design of languages meant for people who already know programming? Our industry has an obsession with lowering barriers to entry, making everything easy for the novice at the expense of making it difficult for the seasoned professional. It's, like, the opposite of other professions, where tools are optimized to empower those doing the work, not for ease of learning. So are there any guidelines to design of powerful programming languages? Tools that sacrifice the learning curve to make them more powerful and better at managing complexity?
- adrian_b 5y agoI believe that there are enough examples in various niches. One of the most obvious is APL and languages inspired by it. While the original APL would not be a good choice today, due to various features missing in it, for managing program structure and more complex data organization, even the first version of APL had much more powerful methods for handling arrays/tensors than almost all popular programming languages used today. When using a set of high-level APL-like operators, someone familiar with them can avoid wasting a lot of time with writing low-level redundant code, i.e. loops, like you are forced in most programming languages.
- 2RY6gGorhN733X 5y agoBoth the power and simplicity of a program come from its abstractions. Any language that makes new abstraction easy allows for a seasoned professional to easily make simple and powerful programs. Beyond that, the language itself cannot do this work for you beyond providing libraries where other programmers have done it already, and shared their work. And the reason for this is simple. To make an abstraction, we must think, and no language can think for us. The power and simplicity of our code is a product of our thinking. The rest is just technical implementation based on specs. With languages that make abstraction hard, programmers have created tools to help. HTML and CSS have horrible abstraction features. Server-side Perl and PHP and client-side javascript has been used to abstract HTML. Sass, Less, and SCSS are tools invented for CSS. The learning curve for abstraction itself is language independent.
- unwind 5y agoBesides all the C-bashing, I think it's hard to take a paper seriously when it first notes that some syntax seems to spread "memetically" between languages, such as square brackets for indexing and then turns around and complains about that, since it makes it harder to use knowledge you already have, such as subscripting for indexing (as in math). At least some leeway for the differences in typography would be sensible there, in my opinion. Source code is "linear" basic text, and expressing subscripting which is a typographical feature is not directly possible, so I think it's rich to judge language designers based on that. EDITS: Spelling, grammar.
- deleted 5y ago[deleted]
- tenaciousDaniel 5y agoI've been building a "programming" language for UI designers, and I had no idea how hard it would be to make a language feel simple. I have no experience in this area, so I'm just trying to make it feel as if it could follow naturally from verbal speech: style box fill: red width: when $size is small: 10px is medium: 20px is large: 30px height: when $size is small: 10px is medium: 20px is large: 30px
- ncmncm 5y agoIf the sins really were deadly, the languages guilty of them would be, y'know, dead. But instead, all of the most successful languages ever are guilty of all of them. Instead, any language guilty of none of them is dead. So, maybe it would better to avoid the sins, anyway, but there very clearly are overwhelmingly more important considerations to making a successful language. Luck seems to have a role, especially in the first year, but other things seem to matter later.