12 ms·
Mistakes in programming language design
- singular 16y agoI totally disagree on the parser-unfriendly syntax point (no. 1). C++ is a particularly bad example in that code cannot be definitely parsed without semantic information, however I think limiting yourself to a language which can be expressed as LALR/LL(1) is pretty brain dead - you limit yourself to what a given algorithm can express clearly rather than what is clearest to the programmer. It's really actually pretty hard to make a language "naturally" LALR anyway, at least without hacks of some kind. C# definitely isn't LALR, there are many features which get in the way of LALR-ness, such as generics which are, however, useful. I do agree on every other point, however!
- joe_the_user 16y agoAnd I completely agree with you here. The progress in programming language design is going to come from eliminating human unfriendly syntax. The closer you can get to something that let's someone express their intentions without restrictions, the better. The computer is, uh, servant of a human. There are many barriers in the way of programming languages or computers in general adapting to human functioning. But whenever someone takes the line that says humans must-adopt-to-computers, it is a fail. And that fail is going to be swept away by the next technology which just works.
- antichaos 16y agoProgramming languages force programmers to think clearly and express ideas unambiguously. It's not a bad thing we should avoid; it helps us write robust software.
- Zak 16y agoBoth points are valid. Programming languages should be designed for people to use, and only secondarily for machines to execute. However, they should be designed so as to encourage clear expression of ideas when practical. I think whether a general-purpose language should discourage or prevent unclear thinking is an open question. I don't think I've seen an example of a language doing so without being somehow crippled, and that's a Bad Thing.
- binaryfinery 16y ago" Programming languages should be designed for people to use" Exactly. Which means that it must be tool friendly, hence LALR/LL(k). Unless you want to do all your refactoring yourself.
- singular 16y agoI don't think LALR/LL(k) implies automated refactoring is easy and anything else does not!! Obviously non-context-free grammars are a problem, but a GLR or PEG grammar is still perfectly refactorable. You forget that refactoring an intuitive grammar to LALR involves totally mangling that grammar and making it more difficult for everyone. If the language is expressed as a GLR or PEG grammar then tool makers have it easier I reckon - easier to understand grammar. The way to really ensure it's easy for everyone is for the compiler write to provide some abstract yet intuitive representation of the underlying grammar. It really isn't an either/or, it's a case of both at once, I think!
- binaryfinery 16y agoI think you hit the nail on the head there. "Context-free" is more of a requirement than LALR or LL. The author clearly isn't a parser writer. I am, but I've yet to try a PEG grammar because ANTLR does such a great job. But this doesn't change his point (or mine): languages should be created that are easy to write parsers for, so that its easier to write good tools. And I think this applies to the grammar too: ANTLR's .g files are a good grammar language because its easy to write tools for - hence AntlrWorks.
- beza1e1 16y agoI'm the author and i did write some parsers. However i'm more in the write-parser-by-hand camp and context-free is not so hard here. ANTLR needs strange hacks to parse Python with its whitespace indentation. A handwritten parser just needs some context within the lexer. In my eyes a parser generator is the solution, if you want to trade efficiency for cross-language-portability. ANTLR is probably the best solution at this point, though the C backend is quite wierd.
- joe_the_user 16y agoThere's no language of higher order than machine code that allows you to specify computer behavior unambiguously (even that's doubtful). In fact, any entity abstract enough to be called "an idea" is going to be ambiguously specified. The question is what sort of ambiguity is most useful - ambiguity about about which object shows itself on the screen is great in an object-orient window manager. Ambiguity about which memory location to read when dereferencing an uninitialized pointer is less useful.
- brazzy 16y agoThe progress in programming language design is going to come from eliminating human unfriendly syntax. The closer you can get to something that let's someone express their intentions without restrictions, the better. The computer is, uh, servant of a human. And a servant isn't very useful if he can't understand its master. Ignoring machine-friendliness in language design just leads to worse and more buggy tools (including compilers). whenever someone takes the line that says humans must-adopt-to-computers, it is a fail. And that fail is going to be swept away by the next technology which just works. Except the "just works" is far more likely to be actually achieved if it's easy to make it work as well as easy to understand. Besides, "human-friendly vs. computer-friendly" is a false dichtomy. There are certainly things that are good for one and bad for the other, but language features can also be good for both, or very good for one while incurring very small disadvantages to the other.
- singular 16y agoBut don't forget that we don't have to limit ourselves to LALR or LL(k). Approaches like GLR allow the user to be happy as well as the tool writers. And again, don't forget, the tool writers have a harder time if they have to mangle their grammar to fit LALR, then write a bunch of hacks around it to get stuff to work. Working around an algorithm which can't express usable languages properly is a bit silly I think. It's better to improve the algorithm in the first place and keep everybody happy!!
- beza1e1 16y agoI do not know a single editor which does syntax highlighting by actually parsing (including semantic analysis) the code. Most of them use regular expressions at most.
- gte910h 16y agoI completely agree with the parser friendly syntax (and disagree with you). The issue is that tools are important. C++ is famously tool unfriendly, when it in fact, has the most need for tools to verify it. From my understanding of the generics problem, generics do not get in the way of LALR requirements. You just have to implement them slightly differently than C# does to make the tokens for the generic types more identifiable. So you can do generics, just they can't look like C++ makes them look.
- shadowfox 16y agoIt would be interesting to see how often code is written for the language vs how often a parser is written for the language before tuning the syntax for one or the other. Also I suspect that a sufficiently well designed parser api, even if it internally uses quirky non LALR parsing techniques, will get a lot of tools going without the need for rewriting a parser each time.
- singular 16y agoThat is not the only problem I had with writing a LALR C# grammar. Anything even slightly touching anything else that is used for other stuff caused endless shift/reduce reduce/reduce conflicts. Not to mention I had to totally mangle the intuitive representation of a C# grammar to fit LALR. Forcing tool writers to have to do the sort of shit I did, even without generics, is not the way forward. The alternative of a fully LALR-able language is not necessarily desirable either - 'I want to add a feature which makes my language far more usable, oh hang on, that screws the LALR. Oh well, let's scrap that then'. How about looking at LALR alternatives?!
- antichaos 16y agoC++ is a pertinent example of terrible syntax design. Not only does the complexity make it a nightmare to write a standard compliant compiler, it also slows down development because you need much non-contextual information to read code.
- binaryfinery 16y agoYeah, Ok. http://www.youtube.com/watch#!v=v9kTVZiJ3Uc http://www.youtube.com/watch#!v=v9kTVZiJ3Uc "A keyboard? How quaint!" Sure, it would be great if you could just describe what it is you are after, except for two problems: 1. Programmers out of a job. 2. How good are you at describing what you want? In English? You think an AI will be able to do it better than a lawyer? What has this got to do with your point? Well, until that time, your productivity is going to be determined by the quality of your tools. You are going to need to iterate, test and refactor. To do that you need good tools, and good tools are hard to write for non-easily parsed languages. Compare the refactoring tools for C++ (limited) and Objective-C (ha ha) vs C# or Java. My productivity is double, tripple in Java and C# because I'm not spending my time moving characters around files - I'm programming. http://blog.binaryfinery.com/?p=250 http://blog.binaryfinery.com/?p=250
- chc 16y agoYou're comparing four relatively similar C-family languages — it's not too surprising that tool support is the biggest difference here. Throw in Ruby or F# here if you really want to compare language quality vs. tool support.
- jmillikin 16y ago> Dynamic languages are fast enough to implement internet services and outgrow the demeaning term "scripting language". This is never going to happen, because "scripting language" is used as a slur or insult, rather than a term with any usefully defined meaning. It's not possible for Python to "outgrow" being a scripting language as long as that's used as a condescending shorthand for "doesn't look like C++". Consider Ruby. How many applications do you know of which use Ruby for scripting? Or Python -- I think my system has two applications which can be scripted in Python (Gimp and Blender), but many dozens of applications written in Python. If Ruby and Python are scripting languages, then so are Smalltalk, Haskell, Boo, or dozens of other high-level languages. And yet, you'll never hear of these being called "scripting languages" because nobody has an axe to grind against them. ------------ Unrelated to that, Haskell does have pointers (including null pointers) -- you can use them just like pointers in C/C++.
- j_baker 16y ago"This is never going to happen, because "scripting language" is used as a slur or insult, rather than a term with any usefully defined meaning." This isn't necessarily true. See Ousterhout's dichotomy: http://home.pacbell.net/ouster/scripting.html http://home.pacbell.net/ouster/scripting.html
- silentbicycle 16y agoI agree with you, but I think jmillikin's point is when most programmers hear "scripting language", they think "dumbed-down programming language" rather than "cleanly separated layers of design".
- jmillikin 16y agoThat's a really wonderful link, and I wish more people used the definition it advocates. I've one minor complaint, in that it conflates typeless and dynamically-typed languages, but considering when it was written that's not a big deal -- strong, dynamically-typed languages probably didn't exist in any significant way. Unfortunately, almost every use of "scripting language" I've ever heard is more along the lines of: "We can't write our GUI frontend in Python^! Scripting languages are too slow for rendering advanced graphics." Usually uttered by somebody who's been writing C++ for 20 years and refuses to touch anything more recent. ^ Substitute Boo, Haskell, Scala, Clojure, or anything else without enough curly braces
- j_baker 16y agoI don't necessarily agree with #2. Yeah, SML has formalized syntax, but it's also a frozen language. It simply isn't practical to have completely formalized semantics for a language like Python or Ruby that are still actively being changed. Nor is it necessarily always possible to eliminate all implementation-specific quirks. In short, it's a good thing to have a language have few quirks, but there is such thing as overspecifying.
- silentbicycle 16y agoThese things don't need to be taken to their logical extremes, though - handling most of the semantic edge cases is still an improvement, even if it isn't exhaustive. Emphasizing well-defined semantics could also be a push to keeping the language small and clean.
- RodgerTheGreat 16y agoIt's possible that I'm missing the thrust of #0, but I don't see how an object-oriented language completely without the concept of a "null pointer" could be used to construct elementary data structures like linked-lists and trees without resorting to special classes as terminators. It would be just as clumsy as using null pointers in the first place. If "not-null" references were provided in addition to normal references, the effect would be pretty similar to the common usage of "final" fields in Java- compiler-enforced initialization.
- Groxx 16y agoI was wondering that too, so I looked up the linked "Cyclone" language. If I'm understanding what I read there, the entire #0 is pretty misleading. Basically, it boils down to adding a "qualifier" to the language, so you can mark pointers as nullable / never-null, so the system doesn't have to check.[1] You can also mark them as "thin" (no pointer arithmetic) and "fat" (safer pointer arithmetic), all of which is accomplished by putting a "@nullable" / "@notnull" / etc. qualifier on the pointer when you declare it (I think). @nullable does a check before each access, @notnull does not. So, it's C + super-static-types to make C somewhat safer. At the cost of making the language significantly more complex. But still not safe, as this is put there by the programmer - people make mistakes. And C programmers seem especially vulnerable to making things unsafe "for speed"... what's to stop an overzealous optimizer from marking more pointers as @notnull? [1]: http://cyclone.thelanguage.org/wiki/Pointers http://cyclone.thelanguage.org/wiki/Pointers
- ekiru 16y agoIf the compile can't statically prove that a pointer can't be null, any attempt to convert it to *@notnull inserts a runtime assertion that it isn't null, according to the website.
- Groxx 16y agoEnabling faster compiled code if it can prove it can't be null? Makes sense, and a useful trade-off for essentially polluting the language with yet more keywords. But that still means you can force it to read things as never being null, even when they could be, and I still don't trust developers (despite (because of?) being one). Unless I'm reading that wrong?