Replace words using gsub

New to ruby! Body is a string, i am using the code directly below. I am
not quite understand what does |k| and K means. This code shows the
error "undefined method `default_proc=' for {"up"=>"down", "in"=>"out",
"you"=>"he"}:Hash (NoMethodError)". Could someone help me out?

subs = {
    "you" => "he",
    "up" => "down",
    "in" => "out"}

subs.default_proc = proc {|k| k}
body.gsub(/(?=\b).+(?=\b)/, subs)

···

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

The k is an iterator. Let's use another example here to demonstrate:

array = [1,2,3]
array.each{ |i| puts i * i }

The iterator is put in i (it could be foobar for all Ruby cares, as long as
the name is consistant.) The first time the block of code is executed, i is
set to 1 and prints 1, then is set to 2 and prints 4, then is set to 3 and
prints 9. What you are doing is passing each element to an anonymous
function called a block, which comes from some functional type programming
with Lambda.

Now on to the other part, I assume you know what a hash is already, if not
check the docs for Ruby (very very useful.)

Let's say we have string:
string = "you up in there"

...and subs as you specified it. We need to iterate through the subs hash,
so we do as so:
subs.each_pair{ |k, v| string.gsub!(k,v) }

...but why are there TWO iterators there? Who said there was a limit? You
could probably (impractically) jam a number of them in there. In this case
we use each_pair, which returns a key and a value (hence k, v) that we use
for substitution. You will notice that I use the gsub! method instead of
gsub, as gsub returns a new string instead of modifying the one in place.
Do note that in functional programming it is frowned upon, which is why
there's a ! at the end of the method indicating it modifies the object.
There are ways to prevent side effects which may very well lead to cleaner
code, and it will be worthwhile to look into this.

Really, if I were you I would get intimately familiar with the Ruby docs,
especially Enumerable. Learning how to properly learn blocks, procs, and
lambdas is what tends to be a graduating point into more advanced code and
as such would be good to look into as well. Try out
http://www.rubymonk.comas well later, it should help.

Cheers

···

On Thu, Jul 25, 2013 at 10:56 PM, noterrain mee <lists@ruby-forum.com>wrote:

New to ruby! Body is a string, i am using the code directly below. I am
not quite understand what does |k| and K means. This code shows the
error "undefined method `default_proc=' for {"up"=>"down", "in"=>"out",
"you"=>"he"}:Hash (NoMethodError)". Could someone help me out?

subs = {
    "you" => "he",
    "up" => "down",
    "in" => "out"}

subs.default_proc = proc {|k| k}
body.gsub(/(?=\b).+(?=\b)/, subs)

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

The k is an iterator. Let's use another example here to demonstrate:

k is not an iterator but takes on every iterated value. The iterator is the
piece of code which is driving this behind the scenes.

This article gives a good overview:
https://www.informit.com/articles/article.aspx?p=1398604

array = [1,2,3]
array.each{ |i| puts i * i }

The iterator is put in i (it could be foobar for all Ruby cares, as long
as the name is consistant.) The first time the block of code is executed, i
is set to 1 and prints 1, then is set to 2 and prints 4, then is set to 3
and prints 9. What you are doing is passing each element to an anonymous
function called a block, which comes from some functional type programming
with Lambda.

Right.

Now on to the other part, I assume you know what a hash is already, if not
check the docs for Ruby (very very useful.)

Let's say we have string:
string = "you up in there"

...and subs as you specified it. We need to iterate through the subs hash,
so we do as so:
subs.each_pair{ |k, v| string.gsub!(k,v) }

Why? The original code did not do this.

...but why are there TWO iterators there? Who said there was a limit? You
could probably (impractically) jam a number of them in there. In this case
we use each_pair, which returns a key and a value (hence k, v) that we use
for substitution. You will notice that I use the gsub! method instead of
gsub, as gsub returns a new string instead of modifying the one in place.
Do note that in functional programming it is frowned upon, which is why
there's a ! at the end of the method indicating it modifies the object.
There are ways to prevent side effects which may very well lead to cleaner
code, and it will be worthwhile to look into this.

Actually Matz's reasoning about the exclamation mark is different: methods
which are potentially "dangerous" get an exclamation mark. For example,
Kernel#exit! does not have the sort of side effects that String#gsub has
but gets an exclamation mark nevertheless.

Really, if I were you I would get intimately familiar with the Ruby docs,
especially Enumerable. Learning how to properly learn blocks, procs, and
lambdas is what tends to be a graduating point into more advanced code and
as such would be good to look into as well. Try out
http://www.rubymonk.com as well later, it should help.

That is excellent advice.

To the original code:

subs = {
    "you" => "he",
    "up" => "down",
    "in" => "out"}

subs.default_proc = proc {|k| k}
body.gsub(/(?=\b).+(?=\b)/, subs)

This does not work - at least not in the intended way. What this does is it
will replace all occurrences of the regexp with the string representation
of "subs":

irb(main):018:0> body = "foo bar"
=> "foo bar"
irb(main):019:0> body.gsub(/(?=\b).+(?=\b)/, subs)
=> "{\"you\"=>\"he\", \"up\"=>\"down\", \"in\"=>\"out\"}"

There are several problems here:

1. the regexp does not match words but arbitrary long sequences of words.
2. the default proc uses the first argument which happens to be the Hash
3. the string replacement as indicated above.

Here's a more appropriate version

irb(main):026:0> subs.default_proc = lambda {|h,k| k}
=> #<Proc:0x8022628c@(irb):26 (lambda)>
irb(main):027:0> body.gsub(/\w+/) {|m| subs[m]}
=> "foo bar"
irb(main):028:0> body = "I am you"
=> "I am you"
irb(main):029:0> body.gsub(/\w+/) {|m| subs[m]}
=> "I am he"

Kind regards

robert

···

On Fri, Jul 26, 2013 at 7:07 AM, Brandon Weaver <keystonelemur@gmail.com>wrote:

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

> body.gsub(/\w+/) {|m| subs[m]}
=> "I am he"

forgot the original : )

body.gsub(/\w+/,subs)

=> "I am he."

···

On Fri, Jul 26, 2013 at 2:34 PM, Robert Klemme <shortcutter@googlemail.com> wrote:

> > body.gsub(/\w+/) {|m| subs[m]}
> => "I am he"

forgot the original : )

What are you trying to say?

> body.gsub(/\w+/,subs)
=> "I am he."

I do not see that with Ruby 1.9* (see above). Is this Ruby 2.0 behavior?

Cheers

robert

···

On Fri, Jul 26, 2013 at 12:56 PM, botp <botpena@gmail.com> wrote:

On Fri, Jul 26, 2013 at 2:34 PM, Robert Klemme > <shortcutter@googlemail.com> wrote:

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

yes. i thought you just forgot to post it. but never mind, your code
works in all versions.

best regards -botp

···

On Fri, Jul 26, 2013 at 7:36 PM, Robert Klemme <shortcutter@googlemail.com> wrote:

Is this Ruby 2.0 behavior?