I've always wanted to get into Cocoa programming. I like the look and feel of a good Cocoa app, and folks I respect tell me that it's a wonderful environment. But, to be honest, I've always been somewhat put off by the way that Cocoa programming is tightly coupled to Xcode and Interface Builder. I've never really liked IDEs, simply because in the past they've felt like they're in my way.
So then Daniel Steinberg twisted my arm and got me to edit his new book, which introduces Cocoa programming to people who are already programmers in some other OO language. Trying to be a good editor, I gritted my teeth are fired up Xcode and started to follow along with his tutorial chapters. And, somewhat to my surprise, I had a working (if minimal) web browser up and running in a few minutes. I added buttons, and later a progress bar, and it all just worked. So now I've changed my opinion. Cocoa is a really well thought out framework, but the tight integration with Xcode and IB make it very, very sweet. I'm looking for an excuse to spend some serious time writing a decent-sized app with it.
In the meantime, if you're like me, and want to dip a toe into Cocoa development, I'd recommend his Cocoa Programming: A Quick-Start Guide for Developers. If you're more of a hands-on learner, the good news is that Daniel and Bill Dudney will also be running a great 3-day Cocoa Studio at the end of October. It's in the amazing Inverness facility in Denver (which I'm at right now, teaching a Rails Studio with Chad).
Currying is the ability to take a function that accepts n parameters and generate from it one of more functions with some parameter values already filled in. In RUby 1.9, you create a curry-able proc by calling the curry method on it. If you subsequently call this curried proc with fewer parameters than it expects, it will not execute. Instead, it returns a new proc with those parameters already bound.
Let's look at a trivial example. Here's a proc that simply adds two values:
plus = lambda {|a,b| a + b}
puts plus[1,2]
I'm using the [ ] syntax to invoke the proc with arguments, in this case 1 and 2. The code will print 3.
Now let's have some fun.
curried_plus = plus.curry
# create two procs based on plus, but with the first parameter
# already set to a value
plus_two = curried_plus[2]
plus_ten = curried_plus[10]
puts plus_two[3]
puts plus_ten[3]
On line 1, I create a curried version of the plus proc. I then call it twice, but both times I only pass it one parameter. This means it cannot execute the body. Instead, each time it returns a new proc which is like the original, but which has the first parameter preset to either 2 or 10. In the last two lines, I call these two new procs, supplying the missing parameter. This means they can execute normally, and the code outputs 5 and 13.
You can have a lot of fun with currying, but that's not why we're here today.
Over the weekend, Matz added a new method to the Proc class. You can now use Proc#=== as an alias for Proc.call. So, why on earth would you want to do that? Well, remember that === is used to match terms in a case statement. Over of the AimRed blog, they noted that this feature could be used to make the matching in case statements actually execute code. In their example, they manually added the === method to class Proc
class Proc
def ===( *parameters )
self.call( *parameters )
end
end
Then you can write something like
sunday = lambda{ |time| time.wday == 0 }
monday = lambda{ |time| time.wday == 1 }
# and so on...
case Time.now
when sunday
puts "Day of rest"
when monday
puts "work"
# ...
end
See how that works? As Ruby executes the case statement, it looks at each of the parameters of the when clauses in turn. For each, it invokes its === method, passing that method the original case discriminator (Time.now in this example). But with the new === method in class Proc, this will now execute the proc, passing it Time.now as a parameter.
While updating the PickAxe, I noticed that Matz liked this so much that it is now part of 1.9. And it means we can combine this trick with currying to write some fun code:
is_weekday = lambda {|day_of_week, time| time.wday == day_of_week}.curry
sunday = is_weekday[0]
monday = is_weekday[1]
tuesday = is_weekday[2]
wednesday = is_weekday[3]
thursday = is_weekday[4]
friday = is_weekday[5]
saturday = is_weekday[6]
case Time.now
when sunday
puts "Day of rest"
when monday, tuesday, wednesday, thursday, friday
puts "Work"
when saturday
puts "chores"
end
Is this incredibly efficient? Not really :) But it opens up quite an interesting set of possibilities.
Programming is a creative activity. And, like most creative people, programmers occasionally succumb to writer's block. You'll sit there, spinning your wheels, trying random stuff, and knowing that you're not really getting anywhere.
I've been experiencing this feeling now in a different sphere. I've been taking music lessons for some months now, and recently blogged my first composition (or, at least, the first I was prepared to let out into the wild).
Flush with success, I launched into my next piece. I envisaged it being a set of three pieces set in a run-down dance studio. (Don't ask why, it just seemed to fit the mood.) The first section was 5/4 and fairly upbeat. The second section was 3/4, and was deliberately clumsy (I saw partners who couldn't quite get it together), and the last section was 4/4, and knitted things together.
At least that was the vision. I spent weeks on this thing. I had some great themes. But I just couldn't see my way through to the end. Every lesson I'd come in with some changes, and by the end I'd argue myself out of them.
Now I've been coaching developers for a while now. And I know what to suggest when some programmer reaches this kind of state. But for some reason it didn't occur to me to apply the same advice to myself. It took my teacher to say “stop working on this for a while, and go do something fun.” He gave me an assignment. Choose a simple melody and arrange it. Come back with it finished the next week.
In the end, it was great fun. It only took an hour or so, and it totally cleared my mind. I came back triumphantly the next week with something actually finished, and it felt good.
And then, I found I could get back to the more complex piece. In fact, the first time I sat down to it, I was having so much fun I went of in a totally different direction, and I'm now trying something kind of wild. More on that later...
So, if you're finding yourself blocked—if you're going around in circles, or if everything you do you end up throwing away—STOP. Go do something else. Something simple. Something fun. Clear your mind, and remember what it is to enjoy your work.
(And, if you're interested, the fluff piece that cleared my logjam is an arrangement of Shenandoah: transcript and below, played by Mike Springer.)
(Update: Chris Morris took this piece of fluff and turned it into something amazing. I think there are about three notes of mine in there somewhere...)