Passing a block to a method recursively in ruby

def bubble_sort_by nums
  do_it_again = false
  nums[0...-1].each_with_index do |item, index|
    if yield(nums[index], nums[index + 1]) > 0
      nums[index], nums[index + 1] = nums[index + 1], nums[index]
      do_it_again = true
    end
  end
  bubble_sort_by nums if do_it_again
  nums
end

bubble_sort_by(["hi","hello","hey"]) do |left,right|
  right.length - left.length
end

      

The program sorts the bubbles based on the block. In this case, the block is sorted by length. So I am getting a local navigation error. Took me a little, but I figured it out. When I call a method recursively, I am not giving it a block. But how can I do this?

+3


source to share


2 answers


Passing the block is optional, but here, as you already figured out, you need you to make your recursive calls. You just pass the block as an additional parameter:



def bubble_sort_by nums, &comparator
  # ...
  bubble_sort_by nums, &comparator if do_it_again
  # ...
end

      

+4


source


yield + block_given solution is one-off, you cannot use it in recursive calls without explicitly passing & block or Proc (closure) as an argument, although it does give you better performance empirically.

Here is some dummy code (a custom version of the map function) to make recursive calls

passing Proc as normal object



def mymap(xs, f)
  if xs.empty? 
    [] 
  else
    hd, *tl = xs
    [f.call(hd)]+ mymap(tl,f)
  end  
end
mymap([1,2,3], lambda {|x| x*2})

      

transfer optinal & block

def mymmap(xs, &block)
  if xs.empty? 
    [] 
  else
    hd, *tl = xs
    [block.call(hd)]+ mymmap(tl, &block) #here yield(hd) will do as well
  end  
end
mymmap([1,2,3]){|x| 2*x} #notice the calling manner is different from the above 

      

0


source







All Articles