Another useful collection method? Enumerable#select_first

For a personal project I’m working on, I need to find out the smallest time period with more than 5 records. I essentially wrote this code:

period = [1.week, 1.month, 1.year].select_first do |period|
  Record.where("published_at >= ?", period.ago).count >= 5

only to find out that the select_first method doesn’t exist. So I wrote it:

module Enumerable
  def select_first(&predicate)
    self.each do |item|
      if yield(item)
        return item
    return nil

and then of course, I tested it:

require "test_helper"

require "enumerable_extensions"

class EnumerableTest  2 }

  should "select_first the first one" do
    assert_equal 1, [1, 2, 3, 4].select_first { |i| i >= 1 }

  should "select_first the last one" do
    assert_equal 4, [1, 2, 3, 4].select_first { |i| i >= 4 }

  should "select_first none" do
    assert_equal nil, [1, 2, 3, 4].select_first { |i| i >= 100 }

Formating strings in C#, like in Python

I like Python’s way to format strings because you can use it everywhere, it’s part of the strings. You can do

print("Welcome %s!" %

as you can do

Console.Writeln("Welcome {0}!", user.Name)

But then in Python you can also do

randomMethodThatTakesAString("Welcome %s!" %

In C# it gets trickier, because the call to Console.Writeln takes extra arguments for the string arguments, while RandomMethodThatTakesAString doesn’t. It just takes a string. So the only way to go is

RandomMethodThatTakesAString(String.Format("Welcome {0}!", user.Name))

which is ugly.

Thanfully C# 3.0 has extension methods, so I quickly wrote this method:

blah blah

and now I can write:

RandomMethodThatTakesAString("Welcome {0}".Args(user.Name))

which is more verbose that Python’s version, but equally nice in my eyes.

If you can understand why allowing the language to be extendable in one aspect was a win here, then you can understand why so many, me included, love Lisp that is extendable in every possible way.

Reviewed by Daniel Magliola. Thank you!

Update 2009-09-17: For those complaining that I didn’t show how I did it, here is the Args method:

public static class StringExtensions {
    public static string Args(this string str, params object[] args) {
        return String.Format(str, args);