in reply to (OT) Has anyone gone from perl to lisp?
I first encountered Lisp on a short programming course I took many years ago, long before I used either C or Perl. I passed the course, but failed to be enthused by the language. I've paid several re-visits to the environs of Lisp-world over the years, and indeed, I'm going through another right now as it is the language used in a book I'm reading.
I can admire the elegance of the forms; the way a few basic steps can be combined into an infinite variety of ways. I can also admire the technical skills and dedication of the practitioners.
But when it comes to viewing an entire production, so much of the detail of the individual steps, and the individual performances, becomes lost in the overall spectacle of the story and production, that the technical skills become obscured in all the random running and jumping about.
And likewise, the details of the individual steps and individual performances, detracts from my ability to discern and follow the overall plot and story.
The very simplicity and consistency of the basic construction: (op arg arg arg)-- the very thing that underlies Lisp's elegance, the very thing that makes it so simple for the computer to parse and translate efficiently-- becomes the barrier to the human being's ability (*this* human being's ability), to grasp the structure and flow of the overall production.
It's not, as is so often cited, not least by me, the profusion of parenthesis that is the biggest problem, though it certainly does not help. It is much more the lack of the visual and structural clues to the organisation and flow of the code that one gets from block structured languages. The familiar keywords: if, elsif, else, for, while, until etc. that allow the brain to pick out clues to the structure and layout of a piece of code. And "pretty print" style layout does little to help.
This problem is exacerbated by the prefix-only notation. Even the least mathematical amongst us are still very familiar with 'normal' algebraic 'infix' notation, and despite the extensibility of prefix notation to multi-parameter forms, the lack of familiarity for the common 1 or 2 parameter forms detracts from readability.
Take for instance encountering this (anonymised) Lisp function(*) for the first time:
(defun f (a b c) (let ((t (sqrt (- (* b b) (* 4 a c)))) (values (/ (+ (- b) t)) (* 2 a))) (/ (- (- b) t) (* 2 a))))
Even with the presence of various instantly recognisable motifs, working out what it is intended to do is quite difficult when compared to an equivalent Perl definition:
sub f { my( $a, $b, $c ) = @_; my $t = sqrt( $b**2 - 4*$a*$c ); return( ( -$b - $t ) / 2*$a, ( -$b + $t ) / 2*$a ); }
(*)I'm aware that there are better alternate implementations
Some people will be thinking to themselves that if the functions were given proper names then this problem would disappear. But, this particular function executes a formula that is instantly recognisable to anyone who has done a little mathematics. Most function definitions you will encounter in programs will be very specific to the domain of the program, and so far less recognisable.
Besides which, there is the secondary problem of deciding whether the implementation of the formula is correct.
How many of the Lisp-familiar readers picked out that the lisp definition above has a deliberate error?
For an instructive exercise that demonstrates the difference very vividly, go to google earth or MSN Virtual Earth and find a satellite image of a piece of countryside you are familiar with. Then look at the same thing with an overlay of the major roads and town names. Pretty much all the same information is there in both representations, but the blandness and sameness and lack of key-points and highlighting in the bare image, make it much harder to discern the detail. Much harder to orient oneself to the layout.
And once you have located a particular point of interest, when you go off looking for the next, it's very easy to lose track of the initial point when you need to divide your attention between the two. The lack of reference points seriously detracts from the visual parsability of the code.
With C and Perl (and the many other block structured languages), the basic structure of program is clearly delineated by the familiar --even across languages--keywords and structural elements. but it goes much further. There are also the 'built-in' functions, which in the case of C, the standard C library serves the same purpose.
Despite the richness of these function-sets, they form a contained vocabulary of words that one pretty rapidly becomes familiar with, that serve to enhance the immediacy of ones understanding of unfamiliar pieces of code.
With languages, like Lisp and Haskell, where one defines your own DSL to solve each individual problem and subproblem space, each organisation and even programmer, develops their own libraries of DSLs, and choses their own names--and more importantly, their own naming conventions--for them. And these start at the lowest levels, so the process of becoming familiar with any given piece of high-level code requires you to start much lower in the chain in order to develop your understanding. And worse, whatever familiarity one achieves with the building block levels at one organisation are usually not transferable to others.
Standardised libraries like Haskell's Prelude go some way to mitigating this problem. But then, in the process of constructing those libraries, they are in effect reconstructing Perl's built-in vocabulary, and in part, throwing away some of the purpose of the minimal language definition in the process.
The Lisp family of languages are tuned for their parsability by interpreters and compilers, not human beings. And being a human being, I prefer the extra structural reference points that the block structured syntax of C, Perl and similar give me. Both from the point of constructing code, and more so, when trying to understand pre-existing code. Especially code that I did not write.
|
---|