My Thought on the "Pickaxe book" (from a Ruby novice)

I realize that I've biasedly presented these two issues as problems
with the ruby language. Well, I can do that because I'm too new to
know any better and I have yet to "see the light" on why this is a
good thing in contrast to all my experiences so far in life. From
my background, SCOPE is a flaw and non-strict pragmas is a
condition to be aware of when tracking bugs. But like I said, I'm
new.

There is quite an influx of programmers into the Ruby community and
to the
extent there is quite a bit of 'teaching' occuring on this
mailing list, I think it is great to get feedback like you provided.

Thank you. I'm very pleased I haven't gotten hate mail for my voice.
Very encouraging!!

Some of what you say is particular to the book vs. Ruby. But it is good
to know what is confusing people. Once you learn a concept it is
hard to
remember how you might have struggled to get there.

No doubt. Try using the book as a reference for teaching another
person(s) and it probably becomes clearer. This is similar to saying
out loud what you have written for a paper. If it sounds good to the
voice, it's probably ok in writing.

I'm curious if you could expand on the issue of 'scope' that you
mentioned.
Is it the lexical scoping of a block that surprised you or something
else?

This:
Variable Scope, pages 105 through 107
"any new locals created (in while, until, for) will be available
afterward"
I've never seen anything like this.
Anything that is declared (or implicitly declared in ruby) within a block
(conditional or loop) is always out-of-scope when you leave that block.

I'm also struggling the lack of what perl calls a strict pragma. It's
isn't has strictly typed as Java, it just prevents you from mistyping
variables.

···

On 1/20/2006, "Gary Wright" <at2002@mac.com> wrote:

On Jan 20, 2006, at 6:29 AM, Tom Allison wrote:

The terminology used in the Pickaxe can be inconsistent or ambiguous at
times. My copy is littered with my own notes written in the margin as
I said "Huh?" and then later figured out what was actually meant.

Here is my go at explaining it. It is long but I hope clear (and correct!).

The while, until, and for loop constructs don't create a new scope so,
from the point of view of local variables, these constructs don't change
the rules in any way. To the extent that other languages do introduce a new
variable scope via their looping constructs this may be unexpected but the
resulting behavior, I think, is readily understood once you realize that no
new scope is introduced by the while, until or for constructs. Conditionals
don't introduce new scopes either (if/unless/case), nor does a begin/end block.

Blocks *do* create a new scope and one that is somewhat different than people
expect. Since Enumerable#each and Kernel#loop are methods that accept blocks
it *seems* as those these looping constructs have special rules but it is
really the blocks that introduce the scoping issue not the methods. Any
method that accepts a block would introduce the same scoping issues, not just
the blocks associated with 'each' and 'loop'.

So what is special about blocks?

    a) local variables that are *created* in the block, *live* and *die* in the block.
       They are not visible outside the block.
    b) local variables that are visible when the block is defined are visible within the block
       when it executes (the block captures the lexical environment in which it is defined)
    c) block arguments behave like local variables, *not* like method arguments

Consider:

  a = 4
  [5].each { |x| puts a,x }
  puts a,x

a is visible when the block is defined (i.e. when each is called) so it is visible
when the block executes

x is *not* visible when the block is defined but as part of the calling
sequence, when each passes 5 to the block, x = 5 is executed. This 'defines'
the variable x within the block (since it didn't previously exist). This
is the behavior described in c) above. Since x was created in the block it
remains visible *only* in the block. When 'puts a,x' runs outside the block
x is undefined.

Now consider:

  a = 4
  x = 5
  [6].each { |x| puts a,x }
         puts a,x

The situation with a is unchanged in this example but is different for x.
Since x is visible when the block is defined, the assignment that is implicit
when the block is called, x = 6, simply changes the value of the existing variable x.
So, in this case, no new variable is created inside the block. Outside the block,
x is still visible and reflects any changes made while the block executed (because
the x in the block is the same as the x outside the block).

I think the thing that is most surprising about this behavior is that block arguments
behave like local variables and don't 'shadow' an identically named variable in the
enclosing scope.

Hope this helps. And if it doesn't then feel free to point out the un-helpful parts.

Gary Wright

···

On Jan 20, 2006, at 2:53 PM, Tom Allison wrote:

This:
Variable Scope, pages 105 through 107
"any new locals created (in while, until, for) will be available
afterward"
I've never seen anything like this.
Anything that is declared (or implicitly declared in ruby) within a block
(conditional or loop) is always out-of-scope when you leave that block.

gwtmp01@mac.com wrote:

This:
Variable Scope, pages 105 through 107
"any new locals created (in while, until, for) will be available
afterward"
I've never seen anything like this.
Anything that is declared (or implicitly declared in ruby) within a block
(conditional or loop) is always out-of-scope when you leave that block.

Hope this helps. And if it doesn't then feel free to point out the un-helpful parts.

I went over this and the sections in the Pragmatic book and have finally figured it out. And there are situations where it is convenient to have this non-traditional method of handling scope in loops.

I think it would be helpful if there was a specific example to help explain via code what this means and why it's "cool". I'm now half way to the "cool" camp on this one.

And yes, I misunderstood that '-w' didn't also address a strict pragma.
But I'm still thinking I can get myself into trouble. I haven't yet, but I'm rather paranoid. Hence my attraction to ruby because of it's security over Python.

···

On Jan 20, 2006, at 2:53 PM, Tom Allison wrote: