raganwald
(This is a snapshot of my old weblog. New posts and selected republished essays can be found at raganwald.com.)

Friday, March 02, 2007
  Programmers are Sages


Raymond Smullyan does much more than write about Infinity, Combinatory Logic, Recursion Theory, and Gödel’s Incompleteness Theorems. And he does much more than teach these concepts delightfully by turning them into stories and puzzles to solve. He also teaches philosophy by way of insightful essays and anecdotes.

I’m going to paraphrase one of his down-home insights. This particular little story has helped me through many dark periods in my life. Raymond was talking about Taoism, and he explained that his two pet dogs embrace the Tao. I think he described them as “Sages.”



Raymond explained that like many dogs, they preferred rich chunks of meat and gravy to dried kibble. And like many people, Raymond had tried making the kibble more palatable by mixing in some meat with the dry dog food and pouring gravy over the whole thing.

The dogs, of course, would carefully pick the meat out and lick up all the gravy, leaving nothing but the dried kibble behind. But did they resent this? Did they howl and whine about the kibble ruining the meat? Of course not! They would wag their tails and frisk about, joyous in finding all that good meat and tasty gravy in their bowls. It was like the kibble existed in some alternate dimension that the dogs cold not perceive.

Aaah… Dogs truly are Sages.

Kibble

Every time someone writes about interviewing and hiring, they are writing about judging people. That’s really deep and meaningful to us as people: being picked or not picked, picking or not picking is pretty much all of our social structure. So when you discuss it, you are reaching deep into people’s souls.

I know this, because it hurts me when I interview for a job and the response is “thanks, but no thanks.” It hurts when people say, “you don’t have the right kind of degree” or when they tell me that I forgot to use GROUP BY when writing a SQL query to sum the sales of automobiles by brand, or that they don’t think a Black engineer would go over well with Southern clients (all true stories).

There’s almost no way1 to write about picking people without getting some heartfelt “thank you for recognizing my worth” responses. And some invective from people who feel you’re saying that you would pass them over. The fact is, there’s some unpleasant dried dog food in every post about interviews and hiring. Even if you pick something you think is obvious and unassailable.

Delicious chunks of meat!

Of course, some programmers just eat the delicious meat and ignore the kibble. Look! A tasty programming problem!

I’m one of these. What was my first thought when I saw a certain notorious screening question? I thought, “Hmmm… Instead of a loop with three conditions, this could be expressed as the composition of three functions, let’s try writing it that way.”2 A tasty chunk of thinking about programming meat!

You know, it never even occurred to me to wonder whether I fail the test and be rejected and be cast out of the herd.3 I mean, honestly, was the original author interviewing me for real? No! So why eat the dry dog food? Honestly??

But in even the most trivial problem there’s some meaty thinking to enjoy. Composing functions. Yummy.

Covered in Gravy

Based on responses, the overwhelming majority of readers of this blog are Sages.

Most people respond to a mixture of dried kibble and meaty chunks friskily, wagging their tails and leaping about with programming solutions and discussion about how best to solve the problem. Yummy stuff indeed.

Some people might wonder if we’re playing Stairway to Heaven. Of course if you walk into a music shop and yell “nobody can play Portrait of Tracy,” everyone with a bass is going to start hitting harmonics.

That isn’t because we’re insecure and need to prove ourselves. It’s because we love playing and you just named a tune.

What can I say, I’m delighted with how many people love to play music. And I’m delighted with how many programmers love to program. For its own sake.

So thank you all for reminding me that life is all about the tasty chunks and delicious gravy.

I really appreciate it. Thank you. Especial thanks to Tom and Eric for constantly telling us all about the tender and sublime taste of Haskell. It’ll be on the menu one of these days.

Wonderful, the universe is covered in gravy!



  1. Well, there is one way to write about picking people without offending anyone: if you really say nothing at all. For example: At NiceCo, we conduct our interviews as conversations. We discuss each candidate’s experience and accomplishments, we canvas their views and share our objectives with them, working collaboratively to identify the most appropriate contribution they can make to the team’s success.

    Now see, you can’t criticize that because it didn’t actually say anything. Maybe it’s a wonderful process involving nice people, or maybe what really happens is that they decide whether to hire you in the first thirty seconds based on some triviality like whether you have body odour. If you don’t say anything, there’s no kibble and no meat.

    It’s an empty dish.

    This does not mean it’s a bad process or a bad statement. But the process isn’t reproducible from the statement alone. That’s the exact sense in which I say that the statement is empty.

  2. This separates the concern of how to generate the list from the concern of how to transform the list. Someone posted a variation with different conditions: you can simply generate a new transformation function by composing two of the exiting functions with two new functions, more or less. And if someone asked for the same thing in Ancient Rome, you could write a different generator that generated the numbers from I to C.

  3. Don’t bother writing to say that my confidence is the reason why: I recall failing a technical interview when I brain cramped and was unable to write a program to print the first 100 prime numbers. I’m not that smart.

Labels:

 

Comments on “Programmers are Sages:
"I recall failing a technical interview when I brain cramped and was unable to write a program to print the first 100 prime numbers."

I assume you mean elegantly. Aren't there tricks in determining if a number is prime? I don't know those tricks, so I would end up writing something like this:

int p=1,count=0;
for (;count<100;p++)
{
int i;
for (i=2;i<p;i++) if (p%i==0) break;
if (i<p) continue;
printf("%d\n",p);
count++;
}

It's not the fastest thing in the world, and it is literally the first time I've even attempted to write a program that outputs primes.

I can imagine I could panic and fail if I had instead focused on a clever or elegant way of writing this.

Even now it occurs to me that I could test i < sqrt(p) instead.
 
This will print the first 100 primes. It also prints a few other numbers.

for(int i=2;;i++) printf("%d ", i);
 
I assume you mean elegantly.

If you combine an urge to provide an elegant solution with failing to take the basic precaution of writing something that "just works" and then improving on it in the remaining time available...

In other words, the test failure was a true failure, in that it identified several mistakes that are actual weaknesses in a programmer.

Today I would:

1. Ask what they are looking for in a solution, up to and including asking whether an elegant solution is "worth more," or whether they just want to satisfy themselves that I can write working code.

2. Get something, anything, working.

3. Polish.
 
def first_n_primes(start, n)
..primes = []
..while primes.length < n
....primes << start if is_prime?(start)
....start += 1
..end
..primes
end

# naive, not seive
def is_prime?(i)
..2.upto(i / 2) { |j|
....return false if (i % j) == 0
..}
..true
end

puts first_n_primes(1, 100).join("\n")
 
Polished:

class Numeric
..# naive, not seive
..def prime?
....2.upto(self / 2) { |i| return false if (self % i) == 0 }
....true
..end
end

def first_n_primes(n, start = 1)
..primes = []
..while primes.length < n
....primes << start if start.prime?
....start += 1
..end
..primes
end

puts first_n_primes(100).join("\n")
 
Doing FizzBuzz with higher-order functions is like playing "Mary Had A Little Lamb" in the style of a Bach fugue. Same with doing it in Roman numerals, just because you can. (It's not "Stairway." It's not even close.)

Picking the gravy out of the kibble I like. Hearing inspired fugues against the backdrop of a thousand kazoos playing a stanza apiece? That makes me grumpy.
 
Giles:

You are conflating the pleasure of listening to the music with the pleasure of playing the music.

I'm not saying that I pored over every solution with delight. Rather, I am delighted that a bunch of people were excited enough to compose solutions.

And honesty, if there were three or four hundred of them, as there were at Jeff's excellent coding horror blog, I might have had trouble wading through all of the comments.

I'm not saying I'm delighted that hundreds of J.S. Bach's read my blog. I'm not saying that the people posting were playing kazoos, either.

I'm just saying that it pleases me that people find this fun.
 
The Haskell version is really elegant:

primes (n:ns) = n : primes (filter (\v -> v `mod` n /= 0) ns)

This is a simple Sieve of Eratosthenes algorithm. To get the prime numbers:

take 100 (primes [2..])

This starts the sieve going on the numbers [2, 3, 4, ...] and picks off the first 100 numbers from the result.

Cool, isn't it?
 
I might be picking meat out of the kibble, but I still need to get a life. Nevertheless;

def prime?(n)
n.times do |i|
return false if(((i > 1) && (i < n)) && ((n % i) == 0))
end
return true
end

def print_prime(quantity)
count = 0
primes = []
while(primes.length < quantity)
count = count + 1
primes.push count if prime?(count)
end
primes.each {|p| puts p}
end

print_prime(100)
 
"What can I say, I’m delighted with how many people love to play music. And I’m delighted with how many programmers love to program. For its own sake."

Word of advise. The reward center, the part of your brain that makes you feel good after you solved a technical puzzle, is a blessing and a curse. It gets you to play around, experiment and practice your skills. That will make you a better developer.

But if you don't keep it under control, it will take over and direct you to do what's rewarding to your brain, not to your project. And it's more rewarding to optimize challanging code, even if it's not a critical section. To write creative solutions, for code that's best left dumb. To solve a problem in a new and interesting way, instead of fixing someone else's code. To find excuses to write code, instead of testing and documenting.
 
Assaf:

I first wrote something long and heartfelt in response, but you know what? That was way too serious!

It's just a few people dancing and having fun. Why not smile and wave, even if you don't feel like joining in?

If I can't dance I don't want to be in your revolution.

Emma Goldman (1869-1940),
 
I'm no sage, but the Haskell version posted above just blew me away. I did not understand how it could work till I ran it, and re-read the Sieve algorithm. But I still do not completely understand(I am new to Haskell, trying to not incur brain-damage). Thank you Peter Scott for posting that! That's enough meat to munch on today.
 
Peter Scott's piece of Haskell, while quite elegant, is not the Sieve of Eratosthenes.

You could write that piece of code if I were interviewing you, and I'd be happy... but you'd better not assert that it's the Sieve of Eratosthenes. ;)
 




<< Home
Reg Braithwaite


Recent Writing
Homoiconic Technical Writing / raganwald.posterous.com

Books
What I‘ve Learned From Failure / Kestrels, Quirky Birds, and Hopeless Egocentricity

Share
rewrite_rails / andand / unfold.rb / string_to_proc.rb / dsl_and_let.rb / comprehension.rb / lazy_lists.rb

Beauty
IS-STRICTLY-EQUIVALENT-TO-A / Spaghetti-Western Coding / Golf is a good program spoiled / Programming conventions as signals / Not all functions should be object methods

The Not So Big Software Design / Writing programs for people to read / Why Why Functional Programming Matters Matters / But Y would I want to do a thing like this?

Work
The single most important thing you must do to improve your programming career / The Naïve Approach to Hiring People / No Disrespect / Take control of your interview / Three tips for getting a job through a recruiter / My favourite interview question

Management
Exception Handling in Software Development / What if powerful languages and idioms only work for small teams? / Bricks / Which theory fits the evidence? / Still failing, still learning / What I’ve learned from failure

Notation
The unary ampersand in Ruby / (1..100).inject(&:+) / The challenge of teaching yourself a programming language / The significance of the meta-circular interpreter / Block-Structured Javascript / Haskell, Ruby and Infinity / Closures and Higher-Order Functions

Opinion
Why Apple is more expensive than Amazon / Why we are the biggest obstacles to our own growth / Is software the documentation of business process mistakes? / We have lost control of the apparatus / What I’ve Learned From Sales I, II, III

Whimsey
The Narcissism of Small Code Differences / Billy Martin’s Technique for Managing his Manager / Three stories about The Tao / Programming Language Stories / Why You Need a Degree to Work For BigCo

History
06/04 / 07/04 / 08/04 / 09/04 / 10/04 / 11/04 / 12/04 / 01/05 / 02/05 / 03/05 / 04/05 / 06/05 / 07/05 / 08/05 / 09/05 / 10/05 / 11/05 / 01/06 / 02/06 / 03/06 / 04/06 / 05/06 / 06/06 / 07/06 / 08/06 / 09/06 / 10/06 / 11/06 / 12/06 / 01/07 / 02/07 / 03/07 / 04/07 / 05/07 / 06/07 / 07/07 / 08/07 / 09/07 / 10/07 / 11/07 / 12/07 / 01/08 / 02/08 / 03/08 / 04/08 / 05/08 / 06/08 / 07/08 /