Why doesn't my cost-effective injectable ruby ​​work?

I tried to do some refactoring to convert each block into an injection, but it didn’t work, and I don’t understand why.

Here is the code that works before refactoring:

class String
  # Build the word profile for the given word. The word profile is an array of
  # 26 integers -- each integer is a count of the number of times each letter
  # appears in the word. 
  #
  def profile
    profile = Array.new(26) { 0 }
    self.downcase.split(//).each do |letter|
      # only process letters a-z
      profile[letter.ord - 'a'.ord] += 1 unless letter.ord > 'z'.ord
    end
    profile
  end
end

and here is my refactor that doesn't work:

class String
  # Build the word profile for the given word. The word profile is an array of
  # 26 integers -- each integer is a count of the number of times each letter
  # appears in the word. 
  #
  def profile
    self.downcase.split(//).inject(Array.new(26) {0}) do |profile, letter|
      # only process letters a-z
      profile[letter.ord - 'a'.ord] += 1 unless letter.ord > 'z'.ord 
    end
  end
end

When I try to execute a processed method, I get

`block in profile': undefined method `[]=' for 1:Fixnum (NoMethodError)

If I understand this correctly, he does not like the array reference operator in the profile object in my refactored version, which implies that the initializer passed to the injection does not work. Is this understanding correct? And if so, why not?

Thank!

+3
source share
1 answer

[]= , profile 1 ( ). , :

self.downcase.split(//).inject(Array.new(26) {0}) do |profile, letter|
  # only process letters a-z
  profile[letter.ord - 'a'.ord] += 1 unless letter.ord > 'z'.ord 
  profile
end

self.downcase.split(//).inject(Array.new(26) {0}) do |profile, letter|
  # only process letters a-z
  profile.tap { profile[letter.ord - 'a'.ord] += 1 unless letter.ord > 'z'.ord }
end
+3

Source: https://habr.com/ru/post/1766692/


All Articles