Collections are the new string manipulation
Wednesday, December 19, 2012 at 10:51AM About 14 years ago (when I first started programming in C and Visual Basic), I felt like most of the work I was doing was string manipulation and memory management. These days I use much higher level tools like Ruby, Coffeescript, SQL, and R. In 2012, most of us spent very little of our time on string manipulation and memory management.
So where does a modern programmer's time go? Well, I bet we build more things in a given time window then we used to. We may also spend more time thinking about what we're going to build. We write tests that verify that stuff works (hopefully).
But what about our actual coding time? A lot of my coding time goes to manipulating collections. And that's great! Its great in part because our tools are great at working with collections. We have stuff like this in almost every modern language:
#ruby
ponies.map(&:color).join(", ")
#R
paste(ponies$color, collapse=", ")
#SQL (well, MySQL anyway)
SELECT GROUP_CONCAT(color) FROM ponies;
We don't loop over each pony and use conditional logic to build a string using their color property. We map the collection of ponies to a new collection that contains their colors. Then, we right fold that collection into a string. (NOTE: #join may or may not be implemented as a right fold, but it does the same thing conceptually)
How f-ing awesome is that? It's unlikely that you're going to get that code wrong. It's unlikely that the next person who works in the codebase is going to break that code. It's unlikely that it's going to be inefficient. In the bad old days that would have been
//Java
String result = "";
int i = 0;
for(Pony pony : ponies){
result += pony.getColor();
if(i < ponies.size() - 1){
result += ", ";
}
i++;
}
Right off the bat we see an easy possibility to create an off-by-one error. I think everyone agrees that the code examples above are better than the Java version.
This is only the tip of the iceberg really though. Working with Data Frames in R takes this concept to a whole other level. I think it's clear that as functional programming concepts make their way into our main languages, we're going to be doing a lot more of this. And it's a very good thing!
Refactoring Rails With sed -- Class Method Renaming
Monday, March 28, 2011 at 06:12PM Something that you'll ocassionally hear from new Rails developers (especially if they are coming from an IDE-centric world) is that they miss having refactoring tools. Well, it's never going to be as easy to automate refactoring in a dynamic language as it is in a static language. All of that compile time info in static languages is very useful for refactoring and in Ruby we just don't have that to work from. That said, as terminal dwellers there is a lot of power that we can gain from leveraging UNIX tools. Here is one way in which I have learned to take advantage of BASH and sed, to rename a class method in a rails app. Here I am renaming a class method called 'omc_data_service' to 'service'. I'm all about pulling this stuff off as one liners right in the terminal. It seems a bit crazy at first, but after you do it a few times you can come up with something like this in about 20 seconds.
It's pretty straight forward really
This is just saying "Loop over all the Ruby files starting from the current dir and recursing"
Print the file name
This is the real logic. Sed is a line based editor that we are using here to make a regex substitution.
The "-i" flag means "Do the subsititution inline, rather than to stdout".
The "-e" flag means "the following string is a sed expression".
The first regex "/[:.]omc_data_service/" is saying "Only apply this to lines that contain the method name". This is only needed because we don't want sed to rewrite lines when there is no change made. Without the first regex the result would be the same, except every file would have it's 'last modified' date changed.
Anyway, we are looking for either a starting '.' for calling and declaring the class method, or a starting ':' for when we are passing the method name as a symbol to Flexmock. The '\([:.]\)' means, "Remember if it started with a '.' or ':'". The "\1" says "Since you rememebered if it had a '.' or ':', put that here". Finally the "/g" takes care of all occurances on a line rather than just the first.
Hope this was helpful.
iOS development with Vim
Tuesday, January 25, 2011 at 07:12PM I've seen a few amazing developers (including http://eraserhead.net/) who feel that they work more productively in standard UNIX text editors than they do in XCode. Despite my recent flirtation with Emacs :) , I'm fairly effiecent in using Vim for non Objective-C coding work, but I've never really considered using it for iOS. It all changed however after seeing Gary Bernhardt's talk at CodeMash.
Gary showed some great examples of how he has streamlined his workflow and made himself into a lightning fast TDD monster. I asked what he would do if he was an iOS developer and his response was that he wouldn't invest the time to create this workflow for iOS unless he had enough work lined up to make it worth it. Well, he may not spent much time with Objective-C, but its likely I'll put in a couple thousand hours with it this year. With that in mind, I have decided that I'll be spending the remainder of the time before there is an official update to XCode in Vim.
The main thing that I was jealous of in Gary's presentation was the Red/Green bar at the bottom (indicating passing or failing tests) and the speed with which he could run them. So, thats the first thing I stole :) NOTE: I also modifed the ruby section of code below from something Navel-Labs shared with me.
End result is that by typing ",t" I can run my current test bundle and see output like below. It doesn't happen quite as fast as Gary's examples, but it is much faster than working with the Build Result window in XCode.
Here's how I'm doing it:
When I start working on a new test I map the key right in my vim session
This is in my .vimrc
The Objective-C Koans
Thursday, December 23, 2010 at 07:37PM Part of what makes unit testing so engrained into the Ruby culture is that many people begin learning the language through TDD. The Ruby Koans of course deserve much of the credit for that. I hope to bring this same mentality to Objective-C. Today I began working on a port of the Koans using the testing framework Kiwi. As a tease, checkout my reworking of about_asserts.rb. Obviously this example teaches you more about the testing framework than Obj-C. I hope that the Objective-C community will want to pitch in and make this a reality. The project is available on Github.
[Your Name Here]
The project is now up on Github. All are welcome to contribute.
https://github.com/joecannatti/Objective-C-Koans
Beginner's LISP — PART 2
Wednesday, August 18, 2010 at 07:45PM "Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers"
My goal is to show a simple yet somewhat clever solution. My first thought on how to accomplish this is to just test all 3 possible cases. This seems like a rather bland approach however and from what I understand, LISP is supposed to be exciting :). As a result, I'm going to go with a less efficient but more readable implementation. I'm going to add the squares of all three numbers and then subtract the square of the smallest.
(define (sicp1.3 a b c)
(- (+ (* a a) (* b b) (* c c))
(* (min a b c)(min a b c))))
Here I define a procedure called "sicp1.3" that takes 3 arguments. I then add the squares the those 3 args and subtract the square of the smallest. If you are not able to see how this code does what I described, then checkout my earlier post.
Now, I already admitted that this is not an optimally efficient algorithm, so I better make this at least a little easier on the eyes. First by pulling out the "square of the minimum value" part to it's own procedure. That gives us:
(define (sqmin a b c)
(* (min a b c)(min a b c)))
(define (sicp1.3 a b c)
(- (+ (* a a) (* b b) (* c c))
(sqmin a b c)))
and finally, I'd say that the "sum of squares" part should really be it's own procedure as well
(define (sqmin a b c)
(* (min a b c)(min a b c)))
(define (sumsq a b c)
(+ (* a a) (* b b) (* c c)))
(define (sicp1.3 a b c)
(- (sumsq a b c)
(sqmin a b c)))
So thats what I've got. Upon looking this up on Stackoverflow I found a similar solution to the one given here, plus a number of much more sophisticated examples. Enjoy!
General