August 2008

Enumerating Enumerable: Enumerable#group_by

by Joey deVilla on August 31, 2008

Enumerating Enumerable

Once again, it’s Enumerating Enumerable time! This is the latest in my series of articles where I set out to make better documentation for Ruby’s Enumerable module than Ruby-Doc.org’s. In this installment — the seventeenth in the series — I cover the group_by method.

In case you missed any of the previous articles, they’re listed and linked below:

  1. all?
  2. any?
  3. collect / map
  4. count
  5. cycle
  6. detect / find
  7. drop
  8. drop_while
  9. each_cons
  10. each_slice
  11. each_with_index
  12. entries / to_a
  13. find_all / select
  14. find_index
  15. first
  16. grep

Enumerable#group_by Quick Summary

Graphic representation of the "group_by" method in Ruby's "Enumerable" module.

In the simplest possible terms Break a collection into groups based on some given criteria.
Ruby version 1.9 only
Expects A block containing the criteria by which the items in the collection will be grouped.
Returns A hash where each key represents a group. Each key’s corresponding value is an array containing the members of that group.
RubyDoc.org’s entry Enumerable#group_by

Enumerable#group_by and Arrays

When used on an array, group_by iterates through the array, passing each element to to the block. The result value of the block is the group into which the element will be placed.

Example 1

For the first example, I’ll use some code similar to the example given in Ruby-doc.org’s writeup of group_by:

(0..15).group_by {|number| number % 3}
=> {0=>[0, 3, 6, 9, 12, 15], 1=>[1, 4, 7, 10, 13], 2=>[2, 5, 8, 11, 14]}

In the code above, the numbers 0 through 15 are passed to the block, which receives each number as the parameter number. The group that each number is placed into is determined by the result value of the block, number % 3, whose result can be one of 0, 1 or 2. This means that:

  • The resulting hash will have three groups, represented by the keys 0, 1 and 2
  • The key 0‘s corresponding value is an array containing the numbers in the range (0..15) that are evenly divisible by 3 (i.e. the numbers for which number % 3 is 0.
  • The key 1‘s corresponding value is an array containing the numbers in the range (0..15) that when divided by 3 leave a remainder of 1 (i.e. the numbers for which number % 3 is 1.
  • The key 2‘s corresponding value is an array containing the numbers in the range (0..15) that when divided by 3 leave a remainder of 2 (i.e. the numbers for which number % 3 is 2.

Example 2

In the first example, the keys in the resulting hash are the same type as the values in the array whose contents we’re grouping. In this example, I’ll show that the keys in the resulting hash don’t have to be the same type as the values in the array.

simpsons = %w(Homer Marge Bart Lisa Abraham Herb)
=> ["Homer", "Marge", "Bart", "Lisa", "Abraham", "Herb"]

simpsons.group_by{|simpson| simpson.length}
=> {5=>["Homer", "Marge"], 4=>["Bart", "Lisa", "Herb"], 7=>["Abraham"]}

In the code above, each Simpson name is passed to the block, which receives it as the parameter simpson. The block’s result is the length of simpson, and this result is the group into which the name will go.

In the resulting hash:

  • Note that the keys are integers while the names in the groups are strings.
  • The key 5‘s array contains those names in Simpsons that are 5
    characters in length.
  • The key 4‘s array contains those names in Simpsons that are 4 characters in length.
  • The key 7‘s array contains those names in Simpsons that are 7 characters in length.

Example 3

In the previous two examples, the keys for the resulting array were calculated from the values in the initial array. In this example, I’ll demonstrate that the keys for the groupings can be determined in a completely arbitrary fashion that has nothing to do with the values:

# Put the Simpsons into randomly determined groups
simpsons.group_by{rand(3) + 1}
=> {3=>["Homer", "Bart", "Abraham", "Herb"], 1=>["Marge", "Lisa"]}

# Let's try that again. The results are very likely to be different:
simpsons.group_by{rand(3) + 1}
=> {1=>["Homer", "Bart"], 2=>["Marge", "Lisa", "Herb"], 3=>["Abraham"]}

# One more time!
simpsons.group_by{rand(3) + 1}
=> {2=>["Homer", "Bart", "Lisa"], 3=>["Marge", "Herb"], 1=>["Abraham"]}

Enumerable#group_by and Hashes

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

Example 1

In this example, we’ll group the cast of Family Guy by the item that they’re bringing to a potluck dinner:

potluck = {"Peter" => "lasagna",
           "Lois"  => "potato salad",
           "Chris" => "lasagna",
           "Meg"   => "brownies",
           "Stewie" => "chateaubriand",
           "Brian" => "potato salad",
           "Evil Monkey" => "potato salad"}
=> {"Peter"=>"lasagna", "Lois"=>"potato salad", "Chris"=>"lasagna", "Meg"=>"brownies",
"Stewie"=>"chateaubriand", "Brian"=>"potato salad", "Evil Monkey"=>"potato salad"}

# Here's one way to do it:
potluck.group_by{|person, bringing| bringing}
=> {"lasagna"=>[["Peter", "lasagna"], ["Chris", "lasagna"]], "potato salad"=>[["Lois", "potato salad"],
["Brian", "potato salad"], ["Evil Monkey", "potato salad"]], "brownies"=>[["Meg", "brownies"]],
"chateaubriand"=>[["Stewie", "chateaubriand"]]}

# Here's another way to do it:
potluck.group_by{|person| person[1]}
=> {"lasagna"=>[["Peter", "lasagna"], ["Chris", "lasagna"]], "potato salad"=>[["Lois", "potato salad"],
["Brian", "potato salad"], ["Evil Monkey", "potato salad"]], "brownies"=>[["Meg", "brownies"]],
"chateaubriand"=>[["Stewie", "chateaubriand"]]}

Example 2

In the previous example, the groupings were based on a calculation performed on the objects in the original hash. In this example, the groupings will be random: a random number generator will determine whose car each potluck attendee will ride to the potluck dinner:

potluck.group_by {[:peters_car, :quagmires_car, :clevelands_car][rand(3)]}
=> {:peters_car=>[["Peter", "lasagna"], ["Chris", "lasagna"], ["Evil Monkey", "potato salad"]],
:quagmires_car=>[["Lois", "potato salad"], ["Meg", "brownies"], ["Stewie", "chateaubriand"]],
:clevelands_car=>[["Brian", "potato salad"]]}

# Let's try another random grouping
potluck.group_by {[:peters_car, :quagmires_car, :clevelands_car][rand(3)]}
=> {:peters_car=>[["Peter", "lasagna"], ["Meg", "brownies"]], :quagmires_car=>[["Lois", "potato salad"],
["Stewie", "chateaubriand"], ["Brian", "potato salad"], ["Evil Monkey", "potato salad"]],
:clevelands_car=>[["Chris", "lasagna"]]}

# One more time!
potluck.group_by {[:peters_car, :quagmires_car, :clevelands_car][rand(3)]}
=> {:peters_car=>[["Peter", "lasagna"], ["Chris", "lasagna"], ["Stewie", "chateaubriand"]],
:quagmires_car=>[["Lois", "potato salad"], ["Evil Monkey", "potato salad"]], :clevelands_car=>[["Meg", "brownies"],
["Brian", "potato salad"]]}

{ 0 comments }

Found these photos while digging through my archives on the backup hard drive and thought you folks might find them interesting. They’re flipchart pages from either June 2000, back when I was working at Cory Doctorow’s startup, OpenCola. These are notes that I wrote on the GNUtella protocol; Chris Cummer and I worked off these notes to produce an app called COLAvision, which scored Gnutellanet for audio and video files, captured them and cued them up to be served as streams (oh, the assignments we got during the bubble…).

I expect to be doing a fair bit of doodling, since the b5media tech office walls are largely floor-to-ceiling whiteboards and I’ve also been diving into Dan Roam’s book, The Back of the Napkin, a book on solving problems and selling ideas with hand-drawn pictures on whiteboards, flipcharts, notepads, scrap paper or even — as the title implies — the back of a napkin (or serviette to you Brits out there).

Joey deVilla's GNUtella protocol notes, circa summer 2000.
My notes on the GNUtella protocol, part 1.

Joey deVilla's GNUtella protocol notes (part 2), circa summer 2000.
My notes on the GNUtella protocol, part 2.

{ 0 comments }

Pair Programming Chairs

by Joey deVilla on August 28, 2008

The development tool company Cenqua have a cute gag ad for a pair programming chair called the “PairOn” — an Aeron built for two:

Cenqua's "PairOn" chair

They list the PairOn’s “key features” as:

  • Fully unit-tested in our ego-free ergonomics lab
  • Essential office furniture for any eXtreme XP Pair (XXPP)
  • Fully adjustable via individual or pair control
  • Can be levered to standup-meeting height
  • 40-hour-week alarm buzzer built in
  • Available in a range of attractive colours

Here’s a pair programming chair that really exists: it’s a set of drawers that doubles as a stool:

TSOT's "Pair Programming" filing cabinate/chair

These are drawer sets mounted on some very good wheels and topped with well-padded upholstery. If you wanted to pair program with someone, you’d simply pull the drawer unit out from under their desk and sit on it. These things were surprisingly comfortable; I’ve spent upwards of two hours sitting on one of these with nary a complaint.

Alas, these aren’t available in stores. They were custom-built for a startup for whom I briefly worked, whose CEOs was more in love with the idea of running a start-up than actually running a start-up. Their last programmer recently ditched them, and I’m hoping to pick up one of these in their bankruptcy sale.

{ 4 comments }

The IE8 USB key in my computer

Last night, I attended a special sneak preview for Internet Explorer 8 Beta 2 organized by the folks at High Road Communications, who do the PR for Microsoft here in Toronto. Pete LePage, Product Manager of Internet Explorer Developer Division, did the presentation, and also present were Elliot Katz, Senior Product Manager for Microsoft Canada, Daniel Shapiro, Microsoft Canada’s Audience Manager, and my friend and fellow DemoCamp steward David Crow, Tech Evangelist for Microsoft Canada.

Let me get the disclosure part out of the way. Attending this event got me:

  • Free drinks and snacks during the presentation and a free dinner afterwards,
  • One Internet Explorer 8 gym water bottle with a tag inside it saying “BPA Free”,
  • and one 1GB USB key containing installers for IE8 (pictured in my laptop above) and the IE8 Evaluators’ Guide (a Word document that walks you through IE8′s features).

I’ve been to a couple of these Microsoft events before. The one about their “Windows Live” sites didn’t interest me at all, and the Vista one I attended was largely for people who did IT at companies with 1000 or more employees, which really isn’t my area of interest either (and the Vista preview installer they gave me resulted in disaster). This one was a considerably more interesting, as Pete put on a good presentation and it appears that Microsoft is making an effort to match the competing browsers.

Over the next little while, I’ll post articles covering my experiences as I take IE8 for a spin. In this article, I’ll mostly be talking about InPrivate Browsing, which is colloquially known as “Porn Mode”.

“Porn Mode”, a.k.a. “InPrivate Browsing”

The implementation of a browser session in which history, cache and other “trails of breadcrumbs” are deleted as soon as the session is over isn’t new: Apple’s Safari has a “Private Browsing” feature and there’s a Firefox extension that provides the same utility. However, for those not using Macs and especially those who aren’t the type to download and install Firefox and then install a plugin — and there are lots of these people out there — IE8 may be their first opportunity to try out such a feature.

Banking, Not Wanking

In his presentation, Pete was careful to take the “Banking, not wanking” approach when covering InPrivate Browsing, suggesting all sorts of non-saucy uses for the feature, including doing online banking, shopping for surprise presents for your spouse, surfing from a public terminal and so on. The Microsoft people present took my constant referring to it as “Porn Mode” in great stride, and I thank them for having a sense of humor about it.

The Problem

Convenience features like history, cache, automatic username and password field-filling are handy, but they sometimes have unintended consequences. For instance, suppose you, as a healthy, open-minded adult, like to look at videos featuring ladies without pants sitting on cakes at YouPorn.com. Let’s also suppose that a friend asks to borrow your computer for a moment to see a funny cat video at YouTube.com. As your friend types in the letters for “YouTube.com” in the address bar, this happens:

Screen capture: A user starts to type in "YouTube.com" and as "you" is formed, my "YouPorn.com" history appears.

This sort of browser-assisted embarrassment takes place more often than you might think. I’ve seen it happen firsthand, and it’s done everything from causing a little red-facedness to actually thwarting romantic possibilities. And you thought computers were supposed to make our lives easier!

The IE8 solution, InPrivate Browsing, is accessible through the Safety menu (shown below) or through the control-shift-P key combo:

Screen Shot: IE8's "Safety" menu, with "InPrivate Browsing" selected

This opens up a new, separate browser window for InPrivate Browsing, which does not keep “breadcrumbs” like history, cache data, cookies and so on. The address bar for InPrivate Browsing windows has the InPrivate logo as a visual cue that this particular session won’t leave a trail that will embarrass you or give away your secrets:

Screen Shot: A new "InPrivate Browsing" window appears

Maybe it’s me, but I think the “InPrivate” graphic in the address bar is a bit too subtle. Then again, a more obvious visual indicator (say, giving the InPrivate browser window a different color) might be an invitation to shoulder-surf.


Hey man, I had to see if it works, right?

Screen Shot: YouPorn's title page

I swear, I had to poke about the site a little bit in order to test if my History was being saved. It’s all in the name of application testing!

Screen Shot: Blurred-out YouPorn video page

After a little “research”, I closed not just the InPrivate Browsing window, but the whole browser, then started it up again. Then I proceeded to type “You” into the address bar. Under normal circumstances, my YouPorn.com history would be there for all to see. But it wasn’t!

Screen shot: None of my InPrivate browsing history shows up

For those of you who need to clear the cache, cookies, history or other data for any reason, there’s also the Delete Browsing History item in the Safety menu:

"Safety" menu with "Delete Browsing History" item selected

And it provides a number of deletion options:

The "Delete Browsing History" dialog box


And there you have it: a quick tour of IE8′s much-snickered-about “Porn Mode”.

Keep watching the blog for more posts about IE8 as I use it more and cover its features. Perhaps I’ll cover the development tools next.

{ 4 comments }

The Funniest “Unboxing” Video I’ve Seen

by Joey deVilla on August 27, 2008

This one’s for the Samsung Omnia (a.k.a. the i900):

{ 0 comments }

b5media is a Red Herring Canada Top 50 Finalist

by Joey deVilla on August 26, 2008

Red Herring "Top 50 Canada" badge and b5media logo

b5media, the company where I work and hold the title of “Nerd Wrangler”, is one of the finalists in Red Herring Canada’s “Top 50″ Awards, which is described as…

…celebrating the most innovative and promising companies in Canada. Adding to the success of our yearly North America 100, Europe 100 and Global 100 events, Red Herring Canada will provide an opportunity for the nation’s Top 50 companies to deliver their message to the top VCs and other participants throughout North America and abroad.

The Top 50 will be announced at the Red Herring Canada ’08 event in Mont Tremblant (near Montreal), which takes place from September 15th through 17th.

{ 0 comments }

I’m on “Future Tense” Tonight

by Joey deVilla on August 26, 2008

John Gordon, host of "Future Tense"On Friday, Jon Gordon from the radio show Future Tense interviewed me about my recent posting here titled Seinfeld and Celebrity Computer Endorsements, which features my comments on Microsoft’s hiring of Jerry Seinfeld as a pitchman and a collection of celebrity computer endorsements. In the interview, which is being broadcast tonight, we talk about whether celebrity endorsements for computers work, as well as some of our favorite celebrity computer advertisements.

Future Tense is broadcast on American Public Media stations. For a schedule of when it’s on, click here.

{ 0 comments }

Security Through Python

by Joey deVilla on August 25, 2008

While this is actually not about computer security nor about the Python programming language (which I’ll cover in some articles soon), I thought my Pythonista readers might find it amusing…

Guy freaking out at seeing two pythons on the dashboard of a car

…for the real story behind this photo, see this article in the Daily Mail.

{ 0 comments }

Even if you saw yesterday’s post about celebrity tech endorsements, do check it again — I’ve been updating it with more ads for computers and videogames featuring celebrities, and I still have to add a few more.

Here’s an 1970s print ad that seems gallows-humor funny today, considering that there are people itching to attack Iran before they develop nuclear weapons. It features the Shah of Iran as a poster boy for a campaign encouraging more nuclear power plants in the U.S.:

Print ad: "Guess who's building nuclear power plants", featuring the Shah of Iran

Here’s the text of the ad:

Guess Who’s Building Nuclear Power Plants

The Shah of Iran is sitting on top of the largest reservoirs of oil in the world.

Yet he’s building two nuclear plans and planning two more to provide electricity for his country.

He knows the oil is running out — and time with it.

Be he wouldn’t build the plants now if he doubted their safety. He’d wait. As many Americans want to do.

The Shah knows that nuclear energy is not only economical, it has enjoyed a remarkable 30-year saftey record. A record that was good enough for the citizens of Plymouth, Massachusetts, too. They’ve approved their second nuclear plant by a vote of almost 4 to 1. Which shows you that you don’t have to go as far as Iran for an endorsement of nuclear power.

For more about Iran’s history with nuclear power (and how it intertwines with U.S. foreign policy), see this article at Foreign Policy in Focus.

{ 3 comments }

Seinfeld and Celebrity Computer Endorsements [Updated]

by Joey deVilla on August 21, 2008

Updated!

Hello, Boing Boing readers! (And thanks, Cory!) I’ve added a whole whack of new videos to this entry including John Cleese’s 1980s ads for Compaq, Tom Baker’s ads for Prime Computer, plus celebrity ads for Intel Centrino, Apple, Nintendo DS and more!

What’s Up with That?

By now, you’ve probably heard that Microsoft latest move to counter the incredibly popular “I’m a Mac / I’m a PC” ads was to hire Jerry Seinfeld as their new pitchman. The new campaign, which is rumored to be based on the slogan “Windows, Not Walls”, is expected to cost US$300 million — $10 million of which is earmarked for Seinfeld — is expected to debut on September 4th. As Jerry would say in his own stand-up routines: “What’s up with that?”

Gawker sums it up best:

Scene from "Seinfeld" showing the Mac in his apartmentYes, because if there’s one surefire way to convince everyone Vista is cool, cutting edge and not liable to get frazzled by life’s minor complications, it’s hiring a 1990s sitcom star and professional kvetcher! Who, um, very visibly owned a series of Macs on his show. This is Microsoft’s worst promotional concept since, well, since its last Vista campaign, the Mojave Experiment, which decisively proved that people hate Vista but will use it if they are tricked into thinking it’s something else, like a stable, functional tool. Here’s how Madison Avenue is responding:

“They are not seen as cool,” says Robert Passikoff, president of Brand Keys, a New York branding firm. “Apple is cool. Can anyone even recall a Microsoft ad? No.”

And they won’t be able to remember this one either, because using Seinfeld humor in ads was already considered tired three years ago.

Microsoft’s hiring of a celebrity who peaked back in the 1990s is a perfect metaphor for a two of their biggest problems:

  • They’re hamstrung by the need to maintain backward compatibility with 1990s applications (Raymond Chen’s blog has the best stories about these issues).
  • They’re still using their 1990s approach to marketing: throwing a lot of money around.

I expect that Microsoft’s ads will be the exact opposite of Apple’s: instead of two unknown (at least prior to the ads) guys against a plain white background, they’ll feature a celebrity against a glitzy background. Also unlike Apple’s ads, I suspect theirs won’t be all that effective.

To borrow another Seinfeld line: “Good luck with all that.”

Seinfeld in One of the Old “Think Different” Ads

Mark Evans found this old Apple “Think Different” ad — one of those “Here’s to the crazy ones” ads with Richard Dreyfuss doing the voice-over — that features, of all people, a young Jerry Seinfeld.

Seinfeld in an HP Ad

In this HP ad, Seinfeld promotes not just one, but two flops: Windows Vista and Bee Movie:

A Brief History of Celebrity Computer Endorsements

Microsoft’s hire of Seinfeld led me to search for computer and videogame system ads featuring celebrities. Here’s what I found:

Commodore: William Shatner

In the original Star Trek series, Shatner’s character Captain James T. Kirk actually destroyed a number of computers just by talking to them. That’s why I always thought Shatner was an odd choice as Commodore’s pitchman. In the ad below, he’s promoting the Vic-20:

Commodore Amiga: Tommy Lasorda, the Pointer Sisters, NASA Astronauts and Thomas “Tip” O’Neil

This is probably the most celebrity-laden ad I’ve ever seen for a computer, the woefully under-appreciated Commodore Amiga:

Bill Cosby: Texas Instruments TI 99/4

Here’s Bill Cosby, who was the spokesperson for Texas Instrument’s incredibly lame TI 99/4:

George Plimpton: Mattel Intellivision

Bak in the early 1980s, we had the first console war: the Atari VCS (later renamed the Atari 2600) versus Mattel Intellivision. Atari had an unknown — a nerdy blond kid with big glasses — as their spokesperson. Mattel went with a celebrity: George Plimpton.

While the Intellivision’s better graphics and sound made it a much better console for sports games, Atari had the far better gameplay, especially for arcade games. Star Strike, which Plimpton hawks in the video below, was far less fun than Asteroids, even if it featured “the total destruction of a planet”:

Finally, here’s an Plimpton ad that gets downright creepy at the end. It features Henry Thomas (he played “Elliott” in E. T. and was a big star at the time), who’s about to make the classic “Oh, let’s get in the playground candyman’s van…he seems legit!” mistake…

Matthew Perry and Jennifer Aniston: Windows 95 Training

Although this isn’t an ad but a training video, it’s still got considerable late-’90s star power in the form of Matthew Perry and Jennifer Aniston from Friends. This features the painful line: “Taskbar? Is that like a Snickers bar?”

Here’s part one:

and here’s part two:

Hewlett-Packard’s Ads

And finally, celebrity ads for half-decent computers (I’ve generally had good experiences with HP machines, and not just the printers).

Here’s Mark Cuban (good friend of my former employer, Tucows):

Vera Wang also did an ad:

Tennis star Serena Williams:

Pop star Gwen Stefani, who should get bonus points for the use of the word “mash-up”:

Jay-Z:

and finally, Pharrell:

John Cleese: Compaq

Back in the early 1980s, Compaq was synonymous with “portable computer”. I remember being stunned that you could actually carry a computer around! I also remember being stunned that John Cleese was doing ads for them.

Here’s Cleese asking the most important question about portable computers: “Does it have a handle?”

“We don’t need a portable. We have Bruno”:

This one’s an ad for the Compaq III that was only shown in the U.K.:

This one targets “that trendy computer” — the original Macintosh. Guess which company is still around?

In which he compares the Portable II to a fish:

Forget about our earlier commercials about portable computers, we make desktops now!

In case you’re not sure how to spell “Compaq”:

“How could a computer be made from three hundred and eighty six chips and 32 bits from a bus?”

The “Trust the well known name” ad is very Pythonesque:

Here’s one for the Compaq DeskPro: “70 megabytes. 8 mega-hertz. Two hundred and eighty-six chips. Dual-mode monitor.”

Here’s another one where he uses the “three hundred and eighty six chips and 32 bits of a bus” line:

“The decision stank”:

“I need a vaction!”

“Three cheers for it!”

Again with “three hundred and eighty six chips and 32 bits of a bus” gag:

He wants 1 million pounds in ransom from IBM:

This one plays on the old adage “Nobody ever got fired for buying IBM”:

In this one, he’s talking about the new Compaq plant in Glasgow:

And finally, an internal promo video for Compaq UK’s dealers:

Intel Centrino: John Cleese, Tony Hawk and Seal

It could be the opening line to a joke: “John Cleese, Tony Hawk and Seal walk into a commercial…”

Prime Computer: Tom “Doctor Who” Baker

Tom Baker played one of my favorite incarnations of Doctor Who; he also shilled for Prime Computer. Here he is with Lalla Ward, who played “Romana” on Doctor Who:

Apple

Here’s an old one for the Lisa (the predecessor to the Mac) featuring Kevin Costner:

Apple’s had a few celebrities in recent ads. Here’s an “I’m a Mac / I’m a PC” one with Gisele Bundchen:

This one features Judy Greer as the cute-but-unstable yoga instructor:

I think HAL 9000 is enough of a celebrity to count, don’t you?

Nintendo DS

Why is Captain Picard Starfleet’s greatest strategist? Because of Nintendo brain training! Here’s Patrick Stewart and Julie Walters with a DS:

Here’s Nicole Kidman keeping her brain sharp:

Liv Tyler:

America Ferrera:

Olivia Newton-John:

Carrie Underwood:

Australian comedian Hamish Blake:

Microsoft UK: Ricky Gervais and Stephen Merchant (The Office, the UK Version)

Here’s a four-parter featuring Ricky Gervais and Stephen Merchant in their The Office characters starring in a Microsoft UK training video titled The Office Values:

IBM: Avery Brooks

We’ve had Kirk and Picard…why not Sisko? Here’s Avery Brooks’ ads for IBM. The “Where are the Flying Cars?” ad struck a chord with a number of friends:

Here’s another one, “Epiphany”:

And here’s one on Linux:

Atari “XL” Series Computers

In those “pre-internet” days, there were considerably fewer uses for computers. As a result, there semmed to be many more ads for the computer as an educational tool than today. Here’s Alan Alda talking about how his Atari XL computer is teaching him Italian:

Here’s one demonstrating Typing Attack, a videogame that teaches touch typing. There were a number of apps like that back then:

Here’s an ad featuring “Atari Writer”, Atari’s word processing package. You have to keep in mind that at this point in time, many people still used typewriters:

IBM: The Cast of M*A*S*H

Alan Alda didn’t just do ads for Atari, he also appeared in an IBM commercial, and so did some of his castmates from M*A*S*H. The video below features two ads: Jamie Farr is in the ad for the PS/2 series of computers, and Alan Alda, Harry Morgan and Gary Burghoff are in the ad for the AS/400 series.

{ 28 comments }

Enumerating Enumerable: Enumerable#grep

by Joey deVilla on August 21, 2008

Enumerating Enumerable

Once again, it’s Enumerating Enumerable time! This is the latest in my series of articles where I set out to make better documentation for Ruby’s Enumerable module than Ruby-Doc.org’s. In this installment, I cover the grep method.

In case you missed any of the previous articles, they’re listed and linked below:

  1. all?
  2. any?
  3. collect / map
  4. count
  5. cycle
  6. detect / find
  7. drop
  8. drop_while
  9. each_cons
  10. each_slice
  11. each_with_index
  12. entries / to_a
  13. find_all / select
  14. find_index
  15. first

Enumerable#first Quick Summary

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

In the simplest possible terms Which items in the collection are a === match for a given value?
Ruby version 1.8 and 1.9
Expects
  • An argument against which every object in the collection will be compared using the === operator.
  • (Optional) A block to be used in a map operation on the resulting array.
Returns
  • If no block is given, an array containing the items in the collection that were a === for the given argument.
  • If a block is given, an array containing the items in the collection that were a === for the given argument, which is then mapped using the block.
RubyDoc.org’s entry Enumerable#grep

Enumerable#grep, Regular Expressions and Arrays

The grep method’s name implies regular expressions, and that’s one of its uses. When given a regular expression as an argument and used without a block, grep returns an array containing the items in the original array that match the given regular expression.

# Here's a list of countries, some of them with "stan" in their names.
#
# I'm including Stan Lee, creator of many wonderful superhero comics simply because
# he's cool enough to be his own country.
countries = ["Afghanistan", "Burkina Faso", "Kazakhstan", "France", "Tajikistan",
"Iceland", "Uzbekistan", "Australia", "Stan Lee"]
=> ["Afghanistan", "Burkina Faso", "Kazakhstan", "France", "Tajikistan",
"Iceland", "Uzbekistan", "Australia", "Stan Lee"]

# Which countries have the string "stan" in their names?
countries.grep(/stan/)
=> ["Afghanistan", "Kazakhstan", "Tajikistan", "Uzbekistan"]

# Note that "Stan Lee" wasn't included in that list. "Stan" and "stan" aren't the
# same thing, but that's easy to fix:
countries.grep(/[S|s]tan/)
=> ["Afghanistan", "Kazakhstan", "Tajikistan", "Uzbekistan", "Stan Lee"]

When a block is used with grep, the contents of the result array are passed through the block and the resulting array is returned. Think of it as grep followed by a collect/map operation.

# Let's get a look at those countries with "Stan" and "stan" in their names again:
countries.grep(/[S|s]tan/)
=> ["Afghanistan", "Kazakhstan", "Tajikistan", "Uzbekistan", "Stan Lee"]

# Let's get the lengths of the names of those countries:
countries.grep(/[S|s]tan/) {|country| country.length}
=> [11, 10, 10, 10, 8]

# It's a slightly shorter version of this:
countries.grep(/[S|s]tan/).map {|country| country.length}
=> [11, 10, 10, 10, 8]

# This time, let's find all the "stans" and uppercase them
countries.grep(/[S|s]tan/) {|country| country.upcase}
=> ["AFGHANISTAN", "KAZAKHSTAN", "TAJIKISTAN", "UZBEKISTAN", "STAN LEE"]

# And here's the version that uses map:
countries.grep(/[S|s]tan/).map {|country| country.upcase}
=> ["AFGHANISTAN", "KAZAKHSTAN", "TAJIKISTAN", "UZBEKISTAN", "STAN LEE"]

What Enumerable#grep Really Does: The === Operator

Here’s grep‘s secret: what it actually does is take each item in the array, compares it against the given argument using Ruby’s === (the “triple equals”) operator and returns an array of those items in the original array for which the comparison returns true.

For regular expressions, the === operator is grep-like. The expression r === s operator returns true if there is a match for regular expression r in string s.

Different classes implement === differently. For example, in the Range class, === is used to see if an item is within the range. The expression r === x returns true if x is in range r. Here’s grep in action when its argument is a range:

# These are the years when the band Radiohead released an album
radiohead_album_years = [1993, 1995, 1997, 2000, 2003, 2007]
=> [1993, 1995, 1997, 2000, 2003, 2007]

# And these are the years when Radiohead released an album between 1996 and
# 2002 inclusive
radiohead_album_years.grep((1996..2002))
=> [1997, 2000]

Generally speaking, collection.grep(thing_to_compare) compares thing_to_compare with each item in collection using the === operator as defined for thing_to_compare‘s class. It returns an array of those items in the original array for which the comparison returned true.

Don’t forget the extra processing — a map operation — comes “free” if you provide grep with a block:

radiohead_album_years = [1993, 1995, 1997, 2000, 2003, 2007]
=> [1993, 1995, 1997, 2000, 2003, 2007]

# Adding a block performs a map operation on grep's initial results
radiohead_album_years.grep((1996..2002)) {|year| year % 2 == 1 ? "odd" : "even" }
=> ["odd", "even"]

Enumerable#grep and Hashes

I’ll put it simply: Enumerable#grep isn’t terribly useful with hashes. Like most methods of Enumerable, when applied to a hash, grep, as it iterates through the hash, converts each key-value pair into a two-element array where the first element is the key and the second element is the corresponding value.

As I mentioned earlier, grep uses the === operator to do its comparison, and for arrays, === returns true only when comparing identical arrays:

# Identical arrays
[1, 2] === [1, 2]
=> true

# How about the first array as a subset of the second?
[1] === [1, 2]
=> false

# How about the first array as a superset of the second?
[1, 2, 3] === [1, 2]
=> false

# How about one array as a permutation of the other?
[2, 1] === [1, 2]
=> false

The practical upshot of all this is that for hashes, grep will return the empty array [] for most arguments, with the notable exception of an argument that is a two-dimensional array that corresponds to one of the key-value pairs in the hash.

That was a bit wordy, but an example should clear things right up:

# These are countries and their total areas (not counting outside territories)
# in square kilometres.
total_country_areas = {"Afghanistan"  => 647_500,
                       "Burkina Faso" => 274_200,
                       "Kazakhstan"   => 2_717_300,
                       "France"       => 547_030}
=> {"Afghanistan"=>647500, "Burkina Faso"=>274200, "Kazakhstan"=>2717300, "France"=>547030}

# Is there a '"Burkina Faso" => 274200' item in the hash?
total_country_areas.grep(["Burkina Faso", 274_200])
=> [["Burkina Faso", 274200]]

# That worked because the array argument we provided was an exact match
# for one of the items in the hash when it is converted into an array.

# Is there a '"Burkina Faso" => 0' item in the hash?
total_country_areas.grep(["Burkina Faso", 0])
=> []

# That didn't work because the array argument didn't correspond to any of the items
# in the hash.

Making Hashes grep-able

If you need to find which keys in a hatch pattern-match a given value, use the Hash#keys method (which returns an array of the hash’s keys) and grep that:

# Again with the countries and the areas...
total_country_areas = {"Afghanistan"  => 647_500,
                       "Burkina Faso" => 274_200,
                       "Kazakhstan"   => 2_717_300,
                       "France"       => 547_030}
=> {"Afghanistan"=>647500, "Burkina Faso"=>274200, "Kazakhstan"=>2717300, "France"=>547030}

# Which ones are the "stans"?
total_country_areas.keys.grep(/stan/)
=> ["Afghanistan", "Kazakhstan"]

If you need to-find which values in a hatch pattern-match a given value, use the Hash#values method (which returns an array of the hash’s values) and grep that:

# Of the countries' total areas, which the ones between
# 500,000 and 1 million square km?
total_country_areas.values.grep((500_000..1_000_000))
=> [647500, 547030]

What if you want to find key-value pairs where either the key or the value is a === match for a given argument? There’s a way to do that, and I’ll cover it when we get to the Enumerable#inject method. It’ll be soon, I promise!

{ 0 comments }

M-Audio Axiom 25 USB MIDI keyboard
My toy: M-Audio Axiom 25 USB MIDI keyboard

For my 40th birthday, the Ginger Ninja got me something I’d had my eye on for some time: a USB MIDI keyboard, specifically an M-Audio Axiom 25, a nice little unit with a lot of features. Prior to my picking up the accordion and getting the “Accordion Guy” nickname, I was a synth player for a good long time. I’ve been meaning to get back into it.

I still have a couple of old hardware synths: a Korg Wavestation A/D (a rackmount unit version of the Korg Wavestation) from my days at Crazy Go Nuts University and a Korg Poly-800 that my friend Steph gave to me when she moved out of town.

My last experience was software synths wasn’t all that hot: it was in the late 1990s, when computers and networking were a great deal slower. Software synths felt very “laggy” in comparison to my good ol’ reliable hardware, and after noodling with them for a while, I decided that I’d give technology some time to play catch-up. That time has come, and I’d like to ask any of you who are familiar with this stuff: what are your favorite software synths, samplers and sound modules?

I’m looking for a couple of things in software form:

  • A nice, decent general purpose synth/sampler. I expect I’ll be doing more sequencing than live performance, but you never know…
  • A “groove builder” or “Groovebox” in the spirit of the Roland MC-303

I’m currently on a PC laptop (running Ubuntu and when absolutely necessary, Vista), but I expect to buy a Macbook Pro sometime in the near future. I’d like to hear about what’s available for any platform. Let me know in the comments!

{ 2 comments }

The Way Computers Were in the Seventies

by Joey deVilla on August 18, 2008

Inspired by my earlier post on the Accordion Guy blog titled The Way Movies Were in the Seventies, I present to you this image showing the way computers were in the seventies:

The way computers were in the seventies: "A small digital computer designed for the businessman" and "a large computer installation"
Illustrations courtesy of Miss Fipi Lele.

{ 0 comments }

Great Showdowns (of the 8-bit Era)

by Joey deVilla on August 17, 2008

Can you identify the ’80s-era games depicted in Scott Campbell’s piece, Great Showdowns (of the 8-bit Era)?

Great showdowns of the 8-bit era

{ 0 comments }

My Stack of Old Computer Books

by Joey deVilla on August 16, 2008

While cleaning out my home office, I found a box books that I’ve been hanging on to for historical purposes and sentimental reasons.

First, this collection of Apple ][ manuals, back from when I had my first computer, an Apple //e. These manuals came with the original apple ][; my //e manuals must be kicking around somewhere...

Apple ][ Manuals

And from my university days, these books: the Adele Goldberg Smalltalk-80 series, Computer Systems in Business, which is rather quaint when read with today’s eyes, and Inside Macintosh from the System 7/8 era:

Smalltalk-80 books, "Computer Systems in Business", Inside Macintosh books

I know I’ve got Lubomir Bic’s The Logical Design of Operating Systems — from which I learned concurrent programming — stashed away, but I can’t seem to find it at the moment.

{ 0 comments }