in reply to Re^7: Thread on Joel on software forum : "I hate Perl programmers."
in thread Thread on Joel on software forum : "I hate Perl programmers."

What is it that mathematicians say? Something like, "One page of symbols and formula is better than 100 pages of text"

We may say it, but it's not always true.

In my experience, a lot of the reason mathematics is so inaccessible to the masses is the focus on obscure notional tricks, rather than the underlying reasoning.

It was quite a jarring experience when I finally had a mathematics teach in my final year of high school start teaching counting arguments using plain english; it all felt seemed somehow suspect, less logical somehow.

It also demonstrated just how much time I was taught to spend translating real world problems into formal mathematical notation before I began reasoning about the solution.

As a mathematician, I understand the power of a good notation; but I also understand how quickly formal notation can become a barrier to understanding. I was taught to always break reasoning down into discrete steps; synthesis is almost always easier than reduction. The same idea applies to coding: break code into small, discrete, provably correct steps whenever possible.

The exact opposite of this is the mathematics trick a few undergrads pulled on their TA. Not knowing how to solve the problem correctly, they wrote the beginning, worked ahead a few stesp, wrote the desired conclusion, worked back a few steps, and linked the two sections with the words: "Trivially, the result follows", and relied on the TA to agree that the result was "trivially correct". Since their TA was a genius (with a 90%+ average in the hardest university math courses every single year), he would often agree that it was "obviously correct", and they'ld get full marks through sheer guesswork.

Too much coding I see these days ends up being of the "trivally correct" stripe: people stare at code for three days, can't find the bug, finally decipher the flaw and fix it, and then declare what the code does to be "obviously correct now".

Me, I learned the hard way: better a series of small steps where you can find your mistakes, than a complex expression of interwoven logic that don't quite work, though your not sure why...
-- Ytreq Q. Uiop

  • Comment on Re^8: Thread on Joel on software forum : "I hate Perl programmers."

Replies are listed 'Best First'.
Re^9: Thread on Joel on software forum : "I hate Perl programmers."
by BrowserUk (Patriarch) on Jun 17, 2005 at 23:09 UTC
    In my experience, a lot of the reason mathematics is so inaccessible to the masses is the focus on obscure notional tricks, rather than the underlying reasoning.

    I cannot express how strongly I agree with this. Of late, I've been trying hard to get into FP (several flavours) and the damndest thing is that, for the most part, I don't even understand the tutorial explainations of the basics of teh language, never mind the reference material.

    The underlying assumption that using math notation to describe functional notation on the premise that everyone will understand, is functionally flawed :) And the way functional code is typically layed out (the 2d syntax) is a total barrier to overview.

    Oh well. Just keep plugging away, maybe the pennny will drop.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
      Well you can do a pretty decent job of functional programming in Perl. The main concepts are trying to avoid side effects, and using higher order functions (like map and grep) when appropriate. I'm not sure what you mean by 2D syntax, but I'll give it a stab using Haskell (since I've noticed you've mentioned it before). Every FP tutorial on the planet must use the factorial function to demonstrate the features of the language, this one is no exception. Here's the easy definition...
      fac n = product [1..n]
      Haskell syntax for defining functions is very lightweight. No "sub" keyword or curley braces necessary. The lone '=' sign is what gives away that this is a function definition. The above code creates a function called "fac" of one argument (called "n"). The product function takes a list and multiplies each element together. Brackets are used to create lists, and the ".." operator is somewhat similar to perl's. So the factorial is the product of the numbers from 1 to n. Here's a recursive version...
      fac n = if n<1 then 1 else n * (fac (n-1))
      "if" is a function in Haskell (like most things), very similar to the ternary ? operator in Perl. As for 2D syntax, maybe you're refering to pattern matching? (like multi-methods in Perl6)...
      fac 0 = 1 fac n = n * fac (n-1)
      This merely means that if you call fac with an argument of 0, the answer is one, anything else compute n*fac(n-1). Haskell also has pattern gaurds. The pipe ('|') symbol introduces a set of alternatives to check on each invocation of the "fac" function. If it finds one of the conditions evaluates to true, then it returns the value of that alternative ("otherwise" is equal to "true")...
      fac n | n == 0 = 1 | otherwise = n * (fac (n-1))
      In perl, it would look something like...
      sub fac { $n = shift; if($n==0) { return 1; } else #otherwise { return $n*fac($n-1); } }

        Yeah! I get all that no problem, but that is as useful in understanding how to program in FP as HelloWorld.(c|pl|etc.) is in teaching you how to program in an imperative language--basically nil.

        FP is far more than the use of high order functions and functional composition and recursion, which can be crudely approximated by:

        P:\test>p1 perl> sub prompt { printf "What's your name?: "; } sub getAnswer{ chomp( $_ =<STDIN> ); return $_; } sub greetings{ print "Hello $_[ 0 ]. Welcome to functional programming +!\n" } sub main { prompt , greetings getAnswer };; perl> main;; What's your name?: BrowserUk Hello BrowserUk. Welcome to functional programming!

        The real essence and subtlety of FP is the typing system, but there is a dearth of documentation on this that isn't couched in complex theoretical explainations and references to research papers that you need a subscription to download, in pdf form (which I hate vehmently because the Adobe reader and GhostSscript UI's are so crap). And when you do download them, you need a greater-than-grad-level-degree of understanding of math notation to even begin to understand. I didn't do math at that level.

        Example:

        And didn't that translation at the bottom really clarify everything!


        Even the gentlest of the tutorials splits it time between

      • Saying the same things in the same way, but repetatively and slowly (like an Englishman speaking to a "foreigner" :).
      • Propagandising the benefits and dogmas of FP. Even the "Haskell tutorial for C programmers" somehow falls into the trap of justifying FP, rather simply explaining how to use it (well).
      • Uses syntax in the examples that you can't simply type into the "runloop interfaces" without modifying it.

        A picture (demo) is worth a thousand words (and 1000 trivial examples). My biggest single problem with all the "tutorial" material for FP languages, (and I think that I have read/scanned/attempted to follow all the commonly available ones for Haskell, Ocaml and Oz over the last few months), is the total absence of a fully worked, practical example. Something that starts with a real world practical problem, including all the "messy stuff" like IO, retained state (even better if a little FFI and concurrency was thrown in), and then takes you through the development process step-by-step without all the propaganda.

        What I mean by "2D syntax" the Python-style required whitespace--2d alignment rules. The FP guys appear to think this is elegant, and I guess it is compared to Lispish, but the always-moving-right, "hanging indents" formatting, looks anything but elegant or even structured to my eyes.

        Examples:

        Lisp

        defun generate-tree (phrase) "Generate a random sentence or phrase, with a complete parse tree." (cond ((listp phrase) (mapcar #'generate-tree phrase)) ((rewrites phrase) (cons phrase (generate-tree (random-elt (rewrites phrase))))) (t (list phrase))))

        Haskell:

        take m ys = case (m,ys) of (0,_) -> [] (_,[]) -> [] (n,x:xs) -> x : take (n-1) xs

        Ocaml:

        #let rec member x btree = match btree with Empty -> false | Node(y, left, right) -> if x = y then true else if x < y then member x left else member x right;; val member : 'a -> 'a btree -> bool = <fun>   #let rec insert x btree = match btree with Empty -> Node(x, Empty, Empty) | Node(y, left, right) -> if x <= y then Node(y, insert x left, right) else Node(y, left, insert x right);; val insert : 'a -> 'a btree -> 'a btree = <fun>

        And what is 'a? Where did that come from? "a" seems to be a "generic type placeholder" generated by the type inferencing, but what is the ' doing? Is it a function that tests the value of the type represented by the "a"?

        I (vaguely) recall that in math, ' is often used to indicate the derivitive of a term or expression, but in that case it is usually used postfix, not prefix as here.

        This sort of stuff pops up early and ubiquitously throughout the tutorials without any explaination. I think I tracked it down that ' is just-another-character used to create identifiers, like "_" in perl or C, but why is it used/generated here?

        The Haskell tuts never explain what '$' does that I have found, but if you look at any non-trivial Haskell code, it pops up all over the place. (I know what it does now through trial and error!).

        And '.'. This is explained, usually as f . g x = f( g( x )) or f . g x = (f (g x ) ) depending upon flavour, but what that doesn't tell you is when you need to use it! In most dialecs, simple abutment of functions f g x achieves the same thing--except when it doesn't and the '.' is required!

        Enough ranting, (sorry you caught me after another fruitless search for information and examples, and several long and ultimately useless downloads of PDFs that I had to search manually because the stupid UI won't let me search for stuff that wasn't bloody indexed. Grrr!).

        For now, I'm making best progress with Oz which has a more traditional syntax and some very nice concurrency features--despite it coming with a emacs interace (Nice OS, shame about the editor!).

        I think Ocaml will (eventually) be my favorite, despite all the same charges applying, because of it's balance of FP, imperative and OO features and very efficient standalone programs. Just a shame about the aweful windows runloop interface.

        I'd like to like Haskell with it's purity and laziness and monads and generics and FFI, but doing anything useful in it seems to be much harder to start with.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.