Skip to content

Learning

These are the stories that have been posted to the Learning category.

Ruby, Yoga for your Brain


Published to Invisible Blocks by Dan Bernier February 20, 2007 14:24

Just a fun little bit of writing, for a contest

LISP has jokingly been described as “the most intelligent way to misuse a computer”. I think that description a great compliment because it transmits the full flavour of liberation: it has assisted a number of our most gifted fellow humans in thinking previously impossible thoughts.

The analysis of the influence that programming languages have on thinking habits of its users, and the recognition that, by now, brainpower is by far our scarcest resource, they together give us a new collection of yardsticks for comparing the relative merits of various programming languages. The competent programmer is fully aware of the strictly limited size of his own skull…

- Edsger W. Dijkstra, The Humble Programmer

“Brainpower is by far our scarcest resource,” indeed. Why then, would I want mine blown? I’d rather gently stretch it. Extend it. Liberate it. Yoga for my brain, please.

In yoga, you honor your body’s suggested threshold of pain. If you can’t do the full posture, don’t hurt yourself, but try this modification, so you still benefit. When you’re ready, you can try the full posture.

Ruby is like yoga for your mind. Ruby encourages you to stretch to your limits, and come back when you’re ready for more. You can write getters and setters, and old-school for loops, and Ruby won’t complain…but it’ll gently encourage you to try attr_reader and attr_writer, and block iteration. You can write your own database access code, until you’re ready to try active record. You can write straight OO, and never leave the Kingdom of Nouns, until you’re ready to try something more functional.

Ruby lets you learn new things, in a familiar setting. With Ruby, you can honor your mind’s suggested threshold of pain. Ruby hasn’t blown my mind, and I trust it never will. A few nasties have blown my mind, and it’s never fun. It takes time to recover from abuse like that. I’d rather follow the yogis out there, and enjoy the benefits of life-long mental flexibility.

reCAPTCHA: stop spam. read books.


Published to Invisible Blocks by Dan Bernier June 21, 2007 19:05

This is really cool. reCAPTCHA is a free CAPTCHA service that asks the user to type two words. They know the first word, but the second comes from a failed OCR scan. If you get the first word right, reCAPTCHA assumes you’re human, and they store your answer to the second word…they even run it by a few other humans to raise the confidence. Not only are you authenticated, you’re transcribing. According to reCAPTCHA, “in aggregate these little puzzles consume more than 150,000 hours of work each day”.

[For the record, I don't know anyone at reCAPTCHA. I found them while reading up on CAPTCHAs for work.]

Why Functional JavaScript?


Published to Invisible Blocks by Dan Bernier January 04, 2008 22:43

I’m teaching myself functional programming (FP). I first noticed it in Ruby, even though it’s been in JavaScript all along. I’m working my way through Structure and Interpretation of Computer Programs (SICP), and The Little Schemer books, so I’m learning Scheme and Lisp too.

When studying FP, I generally use JavaScript and Scheme. My FP examples here are usually in JavaScript:

  • It’s available everywhere, and most programmers are comfortable reading it.
  • It’s closer to Scheme than Ruby is, so the examples translate better. In fact, Douglas Crockford notes: “JavaScript has much in common with Scheme. It is a dynamic language. It has a flexible datatype (arrays) that can easily simulate s-expressions. And most importantly, functions are lambdas. Because of this deep similarity, all of the functions in The Little Schemer can be written in JavaScript.”

I include Ruby or Scheme, though, if it seems appropriate.

I often use the JavaScript Shell, or its big brother, the JavaScript Development environment, because I haven’t found or built a JavaScript REPL as nice as Dr. Scheme.

Performance

Most current JavaScript implementations are slow with recursion and closures…two cornerstones of functional programming.

I don’t worry about this, because my examples are not meant to be dropped into production systems without thought and testing. I write production-ready code at work; here, I play and explore. We do use some functional JavaScript where I work, but it’s where the performance is acceptable, and the imperative alternative would be too unwieldly.

History seems to show that performance is a short-term concern, and better programming techniques are a long-term concern. It also seems that there are no inherent reasons JavaScript is slow; more performant implementations may be in our future.

Why not Haskell or Erlang?

…or OCaml, Scala, F#, Clojure? I’m getting there. SICP and The Little Schemer books are more than enough for me right now.

Counting On Your Fingers


Published to Invisible Blocks by Dan Bernier February 11, 2008 22:26

If I ever have kids, I’ll teach them to count on their fingers. In binary. “Pff, 10? I can reach 1023!”

Of course, they’ll probably get carpal tunnel from all the low-digit activity.

Why We Abstract, and What To Do When We Can’t


Published to Invisible Blocks by Dan Bernier April 05, 2008 22:34

Whenever you see yourself writing the same thing down more than once, there’s something wrong and you shouldn’t be doing it, and the reason is not because it’s a waste of time to write something down more than once. It’s because there’s some idea here, a very simple idea, which has to do with the Sigma notation…not depending upon what it is I’m adding up. And I would like to be able to always…divide the things up into as many pieces as I can, each of which I understand separately. I would like to understand the way of adding things up, independently of what it is I’m adding up.

- Gerald Sussman, SICP Lecture 2a, “Higher-order Procedures” (emphasis added)

The purpose of abstracting is not to be vague, but to create a new semantic level in which one can be absolutely precise.

- Edsger W. Dijkstra, The Humble Programmer

What Larry Wall said about Perl holds true: “When you say something in a small language, it comes out big. When you say something in a big language, it comes out small.” The same is true for English. The reason that biologist Ernst Haeckel could say “Ontogeny recapitulates phylogeny” in only three words was that he had these powerful words with highly specific meanings at his disposal. We allow inner complexity of the language because it enables us to shift the complexity away from the individual utterance.

- Hal Fulton, The Ruby Way, Introduction (emphasis added)

Programming is our thoughts, and with better ways to express them, we can spend more time thinking them, and less time expressing them.

3 + 3 + 3 + 3 + 3 + 3 is hard…hard to read (how many threes?), hard to get right (I lost count!), hard to reason about (piles of operations!). 3 x 6 is easy, once you learn multiplication. This is a good trade-off. We should look for ways to add abstractions, new semantic levels, to our programs.

If you’re doing the same thing twice, stop, and look for the common idea. Peel the idea away from the context, from the details. Grasp the idea, and then use it over and over. As a bonus, you’ll type less, re-use code, and debug less.

“But I can’t find ways to do that!”

When you look at similar bits of code, and can’t find a good way to remove the duplication, you’re hitting the limits of either your language, or your knowledge.

Programming languages put up very real walls, they force you down their paths, often by leaving out features. A language without recursion puts up a wall in front of recursive solutions; a language without first-class functions makes it tough to write higher-order functions. Language limitations are the cause of Greenspun’s Tenth Rule.

Sometimes, the language is not the problem. Sometimes you just can’t find your way through. This is why you read Refactoring, and Design Patterns, but really, this is why you learn other programming languages. Think about the right way to factor the problem.

If you can’t remove the duplication, you need to work around your language, or learn some new tricks.

Passing by reference, and dog leashes


Published to Invisible Blocks by Dan Bernier April 29, 2008 17:38

Pass-by-reference and pass-by-value are pretty confusing when you start learning to code. When I first saw them, I know I ignored the distinction (until I got tired of my code not doing what I expected). Throwing collections into the mix just makes it worse.

Today, though, we stumbled on a pretty decent analogy for passing-by-reference: a reference to an object is like a leash to a dog. Let’s take our dog Dagwood for a walk.


Dog dagwood = new Dog("Dagwood");

new Dog() creates, of course, a new Dog object. Dog dagwood creates a reference that can point to any Dog object — it’s really the leash, but we name our references for what they point to, rather than what they are: a reference, a handle, a leash. The equals sign takes the leash, and hooks it to Dagwood’s collar. Now we can take Dagwood for a walk.


dagwood.walk();

To tell Dagwood it’s time to walk, we tug on the leash. He feels the tug, and gets the message, so he starts following us. We come to a busy road, and wait for the crossing signal, but Dagwood’s oblivious, and tries to cross anyway.


dagwood.halt();

Since we’re stopped, he feels the tug of the leash again, gets the message, and stops. We’re sending messages to Dagwood through his leash. In OO terms, sending a message to an object means calling one of its methods. We’re calling methods on our Dagwood through our reference to him, through the leash.

Storing a reference in an array

In the park, we find a snack shop. We’re getting hungry, but the snack shop doesn’t let dogs inside. Luckily, there’s a chain link fence, and in our eyes, a chain link fence is nothing but a big row of places for us to attach a dog leash. We tie a spare leash to the end of the fence, and attach it to Dagwood’s collar.


Dog[] fence = new Dog[10]; // only room for 10 dogs
fence[0] = dagwood;

What’s happening here in OO terms is that our reference to Dagwood, our leash, is copied into the zeroth slot on the fence. It’s not our leash, but it’s one just like it. So now there are two leashes on Dagwood: one in our hand, and one on the fence. We’ll take our leash off Dagwood, since we can’t very well hold it while we’re in the store.


dagwood = null;

Don’t worry, he’s fine…he’s still tied to the fence, by that other leash. Let’s go buy cashews.

When we come out of the store, we want to re-attach our leash to Dagwood.


dagwood = fence[0];

Now let’s untie him from the fence, and head over to the lake.


fence[0] = null;

Passing by reference

Passing references to methods works in much the same way. Dagwood got kind of stinky, swimming in the lake, so let’s bring him to the groomer for a bath.


DogGroomer.shampoo(dagwood);

When you pass a reference to a method, your reference is copied into that method. Again, it’s like a new leash, one just like ours, springs into the groomer’s hand — now Dagwood’s attached to us, and the groomer. He gets fidgety when he’s getting bathed, so it’s just as well.

From the groomer’s perspective, it might look like this:


void shampoo(Dog doggie) {
    wet(doggie);
    apply(shampoo, doggie);
    rinse(doggie);
    towelDry(doggie);
}

The groomer doesn’t care what Dagwood’s name is, she just keeps calling him “doggie.” That’s ok, she must see a lot of dogs during the day…names aren’t that important to her. The interesting thing is, even though it’s the groomer who’s shampooing our dog, since we still have a leash on him, we can observe him getting cleaner.

When she’s done, the procedure ends, the method returns, and her leash to Dagwood disappears. Which is fine, because he’s stopped fidgeting, now that he’s dry.

Garbage collection

We head back home through the park. Dagwood’s itching to run around, but we’re tired, so we just unleash him. Hopefully we can find him before it gets dark…


dagwood = null;

Unfortunately, the dog catcher spots him running around without a leash, which is illegal in these parts — a stray dog will hang around forever, eating up resources. The dog catcher carries off our poor Dagwood, and destroys him. We take it in stride, and try to keep the whole circle of life allocation-deallocation in mind.

So…

So that’s how references work. It’s why code like this (C#) will ensure the balloon bouquet has at least one balloon that says “Happy Birthday!”:


List<Balloon> balloons = GetBalloons();
Balloon printed = balloons.Find(Balloon.IsPrinted);
if (printed == null) {
   printed = new Balloon();
   printed.PrintMessage("Happy Birthday!");
   balloons.Add(printed);
}
return balloons;

Heading to the Int’l Lisp Conf, 2009


Published to Invisible Blocks by Dan Bernier February 25, 2009 01:30

My next step on the road to lisp is at the International Lisp Conference in Cambridge, MA, this March.

A lot of people are surprised to hear I’m interested in Lisp, but I’ve been studying scheme informally for about 3 years, reading SICP, and finishing The Little Schemer last year. I’ve been interested in clojure for about 18 months, especially after seeing Rich Hickey talk about it last March.  Now I’m studying it in earnest with Stu Halloway’s Programming Clojure.

I don’t use lisps of any sort at work, so it’s not a “practical” language to study like, say, C# is.  But that’s short-term thinking.  Learning lisp is plenty practical, if you’re looking longer-term — even if it’s only three years out.  Learning lisp teaches you about some of the core issues of programming.

I like learning lisp because it’s a window into the workings of programming languages, being so close to the AST.  I want to learn more about meta-programming with macros, hygienic or not.

And for the record, the functional techniques in The Little Schemer have improved my Ruby, JavaScript, and C# in some really solid ways. Functional programming is making its way to the rest of the programming world, and lisp does functional programming.

If you’ll be at the conference, I’d love to hear from you.


Book Review: Pragmatic Thinking and Learning


Published to Invisible Blocks by Dan Bernier April 15, 2009 20:48

I was planning on reading Andy Hunt’s Pragmatic Thinking and Learning: Refactor Your Wetware for a while, but kept putting it off, thinking it wasn’t really central to what I’m interested in, what I’m doing.  I was wrong.

People have different skill levels, from novice to expert.  One sign of expertise is the ability to intuit solutions not available through linear thinking.  Intuition happens on the right side of the brain, so we need to use the right side more effectively.  Rather than “left brain” and “right brain”, he calls them “L-mode” and “R-mode”, for “linear” and “rich”, to emphasize that it’s not literally two halves of your brain working differently, but two different modes of thinking.  Most of the book is about using R-mode more, and using L-mode appropriately, to fact-check your R-mode.

It draws on psychology, neurobiology, cognition studies, managing, teaching, the arts, product design, and math.  The bibliography is ten pages long, and I’ve got a bunch of them highlighted for my next evening at the bookstore.

The most valuable changes I’ve made since finishing the book are:

- Be ready when your R-mode strikes. Since “querying” the R-mode can take a long time, we run it asynchronously, and we never know when the results will come in.  (This explains the “ah-ha!” moments in the shower, on the drive home, and when you’re falling asleep.)  So keep a notebook handy for writing things down.  I’m writing in a notebook almost daily (I’ve joined the cult of moleskine), writing down ideas as they come up.  It’s also a tider home for all the scraps of paper that have lived in my wallet for years, ideas scrawled and smudged into them.  And I’m on my 4th or 5th pocket mod.

- Maintain your ‘exo-cortex,’ your external memory. I wrote a mini-wiki engine with Sinatra, and so far, I’ve used it for everything from clojure, to saving quotes, to robot rights.  I wrote it for practice, but it’s nice to have a searchable, non-linear notebook.

The book mentions Gerald Weinberg’s fieldstone method of writing: to build a stone wall, you gradually gather stones from the field as you clear it, and pile them up.  When you have enough, build your wall.  Both the wiki and the notebook serve this purpose.

- Map out your thinking, and doodle. Drawing pictures engages your R-mode, making it more active, helping you make connections, and understand more clearly.  Besides, it’s fun. This is my 3rd time learning emacs, and it’s finally sticking — I think it’s mostly because I drew up a cheat-sheet, pictorially explaining each command’s effect.  I also map out my learning and career goals this way.

emacs cheat sheet

One of my favorite parts is, after you’ve mapped something out, and the drawing looks like a pile of yarn, re-draw it on a clean sheet, fixing up all the awkward placements and messy bits.  The benefit of this second version is in its creation — by considering how to re-organize it, you’re thinking more about the problem, in ways you might not have before.  This works for note-taking, too.

- Take advantage of your brain’s plasticity. You can change how your brain works by believing it works differently: make it smarter, more creative, cheerier.  This is a pretty incredible claim, but he cites two books I’d like to check out.  It sounds impossible, but I’ve seen it work on me, to some extent.  My biggest problem is continuing to believe it works.

Some things I have yet to try:

- Take a walk.  A meditative walk, like around a labyrinth.

- Write morning pages: for three weeks, as soon as you wake, write down three pages of text.  It doesn’t have to be anything specific.  The idea is, right after we wake, our R-mode is more active, so the gems will be more accessible, and they’ll pop out onto the page.  I’m more curious to see what I come up with.

- I have to get better at setting SMART goals: specific, measurable, achievable, relevant, and time-boxed.  I’ve never been much for this kind of discipline — I made a few, but didn’t stick to them, and haven’t gotten into the habit yet.  But like the book says, change is hard:

Change is always harder than it looks — that’s a physical reality, not just an aphorism. An old, ingrained habit makes the equivalent of a neural highway in your brain. These old habits don’t go away. You can make new neural highways alongside, going a different route and making short-cuts, but the old highways remain. They are always there for you to revert to—to fall back on. Practice may not make perfect, but it sure makes permanent.