[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Confused about variable "declarations"

Graham Nicholls

1/20/2005 11:37:00 AM


Page 14 of the new Pickaxe book says (amongst other things):

"Note that we didn't have to declare the variable 'result'; it sprang into
existence when we assigned to it."

This was my understanding, but I keep seeing this sort of thing:

../duprop:136:in `find_pcap_offset': undefined local variable or method
`offset' for #<Pcap_entry:0x40280794> (NameError)

when I run this:

offset=line.split()[1].to_i

Its easily fixed: I assign 0 to offset earlier in the method:

def find_pcap_offset # Find the offset to the pcap entry for printer_name
found=false
offset=0 # <- This fixes things.
begin
pcap_file=File.open(@pcap_fname)
rescue IOError
print("can't open pcap file #{@pcap_fname}\n")
exit(BAD_PCAP_FILE)
end
# OK, now find the pcap entry
pcap_file.each_line() do |line|
if line.match(@printer_name)
print("Found printer #{@printer_name} in [#{line}]\n") if $debug
found=true
offset=line.split()[1].to_i
break


Now I hate to do this - partly at least 'cause its clear evidence I don't
understand something!

Any help appreciated.
Graham Nicholls
--
With Linux the answer's always "Yes".
Now, whats the question?


----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.new... The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= East/West-Coast Server Farms - Total Privacy via Encryption =---
18 Answers

Peter Hickman

1/20/2005 11:48:00 AM

0

A variable will 'spring into existence' when you assign to it but not
when you reference it.

so:

offset = offset=line.split()[1].to_i

will work fine but something like

total = offset + 1

or

offset = offset + 1

or

table[offset] = 42

will all error because they are referencing a variable that has not been
created. If you look at, or around, line 136 in your code you will
probably find a reference to the variable offset and this is what is
causing the problem.

If not then I am stumped.



Peter Hickman

1/20/2005 11:51:00 AM

0

Peter Hickman wrote:

> offset = offset=line.split()[1].to_i

typo, should be plain

offset=line.split()[1].to_i

sorry about that



Jim Weirich

1/20/2005 11:57:00 AM

0

On Thursday 20 January 2005 06:41 am, Graham Nicholls wrote:
> This was my understanding, but I keep seeing this sort of thing:
>
> ../duprop:136:in `find_pcap_offset': undefined local variable or method
> `offset' for #<Pcap_entry:0x40280794> (NameError)
[...]
> pcap_file.each_line() do |line|
> if line.match(@printer_name)
> print("Found printer #{@printer_name} in [#{line}]\n") if $debug
> found=true
> offset=line.split()[1].to_i
> break
[...]

You didn't show the complete listing, so I am guessing here. offset does
indeed spring into existence at the point you assign it. Unfortunately, it
only exists for the duration of the block that begins with the line
"pcap_file.each_line() do |line|". I suspect that the error message you were
getting occured when you tried to access offset later in the code, outside of
the block.

Assigning to offset outside the block means that it existed before the block
was entered, and will continue to exist after the block is done.

This is one of the little oddities that Matz intends to fix in Ruby 2.0.

--
-- Jim Weirich jim@weirichhouse.org http://onest...
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)


Graham Nicholls

1/20/2005 11:59:00 AM

0

Peter Hickman wrote:

> Peter Hickman wrote:
>
>> offset = offset=line.split()[1].to_i
>
> typo, should be plain
>
> offset=line.split()[1].to_i
>
> sorry about that
No worries, and thanks, but I think that the problem was that offset is
being set inside an iterator (they still confuse me - any pointers to a
good explanation would be nice!), which means that it is out of scope
outside the iterator.

Graham Nicholls
--
With Linux the answer's always "Yes".
Now, whats the question?


----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.new... The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= East/West-Coast Server Farms - Total Privacy via Encryption =---

Robert Klemme

1/20/2005 12:18:00 PM

0


"Graham Nicholls" <graham @rockcons.co.uk> schrieb im Newsbeitrag
news:1106221017_4840@surge1-maxim.com...
>
> Page 14 of the new Pickaxe book says (amongst other things):
>
> "Note that we didn't have to declare the variable 'result'; it sprang
into
> existence when we assigned to it."
>
> This was my understanding, but I keep seeing this sort of thing:
>
> ./duprop:136:in `find_pcap_offset': undefined local variable or method
> `offset' for #<Pcap_entry:0x40280794> (NameError)
>
> when I run this:
>
> offset=line.split()[1].to_i
>
> Its easily fixed: I assign 0 to offset earlier in the method:
>
> def find_pcap_offset # Find the offset to the pcap entry for
printer_name
> found=false
> offset=0 # <- This fixes things.
> begin
> pcap_file=File.open(@pcap_fname)
> rescue IOError
> print("can't open pcap file #{@pcap_fname}\n")
> exit(BAD_PCAP_FILE)
> end
> # OK, now find the pcap entry
> pcap_file.each_line() do |line|
> if line.match(@printer_name)
> print("Found printer #{@printer_name} in [#{line}]\n") if $debug
> found=true
> offset=line.split()[1].to_i
> break

Is this really the complete example? Because from what I see 'offset' is
not read accessed here. Which line causes the error? Maybe you print out
'offset' after the each_line loop and no line matched.

And btw, I'd rearrage the code like this (I know that you don't need to
because of exit but if exit changes behavior i.e. not really exiting the
system you might see surprising results):

def find_pcap_offset # Find the offset to the pcap entry for printer_name
found=false
offset=0 # <- This fixes things.
begin
pcap_file=File.open(@pcap_fname)

# OK, now find the pcap entry
pcap_file.each_line() do |line|
if line.match(@printer_name)
print("Found printer #{@printer_name} in [#{line}]\n") if $debug
found=true
offset=line.split()[1].to_i
break
...
end
...
end

rescue IOError
$stderr.print("can't open pcap file #{@pcap_fname}\n")
exit(BAD_PCAP_FILE)
end

Or leave the exception handling completely out here. IHMO the exception
is meaningful enough:

13:17:42 [otrs-1006999]: ruby -e 'def find_pcap_offset() File.open("x") {}
end; find_pcap_offset'
-e:1:in `initialize': No such file or directory - x (Errno::ENOENT)
from -e:1:in `open'
from -e:1:in `find_pcap_offset'
from -e:1

> Now I hate to do this - partly at least 'cause its clear evidence I
don't
> understand something!

The error can only occur if you read access the var before writing it.

Kind regards

robert

Mark Hubbart

1/20/2005 5:09:00 PM

0

On Thu, 20 Jan 2005 21:01:01 +0900, Graham Nicholls
<graham@rockcons.co.uk> wrote:
> No worries, and thanks, but I think that the problem was that offset is
> being set inside an iterator (they still confuse me - any pointers to a
> good explanation would be nice!), which means that it is out of scope
> outside the iterator.

A short explanation: Blocks have a sort of "leaky scope", where
variables from outside the scope can leak in and out, but those that
are from the inside don't leak out. for example:

def increment_23(num)
23.times { num += 1 }
return num
end

increment_23(9) #=>42

This is because num was defined in the block's outer scope, so it
leaked in. In this example, though:

def one
1.time { num = 1 }
return num
end

one() #=> error!

This gives an error because num was created *inside* the block, and
didn't leak out. So "return num" references a variable that doesn't
exist in that scope. You could fix it like this:

def one
num = nil # assign something to num, initializing it.
1.time{ num = 1 }
return num
end

one() #=>1

Setting the variable before entering the block lets it leak in (and
out). Though it doesn't actually matter what you assigning to the
variable, from what I've seen, the most common idiom for this is to
assign nil, like in the above. That way, if you see where someone has
assigned nil to a variable above a block, you can be fairly sure that
they will also be assigning to that variable inside the block, and
want it to leak back out of the block so they can use it later.

So, to recap: When you assign to a variable *inside* a block, ruby
looks first to see if there is a variable of the same name *outside*
the block; if there is, it will use the same variable; if there isn't,
it will create a variable local only to that block.

HTH,
Mark


Robert Klemme

1/20/2005 5:29:00 PM

0


"Mark Hubbart" <discordantus@gmail.com> schrieb im Newsbeitrag
news:de63abca050120090877cc9971@mail.gmail.com...
> On Thu, 20 Jan 2005 21:01:01 +0900, Graham Nicholls
> <graham@rockcons.co.uk> wrote:
> > No worries, and thanks, but I think that the problem was that offset
is
> > being set inside an iterator (they still confuse me - any pointers to
a
> > good explanation would be nice!), which means that it is out of scope
> > outside the iterator.
>
> A short explanation: Blocks have a sort of "leaky scope", where
> variables from outside the scope can leak in and out, but those that
> are from the inside don't leak out. for example:

While I completely agree with your explanation the word "leaky" strikes me
as odd as it seems to suggest uncommon or defective behavior: it's very
common in programming languages, that variables are visible in nested
scopes but not surrounding scopes:

public int foo() {
int visible_in_whole_method = 0;

{
int visible_only_in_this_nested_scope = visible_in_whole_method + 1;
}
}

Kind regards

robert

Ilmari Heikkinen

1/20/2005 6:01:00 PM

0


On 20.1.2005, at 19:31, Robert Klemme wrote:

>
> "Mark Hubbart" <discordantus@gmail.com> schrieb im Newsbeitrag
> news:de63abca050120090877cc9971@mail.gmail.com...
>> On Thu, 20 Jan 2005 21:01:01 +0900, Graham Nicholls
>> <graham@rockcons.co.uk> wrote:
>>> No worries, and thanks, but I think that the problem was that offset
> is
>>> being set inside an iterator (they still confuse me - any pointers to
> a
>>> good explanation would be nice!), which means that it is out of scope
>>> outside the iterator.
>>
>> A short explanation: Blocks have a sort of "leaky scope", where
>> variables from outside the scope can leak in and out, but those that
>> are from the inside don't leak out. for example:
>
> While I completely agree with your explanation the word "leaky"
> strikes me
> as odd as it seems to suggest uncommon or defective behavior: it's
> very
> common in programming languages, that variables are visible in nested
> scopes but not surrounding scopes:
>

This may be the leaky case:

x = 10
arr = (x..100).map{|x| x*2}
x #=> 100

:)

--
Ilmari Heikkinen



Nicholas Van Weerdenburg

1/20/2005 6:42:00 PM

0

I'm was quite fond of "leaky" since I didn't have a good word for it
before. But you are right, I suppose. "leak" is usually a bad thing in
boats, birth control, and programming. For instance, who would to
apply "leaky logic" algorithms. I can definitely see why they went
with "fuzzy logic" instead of "leaky logic". How about "fuzzy scope"?

Of course, this could make one think of "cuddly scope", which is also
probably accurate when it comes to Ruby (in fact, I noticed one of the
Japanese Ruby books on Amazon had a bunny rabbit on it- it was paired
with the Ruby Hackers Guide (RBG), so I assume it was Ruby- I don't
read or speak Japanese).

Of course, if we doing lisp, it would probably be called "transitive
dynamic semi-lexical scope transclusion" or something like that ( and
no, I have no idea what I just said, if anything).

Regards,
Nick
--
Nicholas Van Weerdenburg

On Fri, 21 Jan 2005 02:31:00 +0900, Robert Klemme <bob.news@gmx.net> wrote:
>
> "Mark Hubbart" <discordantus@gmail.com> schrieb im Newsbeitrag
> news:de63abca050120090877cc9971@mail.gmail.com...
> > On Thu, 20 Jan 2005 21:01:01 +0900, Graham Nicholls
> > <graham@rockcons.co.uk> wrote:
> > > No worries, and thanks, but I think that the problem was that offset
> is
> > > being set inside an iterator (they still confuse me - any pointers to
> a
> > > good explanation would be nice!), which means that it is out of scope
> > > outside the iterator.
> >
> > A short explanation: Blocks have a sort of "leaky scope", where
> > variables from outside the scope can leak in and out, but those that
> > are from the inside don't leak out. for example:
>
> While I completely agree with your explanation the word "leaky" strikes me
> as odd as it seems to suggest uncommon or defective behavior: it's very
> common in programming languages, that variables are visible in nested
> scopes but not surrounding scopes:
>
> public int foo() {
> int visible_in_whole_method = 0;
>
> {
> int visible_only_in_this_nested_scope = visible_in_whole_method + 1;
> }
> }
>
> Kind regards
>
> robert
>
>


Nicholas Van Weerdenburg

1/20/2005 6:53:00 PM

0

On Fri, 21 Jan 2005 03:01:02 +0900, Ilmari Heikkinen <kig@misfiring.net> wrote:
>
> On 20.1.2005, at 19:31, Robert Klemme wrote:
>
> >
> > "Mark Hubbart" <discordantus@gmail.com> schrieb im Newsbeitrag
> > news:de63abca050120090877cc9971@mail.gmail.com...
> >> On Thu, 20 Jan 2005 21:01:01 +0900, Graham Nicholls
> >> <graham@rockcons.co.uk> wrote:
> >>> No worries, and thanks, but I think that the problem was that offset
> > is
> >>> being set inside an iterator (they still confuse me - any pointers to
> > a
> >>> good explanation would be nice!), which means that it is out of scope
> >>> outside the iterator.
> >>
> >> A short explanation: Blocks have a sort of "leaky scope", where
> >> variables from outside the scope can leak in and out, but those that
> >> are from the inside don't leak out. for example:
> >
> > While I completely agree with your explanation the word "leaky"
> > strikes me
> > as odd as it seems to suggest uncommon or defective behavior: it's
> > very
> > common in programming languages, that variables are visible in nested
> > scopes but not surrounding scopes:
> >
>
> This may be the leaky case:
>
> x = 10
> arr = (x..100).map{|x| x*2}
> x #=> 100
>
> :)
>
> --
> Ilmari Heikkinen
>
>

I'm quite fond of this behaviour. It works nicely in the "optparse" library.

e.g.
require "optparse"
logfile=nil;
opts=OptionParser.new do |opt|
opt.on('--logfile', '-l', "Specify log file"){|logfile|}
end

But I was confused initially since I was thinking in C/Java scope
terms at first, and then Perl terms at second. But now I'm happy. I do
suppose it might be nice to allow seeping (fuzzing didn't sound write)
out. That would save some typing, without too much confusion.

Nick
--
Nicholas Van Weerdenburg