# While modifiers have a scoping bug?!

**URL:** <https://www.ruby-forum.com/t/while-modifiers-have-a-scoping-bug/96434>\
**Category:** Ruby\
**Created:** [June 28, 2006, 7:36pm UTC](https://www.ruby-forum.com/t/while-modifiers-have-a-scoping-bug/96434 "2006-06-28T19:36:20Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![beev](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/b38774/32.png) [@beev](https://www.ruby-forum.com/u/beev)\
**Post date:** [June 28, 2006, 7:36pm UTC](https://www.ruby-forum.com/t/while-modifiers-have-a-scoping-bug/96434/1 "2006-06-28T19:36:20Z")

</div>

irb\> puts(line) while line = gets  
this is test line  
[EOF]  
NameError: undefined local variable or method `line’ for main:Object  
from (irb):1

The Pickaxe says on page 354 that unless the expression (on the left of  
the while) is not a block, then the loop gets executed ZERO or more  
times. So it has to evaluate the condition BEFORE the expression, which  
ought to assign a value to “line” (thus defining it).

This will work, but shouldn’t be necessary:

line = nil  
puts(line) while line = gets

Any insight would be much appreciated!!!

---

<div class="post-metadata">

**Author:** ![beev](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/b38774/32.png) [@beev](https://www.ruby-forum.com/u/beev)\
**Post date:** [June 28, 2006, 10:15pm UTC](https://www.ruby-forum.com/t/while-modifiers-have-a-scoping-bug/96434/2 "2006-06-28T22:15:36Z")

</div>

> puts(line) while line = gets
> 
> The Pickaxe says on page 354 that unless the expression (on  
> the left of the while) is not a block, then the loop gets  
> executed ZERO or more times. So it has to evaluate the  
> condition BEFORE the expression, which ought to assign a  
> value to “line” (thus defining it).

Lexically, “puts line” comes first. Although “while line =  
gets” is executed first and it does set /a/ (not /the/) line,  
it’s not yet available for “puts”.

> line = nil  
> puts(line) while line = gets

Now it’s the same “line”…

gegroet,  
Erik V. - [http://www.erikveen.dds.nl/](http://www.erikveen.dds.nl/)

---

<div class="post-metadata">

**Author:** ![beev](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/b38774/32.png) [@beev](https://www.ruby-forum.com/u/beev)\
**Post date:** [June 28, 2006, 10:25pm UTC](https://www.ruby-forum.com/t/while-modifiers-have-a-scoping-bug/96434/3 "2006-06-28T22:25:31Z")

</div>

On Jun 28, 2006, at 1:36 PM, Mr Beev wrote:

> ## which
> 
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

Erik already answered but I’ll throw in my two cents. The first  
assignment of a local variable also declares it. What this means is:

puts(line) while (declare line; line = gets)

line is not in scope for puts(line) yet. Ruby creates it’s lexical  
scopes for local vars by looking top to bottom, left to right at  
_parse_ time.

---

<div class="post-metadata">

**Author:** ![beev](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/b38774/32.png) [@beev](https://www.ruby-forum.com/u/beev)\
**Post date:** [June 29, 2006, 10:09pm UTC](https://www.ruby-forum.com/t/while-modifiers-have-a-scoping-bug/96434/4 "2006-06-29T22:09:06Z")

</div>

2006/6/28, Mr Beev [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> This will work, but shouldn’t be necessary:
> 
> line = nil  
> puts(line) while line = gets
> 
> Any insight would be much appreciated!!!

Note, usually you cannot rely on IRB when it comes to scoping and  
local variables. It behaves differently than normal Ruby code. But in  
this case it’s right:

robert@fussel ~  
$ ruby -e ‘puts line if line = gets’  
d  
-e:1: undefined local variable or method `line’ for main:Object  
(NameError)

robert@fussel ~  
$ ruby -e ‘def t; puts line if line = gets; end; t’  
d  
-e:1:in `t': undefined local variable or method `line’ for main:Object  
(NameError)  
from -e:1

The reason, as has been pointed out already is that the assignment  
appears after the read access. A solution is to use “and”:

robert@fussel ~  
$ ruby -e ‘line = gets and puts line’  
s  
s

robert@fussel ~  
$

Kind regards

robert
