Monday, September 16, 2013

Thoughts on Scala Before Using It

While I think Go is my future, I'm about to embark on a project using Scala. So I've spent the last week reading Programming in Scala, by Martin Odersky et al. And I've signed up for the Coursera class Functional Programming Principles in Scala, which starts today. I do have some experience with a functional approach to programming, so it's not a completely foreign land. But I lean strongly toward an object-oriented, message-driven (push) approach to decomposing problems; the functional (pull) approach will take some getting used to.

This is the first of two posts. I'll write the second six months or so from now, after I've spent enough time with the language to feel that I “get it” — or don't. Here, then, are my first impressions, after diving just below the surface.

Things that I like

Implicit conversions
I'm not sure that no longer having to call toString() explicitly (with a null check) is a reason to use Scala, but it's close. Conversion code is almost always clutter, sometimes quite complex clutter. Being able to move that clutter into a method, and rely on the compiler to invoke the method as needed, is fabulous.
Null is an object
Java's concept of null, and the need to explicitly test for null-ness, is one of the less pleasant things that it inherited from C. It's a leading cause of code clutter, and drives the creation of utility classes that provide null-safe operations. I haven't looked at all the methods that Scala's Null provides, but equals() is enough to make me happy.
Traits
There's a well-worn adage to “favor composition over inheritance.” This can result in a plethora of function calls that simply call a delegate, violating the adage “don't repeat yourself.” Traits make composition easy, creating delegates and then hiding them behind a curtain of syntactic sugar. I will say that I've looked behind that curtain, and don't think I ever want to find myself debugging them.
For Comprehensions
This is a neat feature, which I first saw in Erlang. It makes for a very simple way to apply filters to a list's elements before taking some other action on those elements, and I agree that it largely replaces break and continue.
Match expressions
Another feature that has its roots in Erlang (or earlier inference languages). I'm especially impressed by constructor matching, which leverages the immutability guarantees of a “case” class (again, I looked behind the curtain: while I think the code generation could use some work — particularly reuse of local variables — the approach is elegant).

Things that I don't like

Optional semi-colons
Are semi-colons really that evil? They certainly aren't hard to type: the key is right there on the home row (at least on a US keyboard). Yet Scala, like JavaScript, makes them optional. Of course, the compiler still needs to decide where to end a statement, so has to have other rules. In the case of Scala, the end of a line is the end of a statement, unless it doesn't make sense for a statement to end at that point.

I personally find this rule annoying for complex expressions, which I want to format on multiple lines, with the operator first on the line (so that it's obvious). Scala, however forces me to put the operator on the end of the line, where it's hard to see, because otherwise the compiler thinks the preceding term is the end of the current statement. Perhaps this is a not-so-subtle nudge toward simpler expressions, but there are some cases where a real-world rule has lots of terms; it's just easier to read if the terms are on separate lines, even if they're function calls.

OK, that's just me whining. But, like other languages that attempt to do away with statement separators, Scala sometimes requires you to use them. One example is a variable declaration that precedes a standalone block. Not that you're likely to use a standalone block unless you're demonstrating scoping rules. But if you have to do it sometimes, why add the mental load of remembering when those times are?

Too many symbolic operators
This was one of my first impressions of Scala, after seeing a JUG presentation several years ago. I'm neutral on the subject of operator overloading: it can be abused, but I've seen enough elegant overloads to think it has value. My issue with Scala is that any arbitrary string of apparent line noise is an operator. This creates unnecessary mental load: is “::” really better than “concat”, or “<-” better than “in”? I don't think so.
Precedence and associativity rules
Languages like C++ provide operator overloading: you can create new definitions for existing operators, which follow the rules of the language's grammar. Scala provides operator creation: syntactic sugar that makes arbitrarily-named methods look like they're part of the language. But the precedence and associativity rules that underly this feature are Byzantine to say the least. There's really no excuse for this: if you're going to put programmers in the position of being language designers, you need to give them the tools to do the job properly. In this case, explicit definitions of a function-operator's precedence and associativity..
Underscores as parameter placeholders
This is, I think, conciseness taken too far: rather than define the parameters of a function literal, you use underscores in the function body; each underscore takes the place of a sequential parameter. Intellectually, I get it. Looking at code filled with underscores, I don't. And if you want to use the same parameter in multiple places, you're required to explicitly define it.

Better, in my opinion, would be an explicit parameter syntax. Personally, I like the way the shell does it: $1, $2 and so on for individual params, $* to represent all params.

Things that have me scratching my head

Primary constructor parameters and their relationship to fields
Here's the example given by Odersky (I'm copying this from the book, so errors are mine):
class Rational(n: Int, d: Int) {
  // ...
}
This makes perfect sense: by defining the class' member variables as constructor parameters, you save the boilerplate of explicit variable definitions and assignments. But then, a page later, he shows that they're not really fields in the Java sense: it's a compile-time error if you try to access them using another instance of the class:
def add(that: Rational): Rational = 
  new Rational(n * that.d + that.n * d, d * that.d)
Now, if you look in the actual class code, you'll find that these constructor parameters are, in fact, fields in the class. Unless you continue the example, create explicit fields, and don't otherwise use the constructor parameters in your code. For a language that eschews boilerplate, I just don't get it.

It is, however, something that I've seen before: Scala's primary constructor looks and acts just like a JavaScript constructor function (which is something that experienced JavaScript programmers don't often use). I can understand the pattern for JavaScript, which doesn't have rigidly-defined classes, but it doesn't make much sense for Scala.

Not everything is an expression
I've never liked the separation between statements and expressions, and Scala erodes that boundary in many places. The if expression is one such place, function returns are another. And yet, the boundary remains in several surprising places: a while statement is one example, but the truly baffling one is variable assignment. While I don't often use constructs such as x = y = 0, I do use the Java (and C) idiom of assigning a variable and testing its value (eg: (s = in.readLine()) != null)). But not in Scala.

The only reason that I can imagine is that such behavior is functionally impure: I should use an iteration function that calls another function to process the iterated value, so the language will push me in that direction. I suspect the same reasoning is why while doesn't return a value: we shouldn't be using while.

Thursday, August 15, 2013

A Journey to the Kingdom of Verbs

HRH, DGR Terra Nominem, greetings

Your Grace. In furtherance of your desire to establish diplomatic relations with our neighbors, I have traveled to the Kingdom of Verbs to meet with Queen Repl. I fear that our potential for commerce is limited. They follow exceedingly strange customs, which I shall attempt to relay by anecdote.

To all appearances Queen Repl is the sole permanent inhabitant of the land. She creates minions from pure thought, and these minions exist solely at her discretion. The queen will create complex hierarchies of these minions to fulfill a task, and when the task is complete, the minions disappear. While some of the minions are given names, those names describe but do not define them; each minion is a unique entity, created for a single purpose.

The method by which these minions interact is also exceedingly strange; it took me months to understand it. While we follow the dictum of “tell, don't ask,” they abide by “ask, and you shall receive.” And while we use diverse techniques such as Queues and Busses to decouple Producers and Consumers, they know exactly whom to ask for a service and do not look elsewhere.

Data is a topic that is rarely discussed in this land; indeed, at times it seems almost a taboo. In some cases, when asked for data, a minion will go so far as to create another minion to provide the answer, rather than speaking directly. I can only imagine this as dedication to Platonism: there is an ideal, and there are forms of that ideal, and minions work with the forms while the ideal remains unknowable. Again, it seems uncommonly strange to us, but appears to work for them.

However, this attitude toward data left me with a question: whence comes inputs to the land, and where goeth outputs? Or is the land truly inward facing, minions performing actions without effect? The answer to this question, as you might surmise, was critical to my ability to engage the Queen.

I found the answer to this question in the monadii. They go by various names, but their role is to provide minions with an ultimate source and sink for data. At first, I thought they were like the Flappers of Laputa, standing in the background to make their masters aware of the outside world. As time passed, I realized that they also were bound by the dictum of the land, and only spoke when spoken to. It was my great fortune to learn that there was a minion responsible for listening to the monadii and asking the Queen to interpret their words.

To bring my story to a close, and not waste more of your precious time, I was able to establish contact with two of these monadii, who then provided my bona fides to the Queen and returned her reply to me. While I do not know what form of intercourse our two countries can engage, I am hopeful that Nouns and Verbs will find common ground.

I look forward to my next assignment, the Land of Inference. Your most humble servant,

(signed) Reginald, extends Diplomat, implements Plenipotentiary

Tuesday, August 13, 2013

Thoughts on Unvarying Variables and One-Instance Classes

Closures scare me. There, I've said it, now the cool kids won't speak to me. Which is strange, because the cool kids all seem to be into functional programming, and I see full-fledged closures as the antithesis of functional programming. Perhaps we are using different closures.

Clearly, definitions are in order, and my definition of a closure starts with it being a function that has the characteristics of an object: it can be referenced by a variable and passed as an argument to another function. But my definition doesn't stop there. Critically, a closure has unrestricted access to variables defined in its enclosing scope.

Here's an example of a closure in action (if you don't have Go installed, you can paste this into the Go Tour to run it). Everything here happens in the main thread, but I could create a goroutine to run either function, or I could pass these functions into other functions.

package main

import "fmt"

func main() {
    x := 0

    f1 := func() {
        x += 1
    }

    f2 := func() {
        x += 2
    }

    f1()
    f2()
    
    fmt.Println("x = ", x)
}

Some people will see this and say “well, I'd never use closures this way!” I'll act as devil's advocate by saying that sometimes — sometimes — using closures this way is incredibly useful. But not often. And, unfortunately, I've seen a lot of closures used in exactly that way, often unintentionally. And that's what scares me.

For a long time I thought that my fear was simply a fear of unbridled mutability. Indeed, the first version of this post (drafted several years ago but never published) started with the following:

Var, huh! Good God, y'all, what is it good for?

That, and the title, were just too good to discard with the rest of the text. If you're too young to get the reference, don't worry; it isn't really the cause of my fear.

For the last few weeks I've been discussing my fear with friends, and I've arrived at a better reason: closures create an ad hoc class, whose methods are conjoined solely by the fact that they share common variables. As a person who believes that object-oriented programming has something useful to offer, I find this deeply disturbing. It violates several principles of object-oriented design, not least being the single responsibility principle.

But worse, in my mind, is that the methods so conjoined don't have a name. They are simply actions that happen to know about the same Thing. OK, I realize that some people scorn the idea that all Things should have names. Perhaps those same people name all of their variables a1, a2 and so on. Personally, I stopped doing that when I stopped programming in BASIC.

Named classes, when used properly, provide a way to decompose a program into clearly bounded units of functionality. The methods in the class are all related in common purpose to provide that functionality. And again, used properly, names are an important part of this decomposition; if you see that a frob is getting fribbled, your attention turns immediately to the Fribbilator (or maybe the FrobManager, but definitely not the Bargulator). With closures, and their ad hoc relationships, your task becomes much harder: you might have to walk the entire codebase.

Does this mean I reject closures? No, of course not, not even closures that make use of their ability to mutate enclosing state; as I said, sometimes that's useful. But my fear — which I now name Caution — makes me ask the following question as I'm coding: “should this be a closure or a class?”