From: cle@... (Clemens Hintze) Date: 2000-10-13T16:41:22+09:00 Subject: [ruby-talk:5500] Re: Some newbye question In article , Davide Marchignoli wrote: (...) >In FAQ 2.2 the following code is used as example for: > >a = 0 >for i in 1..3 do > a += i > b = i*i >end >print a, b (...) >Even if both a and b remain accessible after the block. Do you mean, why b remains accessible? You are stumbled about the fact that the 'do' above is not introducing a new block but is syntactical (optional) part of the 'for' construct: 'for' ... ['do'] ... 'end' As in your example you are not dealing with blocks at all, no block variable exists ;-) If you would do this instead: def myfor(range,&block) range.each &block end a = 0 myfor 1..3 do |i| a += i b = i*i end print a, b You will find REAL blocks to be involved. Therefore 'b' is not accessible after leaving the block. >So when does a block create a new scope? Every time a new local variable is created (means first-time assigned) a new scope was introduced, and the new variable will vanish if the block is left. >Which is the rationale of the fact that block variables are non-binding >if some variable with the same name already exists ? Isn't it confusing? Yes and no (or jein!, as we germans would say ;-) Try to see it like this: THERE ARE NO BLOCKS IN RUBY! :-) A block is only a syntactic element to describe Ruby's structure. If we are speaking about blocks, we really are speaking about code + execution contexts (aka closures). These closures may be objectified (via lambda, proc or Proc.new) or not. If you buy this, you will agree that it makes sense that code in a context is able to access the variables valid in that context, isn't it? As a nice add-on, matz has chosen to make variables, new created in that context, local to it. This is a very nice feature, as code should not depend on a variable created by a certain context! Why? Well, it may be that the context is never executed hence the variable does not exist in the end. What will the surrounding context be supposed to do then? >What is supposed to do the following fragment of code? > >a = 1 ; x = 1 ; f = proc {|a| a += 1} >f.call(x) 'a' will not be created in the closure (did you recognize, I didn't call it block? ;-) but used from the surrounding context. Due to the '|a|' construct, the argument passed to the closure will be bound to 'a' modifiying the variable of the surrounding context therefore. Note: '|'...'|' does not CREATE variables, but only MARK them to be used as parameters. During binding, if some variable didn't exist, they will be created, of course, hence are local to the closure! >Why the two following (admittedly contrived) computations give different >results ? > >a = 1 ; x = 1 ; f = proc {|a| a += 1} >f.call(x) >f.call(a) >a # results in 2 > >a = 1 ; x = 1 ; f = proc {|a| a += 1} >f.call(a) >f.call(x) >a # results in 3 Oops ... I would guess the results should be vice versa ... Let me look ... yes! It seems you have exchanged the results. The top one should result in '3' and the bottom one in '2'. But coming to your question. If you take may words from above it will very clear to you :-) First example: - x (=1) is passed to the closure. 'a' is marked to be used as argument. Hence it is bind to the value of 'x' => 1 - Now a += 1 is executed => 'a' is now 2. - a (=2) is passed to the closure. 'a' will be bound to 2. - Now a += 1 is executed => 'a' is now 3. Second example: - a (=1) is passed to the closure. 'a' is marked to be used as argument. Hence it is bind to the value of 'a' => 1 - Now a += 1 is executed => 'a' is now 2. - x (=1) is passed to the closure. 'a' will be bound to 1. - Now a += 1 is executed => 'a' is now 2. All clarities removed? :-) >Are the following statement equivalent? > >p() if (b1 and b2) >p() if (b1 && b2) No! They have different precedence, AFAIK. But they are supposed to do the same, yes. (...) >Sorry for the length of this mail and thanks in advance for any possible >answer. I hope my explanations could help you a bit. > Davide Marchignoli \cle -- Clemens Hintze mailto: c.hintze@gmx.net