Categories
Uncategorized

Damian Conway Tonight!

Damian Conway - July 16, 2008

Damian Conway, Perl expert extraordinaire, Open Source luminary and long-time friend of the Toronto Perl Mongers, will deliver — free and to the public — one of his signature tour-de-force completely insane talks that is…

  • 1/3 high-end IT,
  • 1/3 showmanship,
  • and 1/3 peyote-fuelled hallucination.

Tonight will be the world premiere of a new talk, which goes under the title of Temporally Quaquaversal Virtual Nanomachine Programming in Multiple Topologically Connected Quantum-Relativistic Parallel Timespaces…Made Easy.

As with the fanciful titles of his other talks, it’s hard to tell what it’ll actually be about, but having seen a couple of his presentations, I can guarantee that it will be a slightly-askew look at technology done in an engaging and hilarious fashion. Better still, you’ll be the first to see this presentation, which is a dress rehearsal for the O’Reilly Open Source Conference taking place later this month in Portland, Oregon.

Best of all, unlike the people at the Open Source Conference who’ll have to shell out something in the neighbourhood of $2000, admission to this event is absolutely free. (They will be taking up a collection for Damian in order to provide him some sort of honorarium for his doing the presentation, and some of the DemoCamp money is also going to Damian).

If you’d like to catch this event (I’ll be there), it’s tonight at the Bahen Centre for Information Technology, which is on 40 St. George Street (just north of College), right in the middle of the University of Toronto campus.

As I like to say for this sort of event: be there and be square!

Categories
Uncategorized

This Week in Toronto Tech

Toronto Tech People
Just a small sample of the people that make Toronto’s tech community great.

This week is going to be a week unlike any other in the Toronto technology scene: a week of events created not by municipal groups, large techno-conglomerates or industry think tanks, but by small groups of passionate individuals who enjoys working with both people and technology.

These events don’t have the benefit of major sponsorship or media coverage, nor will they be lining their organizers’ wallets. They’re events put together by amateurs in the original sense of the word: people who do it not for profit, but for their love of their craft, in the hope that both the attendees and even the field itself will be advanced from insights, understanding and knowledge gained by gathering together and exchanging ideas.

It’ll be a busy week for me. I’ll not only be attending these events, but I’ll also be MCing two of them as well. I’ll be posting reports from these gatherings here — keep watching this blog!

DemoCamp 18: Tuesday July 15th, 5:30 p.m. – 9:30 p.m. at Supermarket

DemoCamp Toronto 18: Tuesday, July 15th @ Supermarket

DemoCamp 18 is the eighteenth gathering of the bright lights in Toronto’s software development community where we show each other our projects in action. DemoCamp has grown from a gathering of a couple dozen in late 2005 to a meetup of hundreds at locations like the MaRS Centre and the Toronto Board of Trade and was voted “Toronto’s Best Unconference” earlier this year by BlogTO. It’s given many local software people the chance to showcase their work, meet other people in their field, make connections, get jobs and even get venture capitalist funding (that’s what happened to b5media, for whom I work).

I’m one of DemoCamp’s stewards and will be co-MCing DemoCamp.

You can see the schedule of events for DemoCamp 18 at the DemoCamp.info site. This event’s tickets — a good number of which were free, the remainder going for five or ten dollars — got snapped up within hours of becoming available.

Damian Conway: Wednesday, July 16th, 6:30 p.m. – 9:30 p.m. at the Bahen Centre, U of T

Damian Conway - July 16, 2008

The Perl programming language has been given the nickname “the duct tape of the internet” because of its importance in the development of the early web. Damian Conway is its most eloquent spokesperson and a speaker who can turn the dryest of academic lectures into a brain-tickling comic monologue that delivers both laughs and technical insight.

On Wednesday, Toronto will play host to the world premiere of his new talk, titled Temporally Quaquaversal Virtual Nanomachine Programming in Multiple Topologically Connected Quantum-Relativistic Parallel Timespaces… Made Easy. The event will be held at the Bahen Centre at the University of Toronto and it will be free of charge. For more details, see its Upcoming page.

FAILCamp: Friday July 18th, 4:00 p.m. – 7:00 p.m. at The Rhino

FAILCamp

I’ll let the FAILCamp creators, Amy Hoy and Thomas Fuchs do the talking:

“My reputation grows with every failure,” wrote George Bernard Shaw in a letter to fellow author Frank Harris. A healthy attitude towards the natural state of humanity, if you ask us.

We all know failure: public, private, large, small, free or costly, embarrassing or funny or poignant (or all of the above). We have all experienced what our friend Patrick has called “the beautiful rainbow of Fail.” And we tend to stuff it in the closet, keep it under wraps, don’t-ask-don’t-tell or any other number of hidey clichés that poor, beautiful rainbows should not be subject to. We believe that it’s time to give our personal fail some tough love and talk it out over beer!

Join us for a brief, rousing introduction followed by comraderie, beer, and Show and Tell. We’ll present a little about failure through the ages, mining your personal suck, maybe some science, pithy quotes from people you may or may not respect, and share some failure stories of our own.

Then it’ll be your turn. If all goes to plan, you may even win in our friendly “race to the bottom” for the most public, most expensive, or most ridiculous Story of Fail.

Also, did we mention beer?

For more details, see FAILCamp’s event page on Facebook.

RubyFringe: Friday July 18th – Sunday July 20th at the Metropolitan Toronto Hotel

RubyFringe

Finally, the upcoming weekend belongs to RubyFringe, the “deep nerd tech with punk rock spirit conference”.

“RubyFringe,” says its site, “RubyFringe is an avant-garde conference for developers that are excited about emerging Ruby projects and technologies. We’re mounting a unique and eccentric gathering of the people and projects that are driving things forward in our community.”

I’ll be MCing the opening night’s events at the Amsterdam Brewery. Alas, tickets are sold out!

Categories
Uncategorized

Enumerating Enumerable: Enumerable#drop

Enumerating Enumerable marches on!

This is the seventh article in my series in which I try to do a better job of documenting Ruby’s Enumerable module than Ruby-Doc.org does. If you’ve missed the other articles in the series, they’re listed below:

  1. all?
  2. any?
  3. collect / map
  4. count
  5. cycle
  6. detect / find

In this installment, I cover a method added in Ruby 1.9: drop.

Enumerable#drop Quick Summary

Graphic representation of the \"drop\" method in Ruby\'s \"Enumerable\" module

In the simplest possible terms Given a collection and a number n, create an array made of the items of the collection with the first n items removed.
Ruby version 1.9 only
Expects The number of elements to remove from the start of the collection.
Returns An array made up of the remaining items, if there are any./td>
RubyDoc.org’s entry Enumerable#drop

Enumerable#drop and Arrays

With an array, drop takes a number n as an argument and returns an array created by removing the first n elements of the array. The resulting array is made up of the remaining elements.

# These are the favourite bands of RubyFringe organizer
# Meghan Katleen Millard's, according to her Facebook profile
meghans_fave_bands = ["Afghan Whigs", "Bjork", "Charles Mingus",
"Deerhunter", "Electrelane", "Francois Hardy", "Godspeed You Black Emperor!"]
=> ["Afghan Whigs", "Bjork", "Charles Mingus", "Deerhunter", "Electrelane",
"Francois Hardy", "Godspeed You Black Emperor!"]

# Let's lose the first 5
meghans_fave_bands.drop 5
=> ["Francois Hardy", "Godspeed You Black Emperor!"]

# The original array is not affected
meghans_fave_bands
=> ["Afghan Whigs", "Bjork", "Charles Mingus", "Deerhunter", "Electrelane",
"Francois Hardy", "Godspeed You Black Emperor!"]

Enumerable#drop and Hashes

With an hash, drop takes a number n as an argument and returns an array created by removing the first n elements of the array (drop is only in Ruby 1.9 and later, where hashes keep the order in which they were defined, so its results are predictable). The resulting array is made up of the remaining elements, with each element converted into a two-element array where element 0 is the key and element 1 is the corresponding value.

# Here's a hash of the first five U.S. states
# (in terms of alphabetical order) and their capitals.
# This example is in Ruby 1.9, which means that
# the hash keys will stay in the order in which
# they were defined.
states_and_capitals = {"Alabama" => "Montgomery", \
                       "Alaska"  => "Juneau", \
                       "Arizona" => "Phoenix", \
                       "Arkansas" => "Little Rock", \
                       "California" => "Sacramento"}
=> {"Alabama"=>"Montgomery", "Alaska"=>"Juneau", "Arizona"=>"Phoenix",
"Arkansas"=>"Little Rock", "California"=>"Sacramento"}

# Let's remove the first 3
states_and_capitals.drop 3
=> [["Arkansas", "Little Rock"], ["California", "Sacramento"]]

# The original hash is not affected
states_and_capitals
=> {"Alabama"=>"Montgomery", "Alaska"=>"Juneau", "Arizona"=>"Phoenix",
"Arkansas"=>"Little Rock", "California"=>"Sacramento"}

Enumerable#take: Enumerable#drop’s Evil Twin

I’ll cover take in detail in a later installment, but for now, an example should suffice:

meghans_fave_bands = ["Afghan Whigs", "Bjork", "Charles Mingus",
"Deerhunter", "Electrelane", "Francois Hardy", "Godspeed You Black Emperor!"]
=> ["Afghan Whigs", "Bjork", "Charles Mingus", "Deerhunter", "Electrelane",
"Francois Hardy", "Godspeed You Black Emperor!"]

# drop(n) removes the first n elements
meghans_fave_bands.drop(4)
=> ["Electrelane", "Francois Hardy", "Godspeed You Black Emperor!"]

meghans_fave_bands.take(4)
=> ["Afghan Whigs", "Bjork", "Charles Mingus", "Deerhunter"]

Categories
Uncategorized

Windows Vista is Like Paris Hilton Playing Audrey Hepburn

It’s been five months since I’ve been using a Windows Vista-based computer as my primary machine (after having used a Mac for years). My opinion can best be summarized with a “Successories”-style poster utilizing that horrible new photo of Paris Hilton attempting to channel Audrey Hepburn:

Windows Vista: es, it looks pretty and all dressed up, but it’s still full of big, gaping holes.

If work won’t provide me with a Mac laptop, I may end up just buying one myself. The refurbished ones are available at pretty good prices.


In case you’re too young to get the reference in the Paris Hilton photo, here’s the original — it’s a still from a scene in Breakfast at Tiffany’s:

Audrey Hepburn with a cigerette holder in \"Breakfast at Tiffany\'s\"

Categories
Uncategorized

Enumerating Enumerable: Enumerable#detect/Enumerable#find

Here’s another article in the Enumerating Enumerable series, in which I attempt to improve upon RubyDoc.org’s documentation for the Enumerable module, which I find rather lacking. If you’ve missed the previous articles in the series, I’ve listed them below:

  1. all?
  2. any?
  3. collect / map
  4. count
  5. cycle

This installment covers a method that goes by two names: detect or find. I personally prefer find, as it’s shorter and the term I tend to use for its function.

Enumerable#detect/Enumerable#find Quick Summary

Graphic representation of the \"detect\" or \"find\" method in Ruby\'s \"Enumerable\" module.

In the simplest possible terms What’s the first item in the collection that meets the given criteria?
Ruby version 1.8 and 1.9
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, detect/find returns:

  • nil is returned if no argument is provided
  • the value of the argument, if one is provided.
RubyDoc.org’s entry Enumerable#detect / Enumerable#find

Enumerable#detect/Enumerable#find and 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.

In the examples that follow, I’ll be using the find method. detect does exactly the same thing; it’s just that I prefer find.

# Time to establish my "old fart" credentials
classic_rock_bands = ["AC/DC", "Black Sabbath", "Queen", \
"Ted Nugent and the Amboy Dukes", "Scorpions", "Van Halen"]
=> ["AC/DC", "Black Sabbath", "Queen", "Ted Nugent and the Amboy Dukes",
"Scorpions", "Van Halen"]

# Of the bands in the array, which is the first one
# whose name is longer than 8 characters?
classic_rock_bands.find {|band| band.length > 8}
=> "Black Sabbath"

# Which is the first one whose name is exactly
# 5 characters long?
classic_rock_bands.find {|band| band.length == 5}
=> "AC/DC"

# The order of items in the array can affect "find"'s result.
# Let's put the array into reverse sorted order:
classic_rock_bands.sort!.reverse!
=> ["Van Halen", "Ted Nugent and the Amboy Dukes", "Scorpions", \
"Queen", "Black Sabbath", "AC/DC"]

# Again: which is the first band whose name
# is longer than 8 characters?
=> "Van Halen"

# Again: which is the first band whose name
# is exactly 5 characters?
=> "Queen"

# If no band in the array meets the criteria,
# "find" returns nil.
# There are no bands in the list with names shorter
# than 5 characters...
classic_rock_bands.find {|band| band.length < 5}
=> nil

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

Enumerable#detect/Enumerable#find and Hashes

When used on a hash and a block is provided, 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.

When used on a hash 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.

years_founded = {"AC/DC" => 1973, \
                 "Black Sabbath" => 1968, \
                 "Queen" => 1970, \
                 "Ted Nugent and the Amboy Dukes" => 1967, \
                 "Scorpions" => 1965, \
                 "Van Halen" => 1972}
# Ruby 1.8 re-orders hashes in some mysterious way that is almost never
# the way you entered it. Here's what I got in Ruby 1.8:
=> {"Queen"=>1970, "AC/DC"=>1973, "Black Sabbath"=>1968, "Scorpions"=>1965,
"Ted Nugent and the Amboy Dukes"=>1967, "Van Halen"=>1972}

# Ruby 1.9 preserves hash order so that hashes keep the order in which
# you defined them. Here's what I got in Ruby 1.9:
=> {"AC/DC"=>1973, "Black Sabbath"=>1968, "Queen"=>1970,
"Ted Nugent and the Amboy Dukes"=>1967, "Scorpions"=>1965, "Van Halen"=>1972}

# Which band is the first in the hash to be founded
# in 1970 or later?
years_founded.find {|band| band[1] >= 1970}
# In Ruby 1.8, the result is:
=> ["Queen", 1970]
# In Ruby 1.9, the result is:
=> ["AC/DC", 1973]

# Here's another way of phrasing it:
years_founded.find {|band, year_founded| year_founded >= 1970}

Using Enumerable#detect/Enumerable#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…

# Once again, the array of classic rock bands
classic_rock_bands = ["AC/DC", "Black Sabbath", "Queen", \
"Ted Nugent and the Amboy Dukes", "Scorpions", "Van Halen"]

# Let's define a proc that will simply returns the band name
# "ABBA", who are most definitely not considered to be
# a classic rock band.
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"

# What we want to do is use "default_band" as a proc that
# provides a default value in the event that detect/find doesn't
# find a value that matches the critera.

# 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.

# There *is* a band in the array that comes after
# "Led Zeppelin" alphabetically: Queen.
classic_rock_bands.find(default_band) {|band| band > "Led Zeppelin"}
=> "Queen"

# The last band in the array, alphabetically speaking,
# is Van Halen. So if we ask detect/find to find a band that
# comes after Van Halen, it won't find one.
# Without the argument, detect/find returns nil,
# but *with* the argument, it will invoke the "call"
# method of the object you provide it.
classic_rock_bands.find(default_band) {|band| band > "Van Halen"}
=> "ABBA"

# Let's try something a little fancier. This time, we'll use a lambda.
# The differences between procs and lambdas are very fine -- I suggest
# you check Eli Bendersky's article for those differences.

# Let's create a lambda that when called,
# returns the name of a randomly-selected pop singer.
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 > "Van Halen"}
=> "Britney Spears"

classic_rock_bands.find(random_band) {|band| band > "Van Halen"}
=> "Ashlee Simpson"

classic_rock_bands.find(random_band) {|band| band > "Van Halen"}
=> "Christina Aguilera"

classic_rock_bands.find(random_band) {|band| band > "Led Zeppelin"}
=> "Queen"

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

Categories
Uncategorized

Enumerating Enumerable: Enumerable#cycle

Welcome to another installment of Enumerating Enumerable, my series of articles in which I attempt to improve upon RubyDoc.org’s documentation for the Enumerable module. So far, I’ve covered the following methods in this series:

  1. all?
  2. any?
  3. collect / map
  4. count

In this installment, I’m going to cover a method added into Enumerable in Ruby 1.9: Enumerable#cycle. It’s particularly poorly-documented in RubyDoc.org, and there isn’t much written about it anywhere else.

Enumerable#cycle Quick Summary

Graphic representation of the \"cycle\" method in Ruby\'s \"Enumerable\" class.

In the simplest possible terms Given a collection, creates an infinitely-repeating ordered source of its items.
Ruby version 1.9 only
Expects An optional block to act on the items in the infinitely repeating until the break statement is encountered.
Returns An Enumerable::Enumerator that acts as the infinite source of the collection’s items.
RubyDoc.org’s entry Enumerable#cycle

Enumerable#cycle and Arrays

When used on an array and a block is provided, cycle passes each item to the block. Once the last array item has been passed to the block, cycle starts over again at the beginning of the array. cycle goes through the array forever unless it encounters a break statement in the block.

# This example is a slightly fancier version of the example
# you'll see at RubyDoc.org
days_of_week = %w{Monday Tuesday Wednesday Thursday Friday Saturday Sunday}
=> ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]

# This will print the days of the week over and over,
# forever until you stop it with control-c.
days_of_week.cycle {|day| puts day}
=> Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
Monday
Tuesday
...

# The cycle can be broken with the "break" statement
days_of_week.cycle do |day|
    puts day
    break if day == "Friday"
end
=> Monday
Tuesday
Wednesday
Thursday
Friday
=> nil

The better use for cycle is when you use it to create an object that spits out the next item in a repeating sequence.

# Let's create an enumerator that we can use to give us
# days of the week in a repeating sequence.
days = days_of_week.cycle
=> #

# Enumerator's "next" method gives us the next day of the week
days.next
=> "Monday"

days.next
=> "Tuesday"

days.next
=> "Wednesday"

# Enumerator's "rewind" method resets the enumerator back
# to the first item
days.rewind
=> # "Monday"

...

# If you keep going, the enumerator will "wrap around" back
# to the beginning
days.next
=> "Saturday"

days.next
=> "Sunday"

days.next
=> "Monday"

How about one more example? We’ll use Enumerable‘s zip method, an array of dinner items and the “days of the week” cycle object to create a meal plan:

# Here's an array of international cuisine
dinners = ["Jerk chicken", "Lamb vindaloo", "Chicken fried steak", \
"Yeung Chow fried rice", "Tonkatsu", "Coq au Vin", "Chunky bacon", \
"Pierogies", "Salisbury steak", "Bibim Bap", \
"Roast beef", "Souvlaki"]
=> ["Jerk chicken", "Lamb vindaloo", "Chicken fried steak",
"Yeung Chow fried rice", "Tonkatsu", "Coq au Vin", "Chunky bacon",
"Pierogies", "Salisbury steak", "Bibim Bap",
"Roast beef", "Souvlaki"]

# Let's draw up a mean plan!
days.zip(dinners) {|daily_meal| p daily_meal}
=> ["Monday", "Jerk chicken"]
["Tuesday", "Lamb vindaloo"]
["Wednesday", "Chicken fried steak"]
["Thursday", "Yeung Chow fried rice"]
["Friday", "Tonkatsu"]
["Saturday", "Coq au Vin"]
["Sunday", "Chunky bacon"]
["Monday", "Pierogies"]
["Tuesday", "Salisbury steak"]
["Wednesday", "Bibim Bap"]
["Thursday", "Roast beef"]
["Friday", "Souvlaki"]

# If we want to store our meal plan, we can do it this way
meal_plan = []
=> []

days.zip(dinners) {|daily_meal| meal_plan << daily_meal}
=> nil

meal_plan
=> [["Monday", "Jerk chicken"], ["Tuesday", "Lamb vindaloo"],
["Wednesday", "Chicken fried steak"], ["Thursday", "Yeung Chow fried rice"],
["Friday", "Tonkatsu"], ["Saturday", "Coq au Vin"],
["Sunday", "Chunky bacon"], ["Monday", "Pierogies"],
["Tuesday", "Salisbury steak"], ["Wednesday", "Bibim Bap"],
["Thursday", "Roast beef"], ["Friday", "Souvlaki"]]

Enumerable#cycle and Hashes

When used on a hash and a block is provided, collect and map pass 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.

Each key/value pair is passed to the block, where the operation in the block is performed on the item. Once the last hash item has been passed to the block, cycle starts over again at the beginning of the hash. cycle goes through the hash forever unless it encounters a break statement in the block.

# Here we'll take the RubyDoc.org example for "cycle"
# but apply it to a hash of the crew of the Enterprise-D
crew = {:captain => "Picard", :first_officer => "Riker", \
:science_officer => "Data", :tactical_officer => "Worf"}
=> {:captain=>"Picard", :first_officer=>"Riker",
:science_officer=>"Data", :tactical_officer=>"Worf"}

# This will print the crew's rank and name over and over,
# forever until you stop it with control-c.
crew.cycle {|crewmember| p crewmember}
=> [:captain, "Picard"]
[:first_officer, "Riker"]
[:science_officer, "Data"]
[:tactical_officer, "Worf"]
[:captain, "Picard"]
[:first_officer, "Riker"]
[:science_officer, "Data"]
[:tactical_officer, "Worf"]
[:captain, "Picard"]
[:first_officer, "Riker"]
[:science_officer, "Data"]
[:tactical_officer, "Worf"]
[:captain, "Picard"]
[:first_officer, "Riker"]
...

# The cycle can be broken with the "break" statement
crew.cycle do |rank, name|
    puts "Rank: #{rank} - Name: #{name}"
    break if rank == :science_officer
end
=> Rank: captain - Name: Picard
Rank: first_officer - Name: Riker
Rank: science_officer - Name: Data
=> nil

We can use the same technique that we used with arrays and use cycle to create an object that spits out the next item in a cycling hash. Each time we get an item from the object, it comes in the form of a two-element array where the first element is the key and the second element is the corresponding value.

# Let's create an enumerator that we can use to give us
# the Enterprise-D crew's rank and name in a repeating sequence.
crewmembers = crew.cycle
=> #

# numerator’s “next” method gives us the next crewmember
crewmembers.next
=> [:captain, "Picard"]

crewmembers.next
=> [:first_officer, "Riker"]

crewmembers.next
=> [:science_officer, "Data"]

# Enumerator’s “rewind” method resets the enumerator back
# to the first item
crewmembers.rewind
=> #

crewmembers.next
=> [:captain, "Picard"]

...

# If you keep going, the enumerator will “wrap around” back
# to the beginning
crewmembers.next
=> [:tactical_officer, "Worf"]

crewmembers.next
=> [:captain, "Picard"]

crewmembers.next
=> [:first_officer, "Riker"]

Let’s try one more example! In this one, we’ll use cycle to create three different enumerators — two made from arrays, one from a hash — to assign cooking chores for the Enterprise-D crew for the next ten days.

# Create an enumerator for days
days = %w{Monday Tuesday Wednesday Thursday Friday Saturday Sunday}.cycle
=> #

# Create an enumerator for dinners
dinners = ["Jerk chicken", "Lamb vindaloo", "Chicken fried steak", \
"Yeung Chow fried rice", "Tonkatsu", "Coq au Vin", "Chunky bacon", \
"Pierogies", "Salisbury steak", "Bibim Bap", \
"Roast beef", "Souvlaki"].cycle
=> #

# Make sure we're starting from the beginning of the crew hash
crewmembers.rewind
=> #

# Let's assign dinner-cooking duties to the crew!
10.times do
    day = days.next
    dinner = dinners.next
    chef = crewmembers.next[1]
    puts "On #{day}, Crewman #{chef} will prepare #{dinner}."
end
=> On Monday, Crewman Picard will prepare Jerk chicken.
On Tuesday, Crewman Riker will prepare Lamb vindaloo.
On Wednesday, Crewman Data will prepare Chicken fried steak.
On Thursday, Crewman Worf will prepare Yeung Chow fried rice.
On Friday, Crewman Picard will prepare Tonkatsu.
On Saturday, Crewman Riker will prepare Coq au Vin.
On Sunday, Crewman Data will prepare Chunky bacon.
On Monday, Crewman Worf will prepare Pierogies.
On Tuesday, Crewman Picard will prepare Salisbury steak.
On Wednesday, Crewman Riker will prepare Bibim Bap.

Categories
Uncategorized

Laptop Losses Total 12,000 Per Week at U.S. Airports

A study of 106 major U.S. airports and 800 business travelers says that 12,000 laptops are lost in airports each week. Less than a third are recovered, and nearly half the travelers say their laptops contain some confidential business information. Most are lost either at security checkpoints or departure gates. How over 600,000 laptops get lost at airports each year is a mystery to me; after my passport and wallet, my laptop is the thing I guard the most when flying.