I’m new to Ruby. I’m trying to add a method to the Array class that adds
the functionality of gsub! to arrays.
Looking around the internet, I found a keyword know as detect { } which
allows me to get the elements of the array. Testing it, I find the
following code:
class Array
def test
detect { |x| puts x}
end
end
…prints out all the elements in the array. However, when I try:
class Array
def gsub!(pattern, replacement)
detect { |x|
x.gsub!(pattern, replacement)
}
end
end
…the result is only a modification of the first element in the array.
For example, the following code:
x = [“Hello”, “there”, “world”, “how”, “are”, “you?”]
x.gsub!(/[aeiou]/, “_”)
puts x
detect (Iprefer find) will iterate the enumerable yielding each
element to the block until one returns true, and will return that
element:
[1,2,3,4].find {|i| i > 2} # => 3
In the first example you are calling puts in the block which always
returns null, so the detect never stops its iteration and it goes
through all the elements.
In your “real” code, you use gsub! in the block. gsub! returns the
modified string if it changed it, or nil if no replacement was made,
so you saw in your example that was stopping after the first element,
because it managed to change it with the replacement. As you have
discovered, you should use each to iterate through the full
enumerable.
? Frankly I’d rather use the latter form. Because otherwise you’ll
have to put a method in Array (or Enumerable for that matter) for every operation you want to apply to elements. Additionally, there
is another point: since you made Array#gsub! look like String#gsub!
this might confuse readers of the code - especially if someone picks
bad variable names like “a”.
? Frankly I’d rather use the latter form. Because otherwise you’ll
have to put a method in Array (or Enumerable for that matter) for every operation you want to apply to elements. Additionally, there
is another point: since you made Array#gsub! look like String#gsub!
this might confuse readers of the code - especially if someone picks
bad variable names like “a”.
Just out of curiosity, does anyone know how Ruby knows what “each” is
referring to in this case? It works as intended – I’m just curious as
to HOW.
If I understand your question correctly, “each” is being called on self,
which will be an instance of Array. “each” is already defined for Array,
and “gsub!” is just being added to the class.
In the example below, you expect meth2 to be able to call meth1. It is
analogous to the above.
class A
def meth1
puts “hi”
end
def meth2
meth1
end
end
A.new.meth2
-Justin
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.