1. 10
  1.  

  2. 6

    This is from early 1978; it was before EWD had switched to writing the EWDxxx series entirely in his handwriting, so reading the HTML transcription is better than reading the original PDF.

    It has a few gems in it:

    some people found error messages they couldn’t ignore more annoying than wrong results, and, when judging the relative merits of programming languages, some still seem to equate “the ease of programming” with the ease of making undetected mistakes.

    (PHP is perhaps the modern paragon of this questionable virtue, although Perl, Forth, and assembly language have held the crown previously, and JS has attempted to contest PHP’s position.)

    the modern civilized world could only emerge —for better or for worse— when Western Europe could free itself from the fetters of medieval scholasticism —a vain attempt at verbal precision!— thanks to the carefully, or at least consciously designed formal symbolisms that we owe to people like Vieta, Descartes, Leibniz, and (later) Boole.

    This is a case where a one-line aside from an EWD does a better job of describing a subject than the entire Wikipedia article on it.

    The importance of notation as a tool of thought was a major theme of elite computer science at the time: that was the title of Iverson’s Turing Award lecture about APL the year after this EWD, and had also been the subject of Backus’s rather worse Turing Award lecture the year before, which Dijkstra famously blasted in EWD692. Backus’s lecture and attendant research, despite its serious flaws, inspired much of the work in functional programming during the 1980s, although of course LISP and ISWIM were inspirations from 1959 and 1966, respectively. ISWIM looks a hell of a lot like modern ML.

    On a related note, I’ve often noticed that our programming languages are very poorly suited for handwriting: they underutilize the spatial arrangement, ideographic symbols, text size variation, and long lines (e.g. horizontal and vertical rules, boxes, and arrows) that we can easily draw by hand, instead using textual identifiers and nested grammatical structure that can easily be rendered in ASCII (and, in the case of older languages like FORTRAN and COBOL, EBCDIC and FIELDATA too.) This makes whiteboard programming and paper pseudocoding unnecessarily cumbersome; even if you do it in Python, you end up having to scrawl out class and while and return and self. self. self. in longhand. Totally by coincidence, this morning on the bus on the way in to work, I was coding Quicksort in a paper-oriented algorithmic notation I’ve been working on, on and off, over the last few years, to solve this problem. I would include a sample here, but I don’t yet have anything digitized.

    1. 1

      Can you elaborate on your paper-oriented algorithmic notation? Sounds interesting.

      1. 2

        At present I’m using these conventions:

        • underline for subroutine/function/method definition
        • double-underline for class definition
        • I’m still vacillating between using indentation or a vertical line joined to the underline to delimit the extent of the function or class body
        • a vertical line for iteration (with the while-condition on the left, or the iteration variables and sequence on separate lines for a foreach loop, and the contents on the right). An infinite loop, or loop until break or early return, is indicated by a vertical line with nothing on the left, analogously to C for (;;). I don’t have notation for for (foo; bar; baz).
        • vertical stacking for sequence (as in Python)
        • a vertical line with crossing horizontal lines for conditionals (if-elseif-elseif-else or, with an extra horizontal line across the top with an expression on top of it, switch or pattern-matching). The conditions or patterns to match go on the left, with their consequents on the right. The last condition is typically empty to mean else.
        • ↑ for return, as in Smalltalk
        • Ruby-like @ for self, with the ability to include @vars in argument lists to set them implicitly from the argument
        • . for references to methods or other objects' instance variables, like C and its progeny including Java and Python
        • subscripting for array indexing, as in linear algebra
        • Python-style a:b for slicing, but with Golang/Numpy non-copying semantic; Alexandrescu convinced me that this kind of thing is the right primitive for generic algorithms on iterators, generators, and sequences in general.
        • prefix # for getting the length of a slice or other container
        • ← for mutating assignment (I’m vacillating between = and Golang-style := for declaration-plus-initialization), as in many notations including Smalltalk
        • horizontal whitespace for function application and argument separation, as in ML or Haskell
        • weird box structures enclosing arguments for algebraic data type constructors, although sometimes I’ve just used function application notation
        • comma for tuples, including destructuring tuples, enabling multiple assignment (Lua- or Python-style)

        So here’s a variant of a common example which can be more or less rendered in Markdown and Unicode:

        point @x @y
        ____________

        @r = √@̅²̅+̅@̅²̅
        @θ = atan2 @y @x

        r
        ↑ @r

        θ
        ↑ @θ

        ⼻ Δx Δy
        @x, @y ← @x + Δx, @y + Δy

        Alternatively you could write that last method, whose name is an ideogram for “step”, this way, which is probably how I’d normally do it:

        ⼻ Δx Δy
        @x += Δx
        @y += Δy

        You can see that it uses very few pen strokes compared to more ASCII-oriented notations, but without sacrificing rigor.

        What do you think?

        1. 1

          I’ve hacked up some examples with CSS and HTML. It’s pretty imperfect still, but well enough explained to criticize.