tags:

views:

87

answers:

2

Hi,

I'm new to Ruby and am trying to pass a sort_by lambda to a format method, like this:

sort_by_methods = [ lambda {|l, r| compare_by_gender_then_last_name(l, r)}, 
                    lambda {|l, r| compare_by_something_else(l, r)}, 
                    lambda {|l, r| compare_by_another(l, r)}]

formatted_output = ""
sort_by_methods.each do |sort_by|
   formatted_output << formatter.format(students) { sort_by }
end

The format method code looks something like:

def format(students, &sort_by)
   sorted_students = students.sort { |l, r| sort_by.call(l, r) } // error from this line
   sorted_students.each { |s| result << s.to_s << "\n" }
end

For some reason I am getting a interpreter complaint about the line in the above format method code (students.sort.....): "in sort': undefined method>' for # (NoMethodError)"

What am I doing wrong? I assume I have messed the syntax for passing lambdas around, but cant figure out how.

Thanks.

+2  A: 

First, I apologize if this doesn't work. I don't have a Ruby interpreter handy.

It might be better to pass the lambda as a parameter:

def format(students, sort_method)
    sorted_students = students.sort { |l, r| sort_method.call(l,r) }
    sorted_students.each { |s| result << s.to_s << "\n" }
end

Otherwise you're going to have to add parameters to your block and then yield to that block. The call would be something like:

formatted_output << formatter.format(students) { |l, r| sort_by(l, r) }

With a definition like:

def format(students)
    sorted_students = students.sort { |l, r| yield(l, r) }
    sorted_students.each { |s| result << s.to_s << "\n" }
end

The first solution seems clearer to me. The second uses an implicit block. An explicit block would make it a bit clearer.

gaustin
Alex Baranosky
I'm not sure I recall correctly, but you might need Ruby 1.9 in order to implicitly yield in a block.
gaustin
I'm using 1.9 !
Alex Baranosky
+3  A: 

The problem is in this line:

formatted_output << formatter.format(students) { sort_by }

format() gets called with a block that accepts no arguments and returns the +sort_by+ block. This is why, later sort_by.call(l, r) will flunk. The block doesn't accept any arguments.

If you change it like this, it should work:

formatted_output << formatter.format(students, &sort_by)

The special & syntax indicates that sort_by is a block, which gets passed like the { } notation.

zimbatm
worked like a charm :)
Alex Baranosky