Sponsored Link •
|
Summary
My friend James Ward was explaining some of the struggles he had learning Scala, in particular partial functions.
Advertisement
|
Note: I'm leaving the original text in here because that's what people were commenting on. But on further study, I realized that neither James nor I had enough of a grasp of this topic to discuss it. In particular, Scala's PartialFunction is quite different than what I suspect we were trying to figure out: Partially Applied Functions -- unfortunately the names of the two concepts are quite similar. The PartialFunction only accepts a subset of inputs, and is used, according to Odersky, to "write control structures that are not easily expressible otherwise." Thus it may be more analogous to the Strategy design pattern, although I'm not certain about that. A reply in this post seems to make a case that PartialFunction is a kind of Chain of Responsibility pattern (I find similarities between Strategy and Chain of Responsibility, myself).
Here is one of the best posts on PartialFunction that we came across. In it, we see the most compelling use of PartialFunction I've seen so far:
scala> List(41, "cat") collect { case i: Int ⇒ i + 1 } res1: List[Int] = List(42)
The original article:
He tried to understand that one concept for a couple of months before it made sense to him. Admittedly, partial functions are not intuitive for anyone who has been schooled in traditional programming, but still, looking at the problem he was trying to solve it seemed like James was required to expend too much effort relative to the simplicity of the problem (as he pointed out, now that he understands the concept it seems straightforward).
He showed me the code, and it was basically a situation where there was common code in the existing function, and the partial function completion allowed the programmer to add the custom code. A light bulb went on: "It's the Template Method design pattern!" (Here I was thinking of partially-applied functions).
And my initial reaction was that the template method shouldn't be this hard to understand; that Scala had made life more difficult.
However, after sleeping on it I remembered the observation that several people have made: "A design pattern represents a language failing." Objects aren't really designed to solve this particular problem, so you have to do the Template Method to compensate. What you're actually doing is saying "here's common code, you fill in the custom code," and if a functional programming idiom does that for you, then partial function completion is actually more obvious and a better fit. I initially interpreted the problem through the lens of the Template Method pattern because that's the way I already knew how to analyze it, but the more I think about it the more Template Method seems like an awkward patch and partial functions seem like the elegant approach.
With this new perspective, the next time I approach partial functions in Scala I will have to see if it feels better -- often once you really get the motivation behind a feature it becomes transparent.
Taking a step back, I have a worry about Scala, which is what I'll call "The Perl Effect." Perl prided itself on allowing "more than one way to do it." As a result, you could see many different implementations of the same code, often remarkably different. You'd have to parse through the code before realizing that all the programmer was doing was something you could translate into a simpler form. Often Perl programmers tended towards excessive cleverness. Even worse is when the clever code is your own, and you can't figure it out because it's been several days or weeks since you wrote it. The Zen of Python includes the maxim "There should be one -- and preferably only one -- obvious way to do it" precisely to counterpoint Perl's "There's more than one way to do it."
One might even suggest that Perl has reached end-of-life as a language (does anyone still believe that Perl 6 will ever arrive?) precisely because of the infinite varieties of expression, which sounds good in theory but is not so maintainable in practice.
Scala too has "more than one way to do it." Most of the Scala programmers today are early adopters, and early adopters tend to love cleverness, so they have been publishing lots of clever code. I suspect that the same brain quirk that allows them to be early adopters makes them think that once they've figured something out it should be obvious to everyone else. This kind of code does not do the Scala community any good, because it scares people off and gives Scala the reputation of being quite a difficult language.
It doesn't have to be that way.
Perhaps it's time to start a style guide, and/or a dictionary of Scala programming idioms to express the "one and preferably only one obvious way to do it." Without something like this and the culture behind it, Scala runs the risk of becoming a community of clever early adopters rather than a mainstream programming language.
Have an opinion? Readers have already posted 19 comments about this weblog entry. Why not add yours?
If you'd like to be notified whenever Bruce Eckel adds a new entry to his weblog, subscribe to his RSS feed.
Bruce Eckel (www.BruceEckel.com) provides development assistance in Python with user interfaces in Flex. He is the author of Thinking in Java (Prentice-Hall, 1998, 2nd Edition, 2000, 3rd Edition, 2003, 4th Edition, 2005), the Hands-On Java Seminar CD ROM (available on the Web site), Thinking in C++ (PH 1995; 2nd edition 2000, Volume 2 with Chuck Allison, 2003), C++ Inside & Out (Osborne/McGraw-Hill 1993), among others. He's given hundreds of presentations throughout the world, published over 150 articles in numerous magazines, was a founding member of the ANSI/ISO C++ committee and speaks regularly at conferences. |
Sponsored Links
|