Deontologician

Please Learn to Code

Jeff Atwood recently made a blog post entitled Please Don’t Learn to Code. In it, he comments on the codeyear.com project.

To those who argue programming is an essential skill we should be teaching our children, right up there with reading, writing, and arithmetic: can you explain to me how Michael Bloomberg would be better at his day to day job of leading the largest city in the USA if he woke up one morning as a crack Java coder? It is obvious to me how being a skilled reader, a skilled writer, and at least high school level math are fundamental to performing the job of a politician. Or at any job, for that matter. But understanding variables and functions, pointers and recursion? I can’t see it.

Jeff seems to be confusing “understanding how to write computer programs” with “being a crack Java developer”. He concedes that the mayor of New York needs to have basic literacy and high school level mathematical knowledge, but somehow he doesn’t understand why learning to program is a necessary basic skill in the 21st century.

First, let’s dispense with his specific points before I wax philosophical about the benefits of learning to program.

It assumes that more code in the world is an inherently desirable thing. In my thirty year career as a programmer, I have found this … not to be the case. Should you learn to write code? No, I can’t get behind that. You should be learning to write as little code as possible. Ideally none.

This is a case of missing the forest for the trees. Perhaps Jeff has spent so much time blogging about software engineering principles and coding practices that he’s forgotten that all of that advice is inapplicable if you don’t already know how to code. The above is analogous to stating, “The mathematical proofs that are the most enlightening and easiest to understand are the shortest most elegant proofs. Avoid proving unnecessary lemmas and strive to reduce complexity in your proofs wherever possible. This means the best proofs are the ones you never write at all! In conclusion, don’t learn mathematics.” He seems to be inflating the scope of a specific software engineering practice to the level of a prohibition against ever writing code, and hence, allowing anyone to ever learn to program lest they add more code to this teetering pile we’ve already got!

It assumes that coding is the goal. Software developers tend to be software addicts who think their job is to write code. But it’s not. Their job is to solve problems. Don’t celebrate the creation of code, celebrate the creation of solutions. We have way too many coders addicted to doing just one more line of code already.

Yes, solving problems is the goal. And sometimes as a developer you can solve problems without writing code. This is a valuable principle to avoid adding more unnecessary complexity if you don’t need to. But again, it is not a reason to not learn how to program. It is advice to pull someone back from the edge of just coding without thinking about what really needs to be done. People who don’t know how to program don’t have that problem. Again, this is Atwood missing the forest for the bark of the particular tree he is standing right next to. It is akin to saying to a novice writer who wishes to learn the basics of story structure and plot pacing, “After years of writing your magnum opus novel, you may be tempted to continue adding epilogue after epilogue to a story that you have been engrossed in for so long, and whose characters you don’t wish to leave behind. But no, you must finish it. Eventually every story comes to an end, and you have to publish it.” 

It puts the method before the problem. Before you go rushing out to learn to code, figure out what your problem actually is. Do you even have a problem? Can you explain it to others in a way they can understand? Have you researched the problem, and its possible solutions, deeply? Does coding solve that problem? Are you sure?


This is more of the advice to experienced programmers, incorrectly aimed at people deciding whether learning to program is a worthy goal. More importantly it begs the question “How do you know if coding solves your problem if you are unable to code?” True, he does throw a bone out later in the blog post: 

I suppose I can support learning a tiny bit about programming just so you can recognize what code is, and when code might be an appropriate way to approach a problem you have.

But he equates this superficial knowledge to the ability to detect when a plumber is needed. Really? And how will you evaluate whether the coder you hire knows what he is doing? How will you specify the problem in a way that is thought out well enough that a programmer can actually accomplish it? Programming is more complicated than plumbing. There, I said it. Jeff, you have taken a bad analogy and run wild with it. Learning to program involves learning to think in a clear, logical manner. If you don’t, things don’t work correctly. In thirty years of programming, it’s easy to forget the time before you learned to program, when solving problems was an ad-hoc fuzzy mess. I’ve seen new programmers, they aren’t used to breaking down problems into clear logical components and ensuring things are consistent and make sense. This is something programming teaches you over time. Exactly the thing Jeff is saying you shouldn’t learn.

It assumes that adding naive, novice, not-even-sure-they-like-this-whole-programming-thing coders to the workforce is a net positive for the world. I guess that’s true if you consider that one bad programmer can easily create two new jobs a year. And for that matter, most people who already call themselves programmers can’t even code, so please pardon my skepticism of the sentiment that “everyone can learn to code”.

Who said anything about professional programmers? Mayor Bloomberg clearly isn’t gunning for a job in the field of software development. Unlike, say, recreational plumbing, programming is an inexpensive, easy to pick up skill that allows you to understand the world we now live in. Just yesterday, there was an article about how a judge shot down Oracle’s lawyer’s claims about the rangeCheck function, because he programmed in his spare time:

I have done, and still do, a significant amount of programming in other languages. I’ve written blocks of code like rangeCheck a hundred times before. I could do it, you could do it. The idea that someone would copy that when they could do it themselves just as fast, it was an accident. There’s no way you could say that was speeding them along to the marketplace. You’re one of the best lawyers in America, how could you even make that kind of argument?

To which Oracle’s lawyer replied:

I’m not an expert on Java — this is my second case on Java, but I’m not an expert, and I probably couldn’t program that in six months.

Just like reading, writing and arithmetic, in the modern world, you need to have programming literacy. Not just “how to use Word”, but how to code. You can only get that knowledge by learning to code.

Back to Jeff:

It implies that there’s a thin, easily permeable membrane between learning to program and getting paid to program professionally. Just look at these new programmers who got offered jobs at an average salary of $79k/year after attending a mere two and a half month bootcamp! Maybe you too can teach yourself Perl in 24 hours! While I love that programming is an egalitarian field where degrees and certifications are irrelevant in the face of experience, you still gotta put in your ten thousand hours like the rest of us.

Again, this is analogous to saying “It takes a long time to become a professional mathematician! You have to study for many years and there are only a few slots available! You can’t just pick up a book on algebra and become an algebraist in a weekend! We don’t need more sub-par mathematicians in the world. The existing mathematicians have got this covered, please stay home and don’t learn any math.” There is a vast divide between learning to program and aiming to become a professional developer. Yes, if more people learn to code, more bad programmers will be produced, and some of them will go on to become bad professional developers. But, in addition, more good programmers will be produced, and more of them will go on to become professional developers.

As our society leans more and more heavily on automation and computers, being able to understand how to use those resources to your advantage becomes more and more necessary. Not everyone will become a virtuoso programmer with short elegant programs that are easy to understand and modify. But does that really matter for 90% of people? Is it better to learn to program, and then code up a tangled monstrosity script that automates a tedious process you were doing by hand, or is it better that you not learn to program at all? I would argue the former.



Taken with instagram



Taken with instagram



Parking lot (Taken with Instagram at Great Clips For Hair)


Using pika to create headers exchanges with RabbitMQ in python

I recently had the pleasure of trying to figure out how to get a headers exchange working with RabbitMQ. Unfortunately, there is almost no documentation on how to do this! All of the other exchange types are covered quite well in the tutorials etc, but headers exchanges are apparently the red-headed step children of the exchange world. From what I gathered in this thread, nobody really likes headers exchanges because they aren’t very flexible. But they seemed pretty good for what I needed, so I dug through the pika source and cobbled together an understanding of how they work.

Here’s how you set one up and consume from one using pika (for simplicity I use the BlockingConnection type here, but the asynchronous SelectConnection is preferred when using pika. You can easily adapt the code below to use SelectConnection):

headers_emitter.py

#!/usr/bin/env python 
import pika
import sys

connection = pika.BlockingConnection(pika.ConnectionParameters(
        host='localhost'))
channel = connection.channel()

channel.exchange_declare(exchange='testing',
                         type='headers')

fields = {}
try:
    while True:
        data = raw_input('> ')
        if '=' in data:
            key, val = data.split('=')
            fields[key] = val
            continue
        channel.basic_publish(exchange = 'testing',
                              routing_key = '',
                              body = data,
                              properties = \
                                  pika.BasicProperties(headers = fields))
        print ' [x] Send {0} with headers: {1}'.format(data, fields)
except KeyboardInterrupt:
    print 'Bye'
finally:
    connection.close()

headers_receiver.py

#!/usr/bin/env python 
import pika
import sys

connection = pika.BlockingConnection(pika.ConnectionParameters(
        host='localhost'))
channel = connection.channel()

channel.exchange_declare(exchange='testing',
                         type='headers')

result = channel.queue_declare(exclusive=True)
if not result:
    print 'Queue didnt declare properly!'
    sys.exit(1)
queue_name = result.method.queue


channel.queue_bind(exchange='testing',
                   queue = queue_name,
                   routing_key = '',
                   arguments = {'ham': 'good', 'x-match':'any'})

def callback(ch, method, properties, body):
    print "{headers}:{body}".format(headers = properties.headers,
                                    body = body)

channel.basic_consume(callback,
                      queue = queue_name,
                      no_ack=True)

try:
    channel.start_consuming()
except KeyboardInterrupt:
    print 'Bye'
finally:
    connection.close()

These two little scripts are just toys, but show how you can add key/value pairs to the headers of your rabbitMQ messages. headers_emitter.py interprets anything you type with an ‘=’ character in it as a key/value assignment to add to the header. In headers_receiver.py, you can specify what fields are to be matched in the ‘arguments’ argument to queue_bind. Just add the key ‘x-match’ with the values ‘any’ or ‘all’ to decide whether all of the keys need to match, or just any of them need to match (this part is pretty intuitive).

Apparently the complaints about headers exchanges stems from how there is no rich comparison allowed on the headers fields. So you can’t say something like ‘hams = good | bad’, or ‘id_nbr > 100’ etc, you can only match or not match. You can get some semblance of the either / or by making several bindings from the exchange to your queue. So in the ‘hams = good | bad’ case, you canchannel.queue_bind(properties = {‘hams’:’good’},…)andchannel.queue_bind(properties = {‘hams’:’bad’},…), and all messages with either good or bad in the hams key will be sent to that queue. But unless you want to make a binding for all numbers greater than some value, ‘id_nbr > 100’ is just not possible. Of course, you can catch all messages and then filter in your client based on the value of id_nbr, but depending on the volume of messages, that may or may not be practical


Currying with Java Generics

In functional languages like ML and Haskell (and even non-functional ones like Python, C#, and Ruby) we have first class functions. Functions can be passed to other functions and can be returned from functions as a result. There are a couple of aspects of this that make them useful in these languages. First, these first-class function “close over” their scope. Meaning if I write code like this in Python:

def function_factory():
    a = 3
    return lambda b: a + b

The function that function_factory returns has the value of a baked into it. This isn’t super surprising or anything, but the thing to notice is that a wasn’t defined inside of the returned function. We say it was “closed over”.

The second thing these languages with first class functions provide us with is a way to make an anonymous function. This is just a function without a name, and it’s part of the first class nature of functions. You have to be able to create a function literal, the same way you can make a “String” or a 3. Python provides the lambda keyword, which is a bit cumbersome, but functional languages like Haskell provide even more succinct syntax. The above lambda can be created in Haskell with:

\b -> a + b

If you’re looking for one killer application of first class functions, the easy example for an imperative language is callback functions. Want some library to do something when an event happens? Just pass them the function you want closed over any variables you need it to have. Everything wrapped up all nice and tidy.

“But wait”, you say, “that sounds an awful lot like an object!”. And you’d be right. State and functionality wrapped up into one nice little package sounds a lot like an object. And in a way, that’s certainly how you could implement first class functions in a language without them. Create an object that stores the state it needs and has some method that uses that state and then performs the wanted functionality. But in these modern times, where are you going to get a language with objects that doesn’t also have first class functions? Why, even JavaScript has closures and anonymous functions…

Oh that’s right: Java.

But it won’t do to just show how we can write callbacks in Java using emulated first class functions. After all, that’s something Java already does just fine, there’s no need to come up with a wacky way of doing it. No, I think today we’ll focus on forcing Java to use our emulated first class functions to do some functional programming. But first, we’ll have to take a slight detour and explain currying.

I’ll refer the historical lesson on currying to Wikipedia and focus on the essentials. Currying is a way to allow multiple arguments in a language that only allows one argument per function. The catch is that the language has to support anonymous functions. Luckily, all the languages that only support one argument per function also support anonymous functions for just this reason. Sounds weird? Don’t worry about it, all that matters is how it works in practice.

I’ll write a classy curried version of addition to demonstrate. First in Python:

def add(a):
    return lambda b: a + b

then in Haskell to show the contrast:

add = \a -> \b -> a + b

So what can we do with these seemingly overcomplicated versions of two-argument functions? Well, for one, we can partially apply them. That means if we only give add one argument, instead of an error, we get back a function that just waits around and returns the overall answer when we get around to giving it the second argument. That’s actually pretty cool. Here’s partial application at work in Python:

plus2 = add(2)

and in Haskell:

plus2 = add 2

plus2 is a function that takes a number as an argument and adds 2 to whatever that argument is. That’s it. If you want to skip partial application, and just give both arguments at once, you can. Adding 3 and 4 with our curried function looks like this:

add(3)(4) # returns 7!

and in Haskell

add 3 4 -- result is still 7!

You’ll notice Python is a bit more verbose than Haskell here, with the parenthesis and all, but as we’ll see, it doesn’t hold a candle to Java in complexity. And to be fair, Haskell is a functional language designed to support these kinds of things, Python is multi-paradigm language that has a functional aspect. (And actually, Haskell has syntactic support for currying as well that makes it even more succinct, but that’s for another day).

Anywho, after currying, the one other concept we’d like to force our poor Java compiler to deal with is higher-order functions(HOFs). HOFs are functions that take functions as arguments or return them as results. Above, we saw that currying entails returning functions as results, but we didn’t take any functions as arguments. Let’s change that now with this Python example:

def compose(f):
    def compose_inner(g):
        return lambda a: f(g(a))
    return compose_inner

And here is how we can do it in Haskell (Note: this is not how a Haskell programmer would actually do it!):

compose = \f -> \g -> \a -> f (g a)

So if we have a function f that takes a single argument, and another function g that takes a single argument and outputs some value that f is allowed to take as input, then we can plug the output of g to the input of f and get a whole new function as a result. Here’s an example in Python of using this:

def add2(a):
    return a + 2

def mult3(b):
    return b * 3

mult3_then_add2 = compose(add2)(mult3)
mult3_then_add2(4) # returns 14

and Haskell:

add2 = \a -> a + 2

mult3 = \b -> b * 3

mult3_then_add2 = compose add2 mult3
mult3_then_add2 4 -- result is still 14!

Alright, well this is neat and all, but I promised you some functional goodness in Java. The only problem is, Java doesn’t support anonymous functions (sometimes called lambdas), which is pretty central to our currying scheme!

Well, no, Java doesn’t have lambdas. But, what it does have is anonymous classes, which is just enough to shoehorn in some functional concepts, like currying! Warning: Never write Java code like this. You could never look your mother in the eye again. The central idea is that we can use anonymous local classes to implement an interface that is somewhat like an object whose only purpose is to hold a function. For good measure, we make this whole endeavor type-safe by making extensive use of Java Generics. We’re going to force the Java compiler to bend in ways it was never intended to bend!

interface Fn<A, B> {
  public B ap(final A a);
}

public class Currying {

  // This is our compose function
  public static <A,B,C>
    Fn<Fn<B,C>, // (b -> c) -> 
    Fn<Fn<A,B>, // (a -> b) -> 
    Fn<A,C>>>   // (a -> c)
    compose(){
    return new Fn<Fn<B,C>, 
      Fn<Fn<A,B>, 
      Fn<A,C>>> () {
      public Fn<Fn<A,B>, 
        Fn<A,C>> ap(final Fn<B,C> f){
        return new Fn<Fn<A,B>, 
          Fn<A,C>>() {
          public Fn<A,C> ap(final Fn<A,B> g){
            return new Fn<A,C>(){
              public C ap(final A a){
                return f.ap(g.ap(a));
              }
            };
          }
        };
      }
    };
  }

  // This is our add function
  public static Fn<Integer, Fn<Integer, Integer>> add(){
    return new Fn<Integer, Fn<Integer, Integer>>(){
      public Fn<Integer,Integer> ap(final Integer a) {
        return new Fn<Integer, Integer>() {
          public Integer ap(final Integer b){
            return a + b;
          }
        };
      }
    };
  }

  // This is our multiply function
  public static Fn<Integer, Fn<Integer, Integer>> mult(){
    return new Fn<Integer, Fn<Integer, Integer>>(){
      public Fn<Integer,Integer> ap(final Integer a) {
        return new Fn<Integer, Integer>() {
          public Integer ap(final Integer b){
            return a * b;
          }
        };
      }
    };
  }
  
  // This is the lessthan function
  public static Fn<Integer, Fn<Integer, Boolean>> lessthan(){
    return new Fn<Integer, Fn<Integer, Boolean>>(){
      public Fn<Integer, Boolean> ap(final Integer a){
        return new Fn<Integer, Boolean>(){
          public Boolean ap(final Integer b){
            return a < b;
          }
        };
      }
    };
  }

  // This is the string length function
  public static Fn<String, Integer> length(){
    return new Fn<String, Integer>(){
      public Integer ap(final String str){
        return str.length();
      }
    };
  }
  
  // This is a tricky one! It takes a curried function of two arguments as its
  // first argument (we'll call this function f), then it returns a new curried
  // function that takes the two arguments in reversed order! We use this in the
  // main function to flip the order of the lessthan function's arguments so we
  // can have the function that answers the question "is it less than two?",
  // rather than "is two less than it?"
  public static <A,B,C> 
    Fn<Fn<A,Fn<B,C>>, // (a -> b -> c) ->
    Fn<B,Fn<A,C>>>  // (b -> a -> c)
    flip(){
    return new Fn<Fn<A,Fn<B,C>>, Fn<B,Fn<A,C>>>(){
      public Fn<B, Fn<A,C>> ap(final Fn<A,Fn<B,C>> f){
        return new Fn<B, Fn<A,C>>(){
          public Fn<A,C> ap(final B b){
            return new Fn<A,C>(){
              public C ap(final A a){
                return f.ap(a).ap(b);
              }
            };
          }
        };
      }
    };
  }

  public static void main(String[] argv){
    // Basic usage of currying
    System.out.println(add().ap(3).ap(4));
    // Next, lets try (3 * 4) + 2
    // First lets create the (+2) function...
    Fn<Integer, Integer> plus2 = add().ap(2);
    // next, the times 3 function
    Fn<Integer, Integer> times3 = mult().ap(3);
    // now we compose them into a multiply by 2 and add 3 function
    Fn<Integer, Integer> times3plus2 = Currying.<Integer,Integer,Integer>
      compose().ap(plus2).ap(times3);
    // without compose
    System.out.println(plus2.ap(times3.ap(4)));
    // with compose
    System.out.println(times3plus2.ap(4));

    //Let's do something with different data types!

    // First lets create the "is this less than 7?" function. We have to use
    // flip to flip the order of arguments to lessthan so we get the right
    // meaning 
    Fn<Integer, Boolean> lessthan7 = Currying.<Integer,Integer,Boolean>
      flip().ap(lessthan()).ap(7);
    // Next, let's compose lessthan7 and length
    Fn<String,Boolean> lengthlessthan7 = Currying.<String,Integer,Boolean>
      compose().ap(lessthan7).ap(length());

    // Now let's use our cool function in a loop
    String[] strings = {"Hi","there","majestic","person"};
    for (String str : strings){
      System.out.println(lengthlessthan7.ap(str));
    }
  } 
}
  

I feel like I might go to jail for committing atrocities like this! (Special thanks to Russell Zahniser for his help with some sticky generics points on StackOverflow)



Owl from the Buddy Walk


Random Binary Trees

I had a thought today about randomly generated trees. Specifically, random binary trees where each child node has a 50% chance of either becoming a new branch node, or becoming a leaf node. My naive guess was that the exponential explosion in branches would be tempered by the high rate of leaf nodes (25%). Strangely, it looks like it always converges, so my intuition must have been at least somewhat right. The code below uses the MonadRandom Monad for handling randomness, and the Tree implementation from the containers package. 

module VariableTree where

import Random
import Control.Monad.Random
import Control.Monad
import Control.Applicative
import Data.Tree 

main :: IO ()
main = do
  sg <- getStdGen
  putStrLn . drawTree $ evalRand randTree sg

randTree :: Rand StdGen (Tree String)
randTree = do
  numBranches <- getRandomR (0, 3::Int)
  case numBranches of
    0 -> return leaf
    1 -> (leaf <^>) <$> randTree
    2 -> (<^> leaf) <$> randTree
    3 -> liftM2 (<^>) randTree randTree
    _ -> error "Shouldn't happen"
  where a <^> b = Node "" [a,b]
        leaf = Node "" []

While this code has generated some large trees, it’s always converged within a short timeframe. Wikipedia has an excellent article on Random Binary Trees here: http://en.wikipedia.org/wiki/Random_binary_tree, which explains the math, including expected depth of the tree etc.



Bella in the gutter


Composing functions in Actionscript 3

Actionscript 3 has some interesting features above and beyond javascript, and one of those is the …(rest) functionality for getting a variable number of arguments to a function as an array. Because of this functionality, we can create a flexible “compose” higher order function for creating the composition of two functions, while enabling extra arguments to be provided to both.

/** Composes two functions. When the returned function is called with arguments,
* those arguments are passed to g, and f is called on the result. Any additional
* parameters passed after g to compose get passed to f after the result of g. */
function compose(f:Function, g:Function, ... fargs):Function{
    return function(... gargs):Object{
        return f.apply(null, [g.apply(null,gargs)].concat(fargs));
    }
}

Using it is fairly straightforward (though much more cumbersome than in a functional language with currying)

function plus(A:int, B:int):int{
    return A + B;
}

function times(A:int, B:int):int{
    return A * B;
}

var multiplyAndAdd3 = compose(plus, times, 3)

Now we can use multiplyAndAdd3 easily:

multiplyAndAdd3(3,4) // => 15

This is pretty flexible, because we can provide any extra arguments we need to to both f and g, which is often necessary.


13
To Tumblr, Love PixelUnion