khpeek khpeek - 6 months ago 14
Ruby Question

In Ruby, use a function defined within a method

As part of an exercise, I'm trying to implement the bubble sort algorithm in two different ways.

For the first part, I've implemented the bubble sort algorithm as an Array instance method as follows:

class Array
def bubble_sort!
sorted=false
until sorted
sorted=true
for i in (0...self.length-1)
if self[i]>self[i+1]
self[i],self[i+1]=self[i+1],self[i]
sorted=false
end
end
end
self
end
end


so that, for example,

[5,2,4].bubble_sort!


returns [2,4,5]. The next part of the exercise is to modify the method so that it takes a block to perform the comparison:

[1, 3, 5].bubble_sort! { |num1, num2| num1 <=> num2 } #sort ascending
[1, 3, 5].bubble_sort! { |num1, num2| num2 <=> num1 } #sort descending


In order to not repeat myself, I've tried to implement this as follows:

class Array
def bubble_sort!(&prc)
if block_given?
boolean_operator = Proc.new {|a,b| prc.call(a,b)==1}
else
boolean_operator = Proc.new {|a,b| a>b}
end

sorted=false
until sorted
sorted=true
for i in (0...self.length-1)
# if self[i]>self[i+1]
if boolean_operator(self[i],self[i+1])
self[i],self[i+1]=self[i+1],self[i]
sorted=false
end
end
end
self
end


However, if I try to test this with

p [5,2,4].bubble_sort! {|x,y| x<=>y}


I get the following error:

in `bubble_sort!': undefined method `boolean_operator' for [5, 2, 4]:Array (NoMethodError)


It seems like the "boolean_operator" is somehow not defined where it is invoked (also not if I remove the block in the input). I understand that Ruby doesn't have nested methods, but I thought that defining procs and lambdas within a method was possible?

Answer

The issue here is you're treating the variable you've defined as a Proc like it's a method (on the Array class, hence the NoMethodError). The proper way to call the proc is as follows:

boolean_operator.call(self[i],self[i+1])

Comments