Yesterday's article, about programming language syntax in an ideal world, provoked a small storm of controversy over on
reddit.
Unfortunately, since there were a couple of other Haskell articles on
the same page, the article's argument, that languages of the future
should look like pseudocode, was somewhat lost. A number of
readers assumed the article was a piece of Haskell advocacy, which wasn't the
intention. Instead, it was a plea for the syntax of future languages to
be optimised for writing by humans, and not for parsing by compilers.
That is:
The languages of the future should look like pseudocode
I'll cache the original example of "future syntax" here, so you can keep
it in mind:
fib 0 = 0
fib 1 = 1
fib n = fib (n1) + fib (n2)
Note that this is an argument for syntax, independent of whatever
language you want to use. And it ignores all efficiency issues in current
languages (that's a job for the compiler designers of the future).
Of course, programmers being very practical people took this as an
opportunity to demonstrate how their language of choice (and being
reddit, this means lisp) already provides this "future syntax". Well, sort of:
(define fib
(matchlambda
[0 0]
[1 1]
[n (+ (fib ( n 1)) (fib ( n 2)))]))
(define (fibo x)
(cond
((= 0 x) 0)
((= 1 x) 1)
(else (+ (fibo ( x 1))
(fibo ( x 2))))))
(define (fibo x)
(case x ((0 1) 1)
(else (+ (fibo ( x 1)) (fibo ( x 2))))))
(defmethod fib ((n (eql 0))) 0)
(defmethod fib ((n (eql 1))) 1)
(defmethod fib (n)
(+ (fib ( n 1)) (fib ( n 2))))
(define (fibo x)
(if (< x 2)
x
(+ (fibo ( x 1)) (fibo ( x 2)))))
(let ((fibs (makehashtable)))
(defun fib (n)
(if (< n 2) n
(or (gethash n fibs)
(setf (gethash n fibs)
(+ (fib ( n 1)) (fib ( n 2))))))))
Others focused on improving the particular languages I cited. The
best contribution on this issue came from Greg Buchholz, who illustrated neat
implementations in a variety of languages, far more flattering than
the examples I used (which, incidentally, were not my creation, they were
wikipedia's ....)
Perhaps unsurprisingly (in hindsight) plenty of readers assumed the
plea for future syntax was a plea for "Haskell now!", and talked at length
about efficiency concerns, and the lack of real world code/IO in the
examples:
all of these are monstrously inefficient...
> let fibs = 1 : 1 : zipWith (+) (fibs) (tail fibs)
> take 10 fibs
[1,1,2,3,5,8,13,21,34,55]
That's surely more efficient
And kinda memory eating :-)
You'd better choose something like
fib = fib_iter 1 1
where
fib_iter x y n | n == 1 = x
| otherwise = fib_iter y (x + y) (n 1)
there's a much more efficient way to do it in Hs using the language's
lazyness (the ability to recursively define infinite lists):
fibs = 1 : 1 : zipWith (+) (fibs) (tail fibs)
And, this being the interblargh, some people missed the point entirely:
This code doesn't have any resemblance to everyday programming however -
which generally involves trawling through databases, string matching, and I/O.
What is the point of showing examples which do not reflect reality of
most(?) programing tasks?
I've been a ASM/C++/C# developer for over a year now. But seriously, how
stupid is this? You are going to tout a language strength due to how
efficiently it can work out the Fibonacci sequence?
That is not a real-world example, and if you were to use a real-world
example, this code would be horrific.
So what can be made of all this? I think that it can be objectively stated that
current programming languages, for the most part, don't look like ideal
pseudocode languages, with syntax often bogged down in language features, and
parser hints. Overuse of keywords (defun,define,def,let rec), extraneous typing
hints (like $x), and parser hints (';' and '{' '}'), all obscure the underlying
code. Step back for a second: you're 10 years old, and you're hoping to become
a cool hacker. What syntax do you wish you could use?
Now Python, Haskell and the Lisp family seem to be the closest to
where we want to go, but they're not there yet. Even in Haskell, where years
were
spent
sorting
out
the
syntax, and as a result has some nice features for
human programmers (pattern matching on data structures, and lovely whitespace),
you can still end up writing awkward code (and this is entirely my own fault):
withGS :: (g -> (g -> LB ()) -> LB ()) -> ModuleT (GlobalPrivate g p) LB ()
withGS f = withMS $ \state writer ->
f (global state) $ \g -> writer $ state { global = g }
readGS :: ModuleT (GlobalPrivate g p) LB g
readGS = global `fmap` readMS
writeGS :: g -> ModuleT (GlobalPrivate g p) LB ()
writeGS g = withGS (\_ writer -> writer g)
forkLB :: LB a -> LB ()
forkLB f = (`liftLB` f) $ \g -> do
forkIO $ do
timeout (15 * 1000 * 1000) g
return ()
liftLB :: (IO a -> IO b) -> LB a -> LB b
liftLB f = LB . mapReaderT f . runLB
So finally, if you're in any way involved in the design of syntax for a new
language, or fixing up the syntax of existing languages, please think
hard about what you would have wished to program in, had you never been
exposed to the languages of today. Programming languages don't have to be ugly
and noisy! Concentrate on what the human author of the code would like to
write: code that is aesthetically pleasing and even beautiful, and don't
compromise your syntax, for the short term gain of making parsing easier.
/home ::
/haskell ::
permalink ::
rss