Categories
Uncategorized

Enumerating Enumerable: Enumerable#any?

Welcome to the second installment of Enumerating Enumerable, my project to do a better job of documenting Ruby’s Enumerable module than RubyDoc.org. This installment will cover Enumerable#any?, which I like to think of as Enumerable.all?‘s more easy-going cousin (I covered Enumerable.all? in the previous installment).

Enumerable#any? Quick Summary

Graphic representing Ruby\'s Enumerable#any? method

In the simplest possible terms Do any of the items in the collection meet the given criteria?
Ruby version 1.8 and 1.9
Expects A block containing the criteria. This block is optional, but you’re likely to use one in most cases.
Returns true if any of the items in the collection meet the given criteria.

false if none of the items in the collection does not meet the given criteria.

RubyDoc.org’s entry Enumerable#any?

Enumerable#any? and Arrays

When used on an array and a block is provided, any? passes each item to the block. If the block returns true for any item during this process, any? returns true; otherwise, it returns false.

# "Fromage de Montagne de Savoie" is the longest-named cheese in this list
# at a whopping 29 characters
cheeses = ["feta", "cheddar", "stilton", "camembert", "mozzarella", "Fromage de Montagne de Savoie"]

cheeses.any? {|cheese| cheese.length >= 25}
=> true

cheeses.any? {|cheese| cheese.length >= 35}
=> false

When the block is omitted, any? uses this implied block: {|item| item}. Since everything in Ruby evaluates to true except for false and nil, using any? without a block is effectively a test to see if any of the items in the collection evaluate to true (or conversely, if all the values in the array evaluate to false or nil).

cheeses.any?
=> true

cheeses = [false, nil]
=> [false, nil]

cheeses.any?
=> false

# Remember that in Ruby, everything except for false and nil evaluates to true:
cheeses << 0
=> [false, nil, 0]

>> cheeses.any?
=> true

Enumerable#any? and Hashes

When used on a hash and a block is provided, any? passes each key/value pair in the hash to the block, which you can “catch” as either:

  1. A two-element array, with the key as element 0 and its corresponding value as element 1, or
  2. Two separate items, with the key as the first item and its corresponding value as the second item.

If the block returns true for any item during this process, any? returns true; otherwise, it returns false.

# Here's a hash where for each key/value pair, the key is a programming language and
# the corresponding value is the year when that language was first released
# The keys range in value from "Javascript" to "Ruby", and the values range from
# 1987 to 1996
languages = {"Javascript" => 1996, "PHP" => 1994, "Perl" => 1987, "Python" => 1991, "Ruby" => 1993}

languages.any? {|language| language[0] < "Pascal"}
=> true

languages.any? {|language, year_created| language < "Pascal"}
=> true

languages.any? {|language| language[0] < "Fortran"}
=> false

languages.any? {|language, year_created| language < "Fortran"}
=> false

languages.any? {|language| language[0] >= "Basic" and language[1] <= 1995}
=> true

languages.any? {|language, year_created| language >= "Basic" and year_created <= 1995}
=> true

languages.any? {|language| language[0] >= "Basic" and language[1] <= 1985}
=> false

languages.any? {|language, year_created| language >= "Basic" and year_created <= 1985}
=> false

Using any? without a block on a hash is meaningless, as it will always return true. When the block is omitted, any? uses this implied block: {|item| item}. In the case of a hash, item will always be a two-element array, which means that it will never evaluate as false nor nil.

And yes, even this hash, when run through any?, will still return true:

{false => false, nil => nil}.any?
=> true

Special Case: Using Enumerable#any? on Empty Arrays and Hashes

When applied to an empty array or hash, with or without a block, any? always returns false. That’s because with an empty collection, there are no values to process and return a true value.

Let’s look at the case of empty arrays:

cheeses = []
=> []

cheeses.any? {|cheese| cheese.length >= 25}
=> false

cheeses.any?
=> false

# Let's try applying "any?" to a non-empty array
# using a block that ALWAYS returns true:
["Gruyere"].any? {|cheese| true}
=> true

# ...but watch what happens when we try the same thing
# with an EMPTY array!
[].any? {|cheese| true}
=> false

…now let’s look at the case of empty hashes:

languages = {}
=> {}

languages.any? {|language| language[0] < "Pascal"}
=> false

languages.any? {|language, year_created| language < "Pascal"}
=> false

languages.any?
=> false

# Let's try applying "any?" to a non-empty hash
# using a block that ALWAYS returns true:
{"Lisp" => 1959}.any? {|language| true}
=> true

# ...but watch what happens when we try the same thing
# with an EMPTY hash!
{}.any? {|language| true}
=> false

Categories
Uncategorized

21 Ruby Tricks You Should be Using in Your Code

Over at Ruby Inside, there’s an article titled 21 Ruby Tricks You Should be Using in Your Code will all sorts of useful code snippets. Even if you code in Ruby every day, there just might be a trick or two you haven’t seen before!

Categories
Uncategorized

My Tech Reading List for May

I got a number of books for free this past week:

Books I\'m reviewing in May 2008

  • Head First PMP – When my friend Leigh Honeywell heard that I was taking a project management course later this month, she told me that she got this book for free at a conference and had no use for it. So she gave this book to me, and I’ll be reading it so that when the course comes around — it’s May 21st through 23rd — I’ll be at least familiar with the material.

And four books from Apress, courtesy of Julie Miller:

I’ll be reading them this month and posting my reviews here in Global Nerdy. Watch this space!

Categories
Uncategorized

With Advocates Like Zed…

I can’t help but wonder if, what with Zed Shaw’s talk of switching to Python and Django, if Guido and Adrian view him the way Barack Obama is portrayed as viewing Jesse Jackson and Al Sharpton in The Obama Files

Categories
Uncategorized

RubyFringe: July 18-20

RubyFringe logo

There’ve been hints about it all over the ‘net for the past couple of weeks, but it’s finally out: the RubyFringe conference is taking place in Toronto on July 18th through 20th. Its organizers — local Ruby/Rails heroes Unspace — describe it as “an avant-garde conference for developers that are excited about emerging technologies outside of the Ruby on Rails monoculture”. If the “sold-out and over-sold labradoodle shows that are now staged with alarming frequency” are Kenny G, RubyFringe aims to be the Sex Pistols.

“We believe that the most important function of a geek conference is to encourage networking between smart people doing awesome stuff,” the site says. “We have plans to keep everyone engaged for the entire duration of the event, with several meals as well as after-hours socializing covered.”

The event boasts:

  • Just one track
  • A limit of 150 attendees
  • No technical sponsors

If there’s a group capable of making this gathering — calling it a conference would be contrary to its spirit — it’s Unspace, who are the folks behind Toronto’s original regular gathering of Rails developers, Rails Pub Nite.

Also adding to the event is the speaker list, which already has an interesting assortment of people. Hampton Catlin wrote in his blog that when coming up with the idea for the conference, they had a list of 10 dream speakers and they’ve secured all ten, and from the list below, they’ve got even more:

The conference will take place at the Metropolitan Hotel in downtown Toronto, just a hop, skip and a jump away from some of Toronto’s more interesting neighbourhoods, including Chinatown, Queen Street West, Kensington Market and College West. The early-bird registration rate is $650, and you’ll be able to register starting February 18th.

If you’re looking for a change from the usual big conference fare, this might be the event for you, and Toronto — a great city with all sorts of things to do — is a great place to have it.

Categories
Uncategorized

TSOT Ruby/Rails Project Night Next Tuesday!

Next Tuesday is the second Tuesday of the month, which means: Ruby/Rails Project Night, hosted by TSOT!

Jon Stewart, Conan O'Brien and Stephen Colbert fighting over a Rails logo

The Quick Version

  • When: Tuesday, February 12th, 2008:
    • Doors open around 5:30 p.m.
    • Presentations begin sometime between 6 – 6:30 p.m.
    • Arrive early to get fed!
  • Where: TSOT developer office, 151 Bloor Street West (just east of Avenue Road), Suite 1130
  • Admission: FREE (but please register!)
  • Register with: Corina Newby or Joey deVilla

About Ruby/Rails Project Night

Ruby/Rails Project Night is a Toronto-area gathering held at the TSOT developer office on the second Tuesday of every month. It’s an event that lets people developing projects in either Ruby or Ruby on Rails show them off in front of their peers in 20-30 minute presentations. Presenters are encouraged to go into as much technical detail as they like (even showing the code, if they’re so inclined) and cover all sorts of aspects of their projects, from programming issues to visual design and usability to the business of making a living off their software.

Whether you code in Ruby and Rails for a living like we do, dabble in it in your spare time or are just curious as to what the fuss is all about, we encourage you to come to our office next Tuesday for Ruby/Rails Project Night! It’s a chance for you to see software that’s being developed right here in town and to mingle with other developers interested in Ruby and Rails. We provide food and drink, so you can focus on the presentations and not your grumbling stomach.

Who’s Presenting

Yours Truly will start the night with an opening monologue to get things going, after which I’ll be followed the the evening’s main presentations:

  • How to Avoid Hanging Yourself in Rails, by Rowan Hick. This presentation is subtitled “or: Optimizing Your ActiveRecord Associations”.
  • EasyBrandingTools.com: Mike Bowler and Steve Vetzal will talk about their project that helps new businesses be memorable.
  • CRMS – Clinical Research Management System. Luke Galea will present this project, a Rails and Prolog/XSB application that manages drug and procedure trials at some of the biggest hospitals in the U.S..

What Happened at the Last Ruby/Rails Project Night?

Everyone Takes Their Seats
Click the photo to see it on its Flickr page.

Check out this article, which has a quick write-up and photos.

Categories
Uncategorized

Enumerating Ruby’s “Enumerable” Module, Part 3: “detect”, a.k.a. “find”

Enumerable#find: A magnifying glass focused on a ruby

Welcome to the third installment in my series of articles on the methods of Ruby’s Enumerable module. This series is meant to address some of the shortcomings in the official documentation

In case you missed the first two, here they are:

  1. all? and any?
  2. collect/map

In this installment, I’m going to cover the find method. This is a particularly interesting one because it covers detect/find‘s little-talked about optional parameter.

detect, a.k.a. find

  • In plain language: What’s the first item in the collection that meets the given criteria?
  • Ruby.Doc.org’s entry: Enumerable#detect / Enumerable#find
  • Expects:
    • A block containing the criteria.
    • An optional argument containing a proc that calculates a “default” value — that is, the value to return if no item in the collection matches the criteria.
  • Returns:
    • The first item in the collection that matches the criteria, if one exists.
    • If no such item exists in the collection:
      • nil if no argument is provided
      • The value of the argument if one is provided
  • detect and find are synonyms — you can use either. I personally prefer find, as it’s shorter and a good match with a related method, find_all. I also just think that “find” conveys the method’s functionality much better than “detect”.

    Using detect/find with Arrays

    When used on an array without an argument, detect/find passes each item from the collection to the block and…

    • If the current item causes the block to return a value that doesn’t evaluate to false, detect/find stops going through collection and returns the item.
    • If no item in the collection causes the block to return a value that doesn’t evaluate to false, detect/find returns nil.

    classic_rock_bands = ["AC/DC", "Black Sabbath", "Queen", "Scorpions"]
    
    classic_rock_bands.find {|band| band > "Led Zeppelin"}
    => "Queen"
    
    classic_rock_bands.find {|band| band > "ZZ Top"}
    => nil
    

    Using the optional argument is a topic big enough to merit its own section, which appears later in this article.

    Using detect/find with Hashes

    With hashes, detect/find passes each key/value pair in the hash to the block, which you can “catch” as either:

    1. A two-element array, with the key as element 0 and its corresponding value as element 1, or
    2. Two separate items, with the key as the first item and its corresponding value as the second item.

    detect/find is one of those methods of Enumerable that works a little oddly since:

    • The result it returns depends on the order of the collection
    • We’re always told that hashes don’t really any order (there seems to be one, but it’s shrouded in mystery).

    metacritic_ratings = {"Juno" => 81, "American Gangster" => 76, \
                          "Golden Compass" => 51, "Meet the Spartans" => 9}
    => {"American Gangster"=>76, "Golden Compass"=>51, "Juno"=>81, "Meet the Spartans"=>9}
    
    metacritic_ratings.find {|metacritic_rating| metacritic_rating[1] > 80}
    => ["Juno", 81]
    
    metacritic_ratings.find {|film, rating| rating > 80}
    => ["Juno", 81]
    
    metacritic_ratings.find {|film, rating| rating > 90}
    => nil
    

    Using detect/find with the Optional Argument

    detect/find‘s optional argument lets you specify a proc or lambda whose return value will be the result in cases where no object in the collection matches the criteria.

    (Unfortunately, a complete discussion of procs and lambdas is beyond the scope of this article. I highly recommend looking at Eli Bendersky’s very informative article, Understanding Ruby blocks, Procs and methods.)

    I think that the optional argument is best explained through examples…

    classic_rock_bands = ["AC/DC", "Black Sabbath", "Queen", "Scorpions"]
    
    # Let's define a proc that will simply return the default band's name
    # for cases where none of the bands in the array meets the criteria.
    default_band = Proc.new {"ABBA"}
    
    # Procs are objects, so using a proc's name alone isn't sufficient
    to invoke its code -- doing so will simply return the proc object.
    default_band
    => #<Proc:0x00553f34@(irb):31>
    # (The actual value will be different for you, but you get the idea.)
    
    # To call a proc, you have to use its "call" method:
    default_band.call
    => "ABBA"
    
    # detect/find calls the "call" method of the object you provide as the argument
    # if no item in the collection matches the criteria in the block.
    classic_rock_bands.find(default_band) {|band| band > "Led Zeppelin"}
    => "Queen"
    
    classic_rock_bands.find(default_band) {|band| band > "ZZ Top"}
    => "ABBA"
    
    # Let's try something a little fancier, and use a lambda this time.
    # The differences between procs and lambdas are very fine -- I suggest
    # you check Eli Bendersky's article for those differences.
    random_band = lambda do
    	fallback_bands = ["Britney Spears", "Christina Aguilera", "Ashlee Simpson"]
    	fallback_bands[rand(fallback_bands.size)]
    end
    
    # Let's give it a try...
    classic_rock_bands.find(random_band) {|band| band > "ZZ Top"}
    => "Britney Spears"
    >> classic_rock_bands.find(random_band) {|band| band > "ZZ Top"}
    => "Ashlee Simpson"
    >> classic_rock_bands.find(random_band) {|band| band > "ZZ Top"}
    => "Christina Aguilera"
    

    To see a “real” application of detect/find's optional argument, see this Ruby Quiz problem.