Ruby — Inject
I’ve done a little bit of programming (as a hobby) in a few languages (C, C++, Java and Scheme) and Ruby stands out to me as both “easy” and “fun”. One of Ruby’s strongest points is it’s readability. Phrases like
3.times{ puts "Good Morning" } unless sun.down? are often touted in introductory lessons. The Java equivalent is
if (! sun.down) {
for (int c=0; c<3; c++) {
System.out.println( "Good Morning" );
}
}I really gave Java a break here because in order to run that program I had to wrap it in a class and use the classic Java idiom “public static void main()”. Idioms like Java’s and other’s “for (int c=0; c<num; c++){}” get annoying after you get a good taste of Ruby. Once Ruby starts catching on in your mind you’ll make all kinds of excuses for it like when your hot, new girlfriend drops an F-bomb in front of your mother.
Ruby’s F-bomb in this post is “inject”. I just learned about inject today and despite being confusing and unreadable I still find it charming. I recently wrote a quick script to search for people’s names in text files. If this script finds someone in a text file it puts the name of the text file next to the person’s name. Part of this script builds a String (like: “John Johnson, list_of_users1.txt, list_of_users2.txt”) before putting it in a csv file.
def check_presence_of_user( user )
s = user.to_s
files_to_check.each do |file|
s << (',' + file.name) if file.has_user(user)
end
return s
endThis code takes each users and adds them to a String. Then we run through each check file and, if the user is in a file, we add that filename to the string. Finally we return the string. Refactoring this simple piece of code with inject is fun.
def check_presence_of_user( user )
files_to_check.inject(user.to_s) do |s, file|
s << (',' + file.name) if file.has_user(user)
end
endBasically we just eliminated “setting up” the string, which is where I find myself using inject most often; when building strings. This code seems readable to me in a Why The Lucky Stiff sort of way where you imaging a syringe that starts with “user.to_s” in it and keeps sucking up the output of the block and squirting it back in for another round. However I’ve also seen some inject snippets that that make my head explode.