car and cdr have had their fifteen minutes of fame
In response to
Six Things I Dislike About Ruby (and Four I Don't), someone quipped:
while we are stamping out those silly ungrammatical C++-isms like "puts", can we also get rid of those silly lispisms of 'car' and 'cdr'?
Yeah, sister (or brother, as the case may be)!
car and
cdr are historical anachronisms. They are like secret handshakes: their only remaining value is to help a small cadre of enthusiasts bond around a shared collection of obscure trivia.

I wouldn't be suprised if Lispers have droppped these from production systems in favour of the logo-isms
first and
rest. But then again, I wouldn't be surprised if some Lispers hang onto them either. After all, if every textbook uses them as examples, they become familiar through repetition, even if their names no longer make any sense whatsoever.
The last time I checked nobody was running Lisp on
IBM 704s any more. These names really deserve a quiet retirement in a shady home where they can share war stories with
puts while they listen to
goto complain about what happened when
call/cc made him obsolete.
All that being said, car and cdr were rather prolific parents: Lisp implementations usually support a special syntactic sugar called
composition where you can make up a function with the following form: (/c[ad][ad]*r/ ...) and this is executed as if you types a series of nested cars and cdrs. For example, (caddr foo) has the same effect as (car (cdr (cdr foo))).
I really like composition. We can sort of get that with dot notation and messages in languages like Ruby. But I secretly admire the way the German language lets you
compose entirely new nouns by sticking smaller nouns together.
I think car and cdr's composition has a spiritual descendant in Ruby's metaprogramming style. For example, dynamic finders in Rails.
Person.find_all_by_username_and_password really feels like caddaddr. Uh, maybe not.
But it's nice to see that some of the good ideas from Lisp thrive in new homes.
Labels: ruby
Aptitude? We don't need no stinkin' aptitude!
Here's an academic paper:
The Camel has Two Humps. The authors analyzed programming skills and have come up with an aptitude test that correlates with the success or failure of college students in programming course.

I found the paper's central idea interesting: That the three skills of understanding state change over time (they call it sequence and assignment), recursion, and concurrency are three of the central skills of programming and are ranked in that order of scarcity.
(Revelation: instead of thinking about something as being
hard, consider it
scarce instead. It's a significant change or perspective).
I expect immediate refutations from people who resist the idea that
programming is hard or that programming skill is scarce:
- This only applies to filtering the wheat from the chaff: once students make it through their first year or so of instruction they are good enough to program anything, provided they apply themselves.
- The skills measured do not apply in the real world (wherever that may be), where understanding state change, recursion and concurrency are irrelevant to constructing software: frameworks and IDEs solve all of our problems and all you need to do is wire the pieces together.
What does this mean for you?Even if you agree with the dissenters, read the paper with an open mind. One benefit you (I am speaking
directly to you, not making a grand rhetorical gesture) can take from this is to organize your own self-development along these lines.
Consider athletics. You read a paper saying that future aptitude for sports can be measured at an early age on the basis of running speed, jumping ability, and weight lifting strength. We could drink beer and have a huge argument about their applicability to a specific sport. Maybe fencers would say that heavy bench presses are useless predictors.
But for all round athletes, those three areas are a great foundation for training. Our experience with athletics is that athletes who mix sport-specific skills training with work on speed, leaping, and strength out-perform athletes who just train skills.
So consider this: go out of your way to practice your skills the next time you are writing some code. Use iterators in places where you'd normally use a for loop. Use recursion in places where you'd normally use an iterator. And find a way to decompose operations into parallelizable components.
...
...
...
...
why are you still reading this blog post? hup! hup! get down and give me one recursive routine, then follow the instructions in this paragraph! and I mean all of you, do it at the same time!Labels: passion
The worst interview question I've never been asked
What does this code do?
perl -e '$i=$ARGV[0];$i++while("."x$i)=~/^(..+?)\1+$/;print"$i\n";' 90
(code snarfed from
GuyWithLag on
reddit.)
Labels: jobs
It's Friday! Who's having fun?
One of the things rock climbers like to say is "
the best climber is the one having the most fun."
(Don't worry, this post is not going to go on for pages trying to explain climbing culture and then trying to draw some sort of tenuous parallel to software development.)

Here's one response to the
How would you design a program to referee Monopoly? question:
What I love most about the Monopoly question is how it sucks me in. Maybe it's because I'm a gamer at heart, but my mind immediately starts racing through all the different possibilities. It's a little embarrassing to admit, but I'd love nothing more than to sit in a room with another programmer and hash this problem out. Because it's fun.
Now, I'm not going to tell you that I have some sort of crystal ball for telling you that the guy having the most fun with Monopoly has the most fun with programming as a whole. But you know what? I think it's a significant indicator. (More on why I am probably wrong below.)
One of the things I look for when recruiting is enthusiasm. This is no secret. Pick up any random book about success (or "life hacking" as people call it these days). That word pops up. Read any random biography about somone you admire. That word pops up.
I can't guarantee that a programmer who thinks programming is fun does more and does it better than a dour-faced individual who come in and just works with a Puritan "work == suffering" mentality. But look around. Don't you think employers are looking for enthusiasm?
Now does that mean Monopoly is a great question? No,
of course not. Enthusiasm can and does come through when a candidate loves to talk about a design. But enthusiasm can also come through when a candidate talks about a problem they've solved in a previous position or talks about where they want to be in five years, or does almost anything else in an interview... when the candidate is enthusiastic about their chosen profession.
Now what about this quote:
If you're interested enough to ask me in on the basis of my resume, then let's have an interview, not play stupid games or do tests.
Obviously the second person just plain doesn't enjoy this kind of problem. It's not like she said "hey, that sounds like a lot of fun, but what does it have to do with my job?" But that doesn't mean she doesn't have enthusiasm for her work. Maybe the she hates solving design problems and hates writing code in an interview, but ask her about what she accomplished in her last position and her eyes will light up. I don't know.
Interviewers are pattern matching machines. Interviewers have in their head two lists: traits they associate with success and traits they associate with failure. Ideally (IMO), these lists are compiled from personal experience.
If an interviewer has met a number of people who consider solving design problems interesting and who have been very successful designing software, the interviewer will tend to select candidates that enjoy solving design problems in interviews. This interviewer likes Jeff.
Another interviewer may have the exact opposite opinion. They may have known individuals that go into raptures over the architectural options of a design but failed to ship quality software on time. Such an interviewer would weed such candidates out. This interviewer likes the second person.
There is little consistency between interviewers, even within one company. And I'm sorry to say so, but sadly it's true: the subjective things like what you think is important about software development mean so much more than the objective things like how many years of experience doing X a candidate may claim to have.
One great danger is interviewers who (rightly or wrongly) consider themselves successful. They are their own shining example of success. How can such an interviewer avoid selecting people who are just like them? They believe they are a walking example of the kind of person that will be successful.
It's very difficult to shake this, especially when an interviewer has some length and breadth of experience. It is hard to say "
I'm not young enough to know everything" and to look at a candidate's potential with a very open mind. Even when their track record and their attitude towards your suggested line of interviewing are not what you prefer.
Given this mess, are we in trouble in our chosen profession? I don't think so. I'll tell you why I'm personally optimistic: my "circle of concern' is well-aligned with my "circle of influence." Or to put it in a triter way,
you only need one.
When looking for a job, you only need the one perfect job. It's irrelevant whether you get job offers from half of the places you apply, three quarters, or just one. What you need are the following:
- The perfect place for you is hiring;
- The perfect place for you interviews you;
- The perfect place for you makes an offer.
You only need that one interview and that one offer. All other interviews and offers are actually waste by-products of your search for the perfect job.
So when going to interviews, you can afford to be choosy. By all means, if you hate stupid games, walk on out. That company isn't your kind of place. It will be full of people who are very different than you. They all got their jobs because they think that solving that kind of problem is fun. And if you like programming but you have to ask a hiring manager if they want to see you
juggle, don't worry about getting an offer from that place.
Do you really think you'll have fun in a company where you don't have fun in the interview?
Here's the thing I've seen in my career: some companies do a better job of interviewing than others. But whether they interview well or poorly, the company's character and style are always front and centre on display.
If you walk out of an interview feeling enthusiastic about working in that place, you have a much better chance of enjoying yourself at work there than a place where you walked out feeling ambivalent.
After all, if you want to be the best programmer...
Wait for it...
You have to be the one
having the most fun.
Labels: passion
Six things I also dislike about Ruby (and four that I don't)
10 Things Elliotte Rusty Harold "Hates" About Ruby:
1. initialize
To create a new object in Ruby you invoke the new class method like so: c = Car.new("Toyota") Naturally you think the constructor would be defined in a method called new, right? Or just maybe a method called Car like in Java? But no, instead it has to be called initialize.
Right on. That's annoying.
2. Weak typing
Ahhh... I have promised not to write the same essay more than four times in any twelve-month period. Let's agree that Ruby would be
even better if there was some sort of type inference system that doesn't require type declarations everywhere.
4. Global variables
Didn’t somebody tell me Ruby was an object-oriented language?
5. puts
Do we have to copy C’s most ungrammatical, pointless method names?
Matz was clearly in
Raymond Chen mode when he put all the perlisms in the language. As an application developer, I don't use any of them. But I'll accept it on faith that there are people using Ruby as a scripting language who like them.
But I don't have to like them.
6. Zero-based arrays
C arrays began at zero to match memory addressing. In a weakly typed scripting language, there’s exactly no reason to do this. There hasn’t been for decades. Can’t we please start the arrays at 1 where God intended? Hasn’t anyone read Numerical Recipes? Aren’t we tired of fencepost errors yet?
See above. But with extra pursing of the lips. Zero-based arrays are a perfect example of a
leaky abstraction. Back in the days when programmers all wore beards and C was the new kid on the programming block, zero-based arrays were really just a funny kind of macro for performing a multiply and add on an integer that you hope is a pointer.
No really, it's true. Go ahead,
look it up. I'll wait.
Okay, I agree with Rusty and then some. I'm perfectly okay with a new language using 1-based indexing. I think I can get over the momentary unfamiliarity as I untrain my brain to stop doing this unnatural zero-based thing.
7. elsif
Sorry. “elsif” is not a word in the English language, and it shouldn’t have been one in Ruby. Would typing one extra letter have been so onerous?
Getting this wrong is almost a rite of passage when learning Ruby. Annoying. But not fatal, fortunately. At least Ruby doesn't assume els
eif is a new variable declaration. I hope.
8. $_
Global variables suck. Did I say that already? Global variables you didn’t actually create and that pop up out of nowhere suck even worse. And global variables whose names are indistinguishable from line noise suck still more. Java’s verbose, but that verbosity is in the service of legibility. Ruby’s compactness all too often serves only to obfuscate.
See above, again. I really suspect that the Perl-style stuff is of value when writing one-liners on the command line. It probably doesn't belong in an application longer than a page.
I would normally say "so don't use them," but there is a small problem with globals: at least one, $=, affects the default behaviour of a kernal function: regular expression matching. For that reason, I consider it a little dangerous.
I can live with built-in global variables that are, essentially, syntatic sugar for functions. But I'd rather that they not be syntatic sugar for method calls that change global state. No doubt you cannot have one without the other and thus I dislike them as well.
Now about the lack of object orientation. It looks like other langauges have exactly the same problem. What's with all the
singletons out there? And what happens when you call java.lang.System.setProperty(...)?
It seems that programmers like this stuff, no matter how bad it is for them. Which reminds me,
ribs for lunch today?
9. Methods are public by default
I personally don't care one way or the other about what the default access is, but I think Rusty has been perfectly cogent when
presenting his argument in favour of restricting APIs as much as possible. And he goes further to suggest that restriction should be the default.
Shrug. After all, you can choose what you want. Is there something drastically wrong with assuming that if a programmer writes a method with the default (public) visibility, that the programmer knows what she is doing and wants it that way?
Uh, oh. I think I've also written this essay before. Let's move on.
But I'll put this one down as a tie. I think Ruby would be a perfectly fine language if you had to take more care to make methods public.
By the way, is there a resonance between this perspective and with the way you can declare that certain Rails controller actions must be invoked with PUTs or via XmlHttpRequest?
10. No package access or friend functions.
There’s no access in-between public and private. All too often different classes in the same library/application/codebase need more detailed access to their other parts than the general public should have. Ruby provides no way to manage this.
(Something I find quite interesting: most of the Java programmers I have met do not use Java's 'default' visibility. But back to the subject at hand.)
There are a lot of security measures you have to put in place if your objective is to hobble programmers. Even then you may find they are motivated to work around the constraints you are attempting to impose:
Just about every developer at some point has used a library or a component developed by someone else. Just about every developer at some point has also gotten frustrated with the library to the point of being willing to find the guy who decided to make a method private and talk some sense into him. Well, most of us wouldn't go that far, but it would certainly be nice to be able to change things that make our lives miserable. It's not that libraries are written by mean people; it's just that even the brightest designers are unable to foresee all the possible ways that other developers would want to use their code.
In addition to providing various access constraints, you also have to put together security mechanisms like enforcing sealed packages. Within the Java world, researchers are also proposing
sealed classes and even sealed methods.
Now I'm not going to say that just because someone can hack around your mechanisms that the mechanisms are bad. I'm perfectly okay with a language that gives you nothing better than a glorified annotation, the equivalent of a post-it note on your ham sandwich saying "mine! don't touch!!"
It's useful to document your intentions, even if perfect enforcement is elusive. That being said, I'd like to close with the wise words of another:
Less is More. For some people, fine-grained access control is important. But adding that feature is not free.
Given the current culture of Ruby programming, I'd say that additional access control would be expensive if you go down the rabbit hole of trying to stop people using Ruby's meta-programming strengths to hack around your restrictions.
However, lightweight mechanisms for access control and managing name spaces could be useful.
Conclusion:
As I suspected before I wrote this, I agree with more than half of Rusty's observations. Isn't this always the way? Most people have far more in common with each other than not.
One of the reasons I read Rusty's work so carefully is that he has a markedly different viewpoint than my own. It's nice to read all the nice affirmation from people who seem to value the same things I value, but there is always an opportunity to learn something profound when looking at the same things from a different perspective.
Labels: ruby
Hiring a Juggler
Circus Manager: How long have you been juggling?
Candidate:
Oh, about six years.Manager: Can you handle three balls, four balls, and five balls?
Candidate:
Yes, yes, and yes. Of course, some interviewers are just looking for an excuse to talk about technical issues and will not prejudge you in any way. Speaking for myself, I would laugh if you wrote something like this out. But then again, I once worked for someone who had won the second International Obfuscated C Contest.
What I’m about to say will be blindingly obvious to the Enterprise crowd (sorry, not you over there with the Greasemonkey script that translates your web email to Klingon). The rules must be considered as carefully as the entities. Enterprise developers have known this for years: that’s why you see rules engines, table-driven designs, and visual workflow editors in many Enterprise applications.
<
In case you didn’t know this, about 1/3 of all technical interview questions worldwide are variants of “How do you fit 10 pounds of crap in a five-pound bag?” Examples: how do you reverse a string in place, how do you sort a billion numbers, how do you write a decent compiler backend for an architecture with only four frigging registers, how do you handle fair scheduling when someone just forked off 1000 copies of some Towers of Hanoi simulation, etc.
I’m exaggerating a lot, but the point is, when you select 1 out of 200 applicants, the other 199 don’t give up and go into plumbing (although I wish they would… plumbers are impossible to find). They apply again somewhere else, and contribute to some other employer’s self-delusions about how selective they are.
And then there is the issue of why would someone care if I knew how to write a file copy function, ahead of what the difference between an interface and an abstract class was. Or when would I use encapsulation? Or in my design, how would I choose between polymorphism or inheritance? Or what pattern would I recommend for dealing with a general or specific problem?
I know lots and lots of interviewers, at many companies, who’ve decided that they can fully evaluate you based on whether you can solve some particular convex optimization problem (or graph-search problem, or logic problem, or whatever their pet Elephant Question is), and they ask every candidate this question regardless of their background or experience. In fact, I’d estimate that some 10% of all technical interviewers ask the same questions, year after year, and they could care less about your experience.
Labels: jobs, popular