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?

···

--
Posted via http://www.ruby-forum.com/.

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

···

--
Posted via http://www.ruby-forum.com/.

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 Fri, Mar 26, 2010 at 3:49 AM, Derek Cannon <novellterminator@gmail.com> wrote:

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?

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

···

2010/3/26 Derek Cannon <novellterminator@gmail.com>:

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

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Derek Cannon 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.

···

--
Posted via http://www.ruby-forum.com/\.

Agreed. There's also

  require 'facets/enumerable/every'

  arr.every.gsub! /foo/, 'bar'

···

On Mar 26, 5:15 am, Robert Klemme <shortcut...@googlemail.com> wrote:

2010/3/26 Derek Cannon <novelltermina...@gmail.com>:

> 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

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".

Derek Cannon wrote:

Derek Cannon 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.
  
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

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.

···

--
Posted via http://www.ruby-forum.com/\.