2010-09-27 25 views
3

J'ai essayé de faire un refactoring pour convertir chaque bloc en une injection, mais ça n'a pas marché et je ne comprends pas pourquoi.pourquoi mon rubis refacturé en utilisant injecter travail?

est ici le code qui fonctionne avant 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 

et voici mon refactor qui ne fonctionne pas:

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 

Lorsque je tente et exécuter la méthode refondus Je reçois

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

Si je comprends bien, il n'aime pas l'opérateur de référence de tableau sur le prof objet ile dans ma version refactorisée, ce qui implique que l'initialiseur passé à injecter ne fonctionne pas. Cette compréhension est-elle correcte? Et si oui, pourquoi pas?

Merci!

Répondre

3

La méthode []= retourne la valeur attribuée, la valeur de profile dans la prochaine itération sera 1 (car il est la valeur de la dernière itération). Afin d'obtenir le comportement que vous voulez, vous aurez à faire:

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 

ou

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 
+0

Ah ... * * évident front gifle avec le recul. +10 pour me présenter à Object # tap! –