Creating a gsub! method for Arrays

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

outputs only:
H_ll_
there
world
how
are
you?

Does anyone know what I’m doing wrong?

After playing around some more, I’ve found a solution.

For anyone who is interested, the following code works:

class Array
def gsub!(pattern, replacement)
each { |x|
x.gsub!(pattern, replacement)
}
end
end

On Fri, Mar 26, 2010 at 3:49 AM, Derek C.
[email protected] wrote:

end
end
there
world
how
are
you?

Does anyone know what I’m doing wrong?

http://ruby-doc.org/core/classes/Enumerable.html#M003123

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.

Jesus.

On Mar 26, 5:15 am, Robert K. [email protected] wrote:

 }

? 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”.

Agreed. There’s also

require ‘facets/enumerable/every’

arr.every.gsub! /foo/, ‘bar’

Agreed. There’s also

require ‘facets/enumerable/every’

arr.every.gsub! /foo/, ‘bar’

Ah, I like this way a lot. Thanks, I’ll be using it.

Derek C. wrote:

class Array
def gsub!(pattern, replacement)
each { |x|
x.gsub!(pattern, replacement)
}
end
end

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.

2010/3/26 Derek C. [email protected]:

end
What is the benefit of doing

arr.gsub! /foo/, ‘bar’

over

arr.each {|s| s.gsub! /foo/, ‘bar’}

? 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”.

Kind regards

robert

Derek C. wrote:

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