Search code examples
rubyiteratorblockproc

using proc instead of block inside hash iterator


I wrote my own iterator for the class that I'm working on which extends hash.

The iterator that I wrote was achieved using blocks and now im trying to achieve the same exact thing using Proc. but I kinda don't know how to use it in this context! :(

def each_word
   rank=0
   self.sort_by{|k,v| v}.reverse.to_h.keys.each{ |key,abs, rel | yield rank+=1, 
   key,self[key], self.frequency(key) if block_given? }#iterate with aid block
end

and i would use it like this :

puts "Rang - Anzahl - Häufigkeit(%) - Wort"
obj1.each_word do |rank,word,abs ,rel|
  puts "#{rank}         #{abs}       #{rel}%        #{word} "
end

using Proc(not correct code)

problem is that i want to have the same code using Proc

def each_letter
  rank=0
  x=self.sort_by{|k,v| v}.reverse.to_h# this wont work but wrote it as helpless try
  my_proc=Proc new { |key,abs, rel | yield rank+=1, key,x[key], x.frequency(key) }
  my_proc.call()
end

I already looked up those pages

so what is the correct way to use the provided block using letters?!

Edit the Assignment text:

each_word iterate over the words found using the method and a block, starting with the most common word to the least common word. The block gets the word, the absolute and relative frequency passed.(which I assume I did correctly)

The letter statics each_letter It behaves similarly to each_word, but within the method, you should use a Proc instead of a block.


Solution

  • What your doing here in your attempt is wrapping yield with a Proc, but in reality you can replace yield with the Proc:

    def each_word(&proc)
       rank=0
       keys = self.sort_by{|k,v| v}.reverse.to_h.keys
       keys.each do |key, abs, rel|
         if proc
           proc.call(rank+=1, key,self[key], self.frequency(key))
         end
       end
    end
    

    What &proc does it take the block that is passed in (whether with do ... end or { ... } syntax) and converts it to a proc.

    To check whether a block was given, you would simply use if proc (whereas if you were using yield, you'd use block_given?). You could alternatively use proc&.call which is the safe navigation operator.

    By the way, you should probably change rank +=1 to rank + 1, there's no no point reassigning the variable's value here since it's not going to change the value in the hash anyway (numbers are immutable).