Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Tools
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker

Monthly Archives: November 2008

Adam Milligan

Functional witness protection

Adam Milligan
Tuesday, November 11, 2008

I wrote a bit about function objects here. However, if you don’t buy that the persistent state of function objects provides something that anonymous functions cannot, how about this: readability. In some cases.

Anonymous functions are boss and cool, and extremely common in idiomatic Ruby. However, in some cases they can get a little… esoteric. Consider:

people.sort do |lhs, rhs|
  lhs, rhs = rhs, lhs if ascending?
  result = lhs.name <=> rhs.name
  if result == 0
    result = lhs.date_of_birth <=> rhs.date_of_birth
  end

 # etc...
end

Sometimes, anonymity isn’t the answer. Consider:

class ByNameAscending
  def self.to_proc
    Proc.new { |lhs, rhs| rhs.name <=> lhs.name }
  end
end

This allows you to write this:

people.sort(&ByNameAscending)

Or, to push the example to the extreme:

class SortOrder
  def initialize(direction = :descending)
    @direction = direction
  end

  def by(attribute)
    attributes << attribute
    self
  end
  alias_method :and, :by

  def to_proc
    Proc.new do |lhs, rhs|
      lhs, rhs = rhs, lhs if ascending?

      return lhs <=> rhs if attributes.empty?
      attributes.each do |attribute|
        result = lhs.send(attribute) <=> rhs.send(attribute)
        return result if result != 0
      end

      0
    end
  end

private
  def attributes
    @attributes ||= []
  end

  def ascending?
    @direction == :ascending
  end
end

def ascending; SortOrder.new(:ascending); end

Which gives us:

people.sort(&ascending.by(:name).and(:date_of_birth))

A DSL for generating sort order function objects. It could be useful.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Adam Milligan

Give up the func

Adam Milligan
Monday, November 10, 2008

I’ve been a C++ developer ever since I discovered the language in the early 90′s and I realized that my beloved Pascal had nothing on objects. I’ve spent plenty of time working with other languages, of course, and over the past year or so I’ve written almost exclusively Ruby. But, one thing I’ve missed about C++ is the ease with which you can make objects act like functions.

In case your C++ is a little rusty, here’s an example:

class Fibonacci {
public:
  Fibonacci(): n1_(1), n2_(1) {}

  int operator()() {
    int result = n1_;
    n1_ = n2_;
    n2_ = result + n2_;

    return result;
  }

private:
  int n1_, n2_;
};

What you’re looking at there is an overload of the function call operator. No, I’m not kidding; that will compile and run. Instances of the Fibonacci class are called function objects, or functors.

Now, you’re wondering to yourself why anyone would care. The answer is, this function can now carry state around with it:

Fibonacci fibonacci;
fibonacci();  // 1
fibonacci();  // 1
fibonacci();  // 2
Fibonacci()();  // 1

vector<int> v(5);
generate(v.begin(), v.end(), Fibonnaci());  // [1, 1, 2, 3, 5]
generate(v.begin(), v.end(), fibonnaci);  // [3, 5, 8, 13, 21]

This may not seem particularly compelling for generating Fibonnaci numbers, but consider generators that may carry more complex state, or references to state owned by other objects. Consumers can also set initial state, such as a seed value for a random number generator, via the ctor.

Also, consider the generate method above. It expects a third parameter that supports function call semantics with arity of zero. And nothing else. That parameter could be a function pointer (should you desire statelessness and impenetrable syntax), a functor of any type, or anything else that supports operator (). That’s duck-typing, my friends. In a statically-typed language. Dogs and cats sleeping together, and all that.

Again, you cry, why would anyone care? Well, blocks in Ruby carry around the state of the context in which they were created, but sometimes you want more. For instance, if you pass your Proc object around your code may be clearer with the state explicitly encapsulated. The initial state may simply not make sense as local variables when you create the Proc. You may want to save some secondary value that a consumer can query the functor for (how many Fibonacci numbers has this generator generated). Or, perhaps you want consumers to be able to mutate the state in some way.

In any case, this functor approach wacked me over the head recently while I was looking at some code that used the Rails Symbol#to_proc. We all know that Rails adds voodoo to symbols so that

User.find(:all).collect(&:name)

is equivalent to

User.find(:all).collect { |u| u.name }

And, we all know that this works because the & operator, when applied to an object in a parameter list, will implicitly call #to_proc on that object and then convert the result to a block. This is vanilla Ruby functionality, Rails just adds #to_proc to the Symbol class.

So, duh. Check it out:

class Fibonacci
  def initialize
    @n1 = @n2 = 1
  end

  def to_proc
    @proc ||= Proc.new do
      result = @n1
      @n1, @n2 = @n2, @n1 + @n2
      result
    end
  end
end

fibonacci = Fibonacci.new
fibonacci.call  # 1
fibonacci.call  # 1
fibonacci.call  # 2
Fibonacci.new.call  # 1

(1..5).collect(&Fibonacci.new)  # [1, 1, 2, 3, 5]
(1..5).collect(&fibonacci)  # [3, 5, 8, 13, 21]

VoilĂ , a functor. I’d love to hear from anyone who has used this technique to do something really cool.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joe Moore

Standup 11/07/2008: Selenium for Flash

Joe Moore
Friday, November 7, 2008

Interesting Things

  • Teaser: Selenium for Flash! We’ve developed a Selenium-like framework for Flash. It’s pre-alpha, and needs to be extracted from it’s current home inside a project. Are you interested in a Selenium-like framework for Flash, or have you written one yourself? Let us know!
  • STI-weirdness. Rails surprise of the day: given a query of a has_many :photos where Photos has STI subclasses (got that?) Rails will build a SQL query that includes the subclass types of Photo, which you might not want:

    foo.photos.find_by_type("Photo")
    # query will have "... WHERE type IN ('Photo', 'OriginalPhoto', 'ThumbnailPhoto')"
    
  • It appears that the retardase_inhibitor might not work with Rails 2.1.X due to fixes in ActionMailer.

  • JetBrains has been hard at work: they have released both a new Ruby plugin for IntelliJ, and a ruby-specific IDE (based on IntelliJ) named RubyMine.
  • Check out Pivot Jonathan’s wife’s art exhibit at Artist-Xchange Gallery in San Francisco, Friday 11/7 from 7-10pm:

    Artist-Xchange Gallery
    3169 16th Street
    San Francisco
    CA 94103

Ask for Help

“I want to create a custom launcher for Firefox 2 and Firefox 3 with different profiles. Perhaps the real question is how do we create a custom version of a Mac application launcher, passing in the arguments we need?”

… without having to invoke it on the command line every time.

“We’re trying to delete cookies in our Controller, but they keep appearing in the headers anyway.”

Suggestion: make sure you are specifying your URL paths and domains correctly.

“Why won’t our CSS and other assets load the first time when accessing an SSL-protected domain on Engine Yard?”

It’s most likely not Engine Yard or Firefox 3′s fault. More research needed.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 11/6/2008

Pivotal Labs
Thursday, November 6, 2008

Ask for Help

“console.log seems to be broken again in Firebug with 1.2.1?”

People have had some success with 1.3 beta. Get Firebug

“Suggestions for creating PDF’s in Ruby?”

  • PDF Writer
  • Prawn
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 11/5/2008

Pivotal Labs
Thursday, November 6, 2008

Interesting Things

  • RubyMine – JetBrains has a preview of their new Rails IDE, RubyMine. Presumably, it’s the same as IntelliJ without support for other languages and the Rails Plugin baked in. Feedback from Pivots thus far is that it’s definitely an early Alpha with lots of bugs and slow to load projects. It’s rumored to cost somewhat in the range of Textmate.

  • Solr text field stemming problem – When creating an index on a text field in solr, it can be set to stem fields (e.g., running => run, runs => run, etc.) to increase relevancy. Thus, when a query is performed for “run”, hits with “running”, “runs”, etc. will be found. However, if the query contains “running*” or “running~”, the results do not take into consideration any of the stemmed versions. The recommended solution is to stem the query on the client-side, thus “run*” or “run~”.

Ask for Help

“Rails 2.2 – has anyone heard any news? “

Some comments from Pivots:

  • An RC candidate is out but may or may not work with Polonium.
  • The new join syntax is cool, shallow routes are neat, internationalization is included.
  • Core bundle seems to work
  • Desert has problems due to class-loading changes.
  • The country selector has been pulled out to a plugin, apparently for political reasons.

More info can be found here.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joe Moore

Standup… and VOTE!

Joe Moore
Tuesday, November 4, 2008

Interesting Things

  • It’s election day! If you are taking the time to read this geeky blog, you better have voted!

Ask for Help

“Is there some order-dependency issue with `has_many_polymorphs?”

We have a test that passes in isolation, but fails when the whole file is run.

“Any advice to setting up Lucine to allow us to search for strings with special characters, such as ‘-’, without having to wrap them in quotes?”

We have some Lucine knowledge here but feel free to give us your suggestions as well.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

HAML

Monday, November 3, 2008 | Run time: 25:22

Felix M. and Aaron Peckham talk about HAML.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Devver

Monday, November 3, 2008 | Run time: 44:04

Ben Brinckerhoff and Dan Mayer talk about Devver, their cloud-based test acceleration platform.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Scrum

Monday, November 3, 2008 | Run time: 1:14:27

Christian Sepulveda gives an overview of the Scrum development process as it applies to software.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

New Relic

Monday, November 3, 2008 | Run time: 41:51

Lewis Cirne demos New Relic’s RPM, a real-time Rails performance monitoring and analysis tool.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (783)
  • rails (117)
  • testing (90)
  • ruby (86)
  • ruby on rails (71)
  • jobs (62)
  • javascript (59)
  • techtalk (44)
  • ironblogger (42)
  • rspec (39)
  • bloggerdome (34)
  • productivity (34)
  • activerecord (30)
  • rubymine (30)
  • git (29)
  • gogaruco (29)
  • nyc (27)
  • design (24)
  • mobile (23)
  • pivotal tracker (22)
  • process (21)
  • cucumber (21)
  • jasmine (19)
  • ios (18)
  • tracker ecosystem (17)
  • webos (17)
  • objective-c (17)
  • fun (16)
  • android (16)
  • palm (16)
  • ci (16)
  • "soft" ware (16)
  • bdd (15)
  • tdd (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • css (14)
  • gem (13)
  • mouse-free development (12)
  • selenium (12)
  • goruco (12)
  • bundler (12)
  • api (12)
  • keyboard (11)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
Subscribe to Community Feed
  1. ←
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Tools
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >