[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

newbie scope question

Charles L. Snyder

6/26/2005 10:13:00 PM

Hi,

Thank you answers to my previous question(s) !

Why does this not work?

doc = File::open("my.txt")
class Crap
def junko
@doc = doc
@doc.each {|line| print line}
end
end
myobj=Crap.new
myobj.junko

The segment below does work - I just don't quite understand why the Crap
object can't 'see' the txt file in the above example...

doc = File::open("my.txt")
class Crap
def junko(a)
a.each {|line| print line}
end
end
myobj=Crap.new
myobj.junko(doc)

Thanks in advance


5 Answers

Ryan Leavengood

6/26/2005 10:39:00 PM

0

Charles L. Snyder wrote:
>
> Why does this not work?

Because the variable doc is local to the top-level scope and can't be
seen inside the methods of Crap. This works:

$doc = File::open("my.txt")
class Crap
def junko
@doc = $doc
@doc.each {|line| print line}
end
end
myobj=Crap.new
myobj.junko
$doc.close

$doc is now a global. Of course, I would not recommend coding this way.
For example your original code never closed the file (which is probably
not that bad here because at exit open files will be closed.) In
addition globals are bad in most cases.

Using File::open with a block, and passing in the file (like your second
example) is better:

class Crap
def junko(doc)
@doc = doc
@doc.each {|line| print line}
end
end

File::open("my.txt") do |file|
myobj=Crap.new
myobj.junko(file)
end

That way the file is closed automatically when the block ends.

Ryan


Devin Mullins

6/26/2005 11:57:00 PM

0

Ryan Leavengood wrote:

> Because the variable doc is local to the top-level scope and can't be
> seen inside the methods of Crap.

That is interesting, though. In most cases, variables defined in the
outer scope are available in the inner scope. This applies in the case
of begin...end, blocks, and the if/while/etc control flow operators. It
seems that the same rule does not apply to method and class definitions.
Why? Is there anything else to which it doesn't apply?

Devin



Florian Groß

6/27/2005 1:02:00 AM

0

Mark Hubbart

6/27/2005 1:02:00 AM

0

On 6/26/05, Devin Mullins <twifkak@comcast.net> wrote:
> Ryan Leavengood wrote:
>
> > Because the variable doc is local to the top-level scope and can't be
> > seen inside the methods of Crap.
>
> That is interesting, though. In most cases, variables defined in the
> outer scope are available in the inner scope. This applies in the case
> of begin...end, blocks, and the if/while/etc control flow operators. It
> seems that the same rule does not apply to method and class definitions.
> Why? Is there anything else to which it doesn't apply?

Unlike some other languages, variables that are not in scope in Ruby
are completely inaccessible (unless you resort to certain tricks).
Class, Module and Method definitions introduce new scopes, so outside
variables will be entirely invisible. Conditionals and looping
statements (ie, if..else, while..end, case..when..end) do not
introduce new scopes, so they can access variables that are outside
them, and variables defined inside them will be accessible outside the
statement.

Blocks are a little more complicated; they don't really introduce a
new scope, but any variables defined only inside a block will not
escape the block.

foo = 23
class Bar # new scope! foo is not accessible
baz = 42
def qux # another new scope! no baz for you!
puts baz # yoiks, that'll be a NameError
end
end

And for blocks:

name = "Mark"
5.times{puts name} # works

5.times{|n| n+=1}
puts n # doesn't work, n stays in the block

n = nil # n exists before the block
5.times{|n| n+=1}
puts n # outputs: "6"

Hope this helps, and isn't too confusing :) Except for blocks, it's
actually a simpler scheme than most other languages; no masking of
variable names in outer scopes.

cheers,
Mark


Devin Mullins

6/27/2005 1:50:00 AM

0

Wow, that was a simple and complete summary of scope in Ruby. That helps
a lot. :)

I had known that variables defined inside blocks didn't escape blocks. I
didn't know that the same wasn't true for loops and conditionals.
Essentially, scope is flat inside a class/module/method, with the odd
exception of blocks.

This is good, except it makes blocks a little confusing

Example #1:
irb(main):001:0> a = nil
=> nil
irb(main):002:0> 5.times {|a| }
=> 5
irb(main):003:0> a
=> 4

Example #2:
irb(main):006:0> 5.times {
irb(main):007:1* a ||= 0
irb(main):008:1> a+=1
irb(main):009:1> print a, ' '
irb(main):010:1> }
1 1 1 1 1

Example #3:
irb(main):001:0> a = 0
=> 0
irb(main):002:0> 5.times {
irb(main):003:1* a ||= 0
irb(main):004:1> a+=1
irb(main):005:1> print a, ' '
irb(main):006:1> }
1 2 3 4 5

Not a huge issue. Just something to get used to.

Devin