On a more serious note yes, but again that's a cultural thing. Languages like Erlang (and OCaml, and Haskell, and...), you spend more time thinking than typing. You don't (need to) write much code, and if you think of a better way you might completely overwrite yesterday's work. You might deliver a huge chunk of functionality in a couple of pages of code that took weeks of thought, but that looks like it was typed in a day (I have been in that situation). Functional languages don't fit big-company management comfortably. They don't look like "work" in the sense that most IT organizations are used to. Java will be with us for a long time.
Remember - the author is the smartest person who will ever see a given piece of code. The reader, even if it's the same person, will be dumber.
Programming isn't literature or poetry. No one ever had to add a mail reader to"Ode to a Grecian Urn".
Part of writing good code, whether two pages of brilliance or twenty of gradual brilliance, is conveying intent in the human-readable parts. The parser doesn't care if all the functions have names like doTheNextThing() or french_onion_soup, but it would be a slap in the face to any future maintainers.
Choosing informative names and separating a program along clear conceptual boundaries can be a greater aid to understanding than any syntactic redundancies. Well-placed comments help smooth things over, particularly notes on why a particular approach was chosen. The names themselves should be able to convey what is going on in most cases.
(For distilled wisdom along those lines, see _Thinking Forth_ by Leo Brodie, also online at http://thinking-forth.sourceforge.net/.)
It's not unusual now for some of my source files to be more comments than code, the comments explain my intent and the assumptions I have made.
I'm gonna call a function french_onion_soup tomorrow just for larks :-)
The biggest thing I learned from Forth is that if I'm about to add a comment inside a function because something needs clarification, I should probably try breaking it out and thinking up a descriptive name instead.
Erlang really is easier than Java -- both to read and to write. I think people too often confuse "different" with "difficult".
For example, something like
let days_in_month m = match m with
| Jan | Mar | May | Jul | Aug | Oct | Dec -> 31
| Apr | Jun | Sept | Nov -> 30
| Feb -> if leap_year () then 29 else 28
It takes a small amount of context (all "| Val" sections without a -> ... side match together), but it's a pretty direct correspondence. public int days_in_month(month) {
switch(month) {
case JAN:
case MAR:
case MAY:
case JUL:
case AUG:
case OCT:
case DEC:
return 31
case APR:
case JUN:
case SEPT:
case NOV:
return 30;
case FEB:
if(leap_year()) return 29; else return 28;
}
}
Pattern-matching really shines when you need to destructure the argument, then do something similar to the result regardless of which case resulted in the destructuring. For example, compare red-black trees written in Java:http://www.docjar.com/html/api/java/util/TreeMap.java.html
vs. those written in Haskell:
http://www.cse.unsw.edu.au/~dons/data/RedBlackTree.html
The rebalancing code in Java is 80 lines long. The rebalancing code in Haskell is 6.
Maybe something like this (in pseudo-ML):
(* Look up order code for a Sci-Fi GadgetTM, units are in cm *)
let gadget_order_code width depth height color has_laser =
match (width depth height color has_laser) =
(* The original, simple code *)
| 5, 2, 1, Red, true -> "ZAP-X"
(* Most common width, color *)
| 4, d, h, Blue, true -> sprintf "ZAP-4-%d%d+" (str d) (str h) "+"
(* C for Custom Color *)
| 4, d, h, c, false -> "ZAP-4C-%d%d-%c" (str d) (str h) (color_code c)
(* Orange lasers are discontinued *)
| w, d, h, c, true when (w + d + h) < 15 and c != Orange ->
"ZAP-S-%d%d%d-%c" (str w) (str d) (str h) (color_code c)
| _, _, _, _, _ -> failwith "Unavailable"
That's a little complicated to determine with pattern matching or via a database, but doing it in a series of nested if statements would get mind boggling.