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

> 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


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