Variable scopes with code blocks.

P

Patrick Lynch

Hello!

Novice here. I'm reading Beginning Ruby and Beginning Rails by Apres and
building both applications they walk you through. Additionally, I'm
taking courses at lynda dot com and attempting to build a simple
application myself.

That said, I'm aware of the limits you have with local variable being
incapable of accessing variables defined inside of a code block, but is
there any exception to this rule?

Example:
_____________

1.times do
File.open("text.txt").each {|a| puts a}
end

puts a
# This where I get my error.
_____________

Is there anything I can do to 'puts a' that will allow it to return the
content it was passed inside of the code block?

Ultimately, I'd like to store the 'text.txt' as an array so I can call
uniq! on it... But we don't need to get into that in this thread.

I hope my question makes sense.

Thank you in advanced,
Aaron
 
P

Patrick Lynch

Good afternoon,

...this is slightly off topic, but i'm also going thru the Apress "Beginning
Ruby" book...i'm finding it to be a really good read...
...are you using a Mac, if so, take a look at 'TextMate' the editor
recommended for the Mac - it's excellent and it doesn't cost much...it
supports both Ruby and Rails...
...i went thru the AWDWR ["Agile Web Devlopment with Rails"] book - but I
found the "Ruby on Rails 3 Tutorial" with an associated screen cast to be
better suited to me...it's a bit expensive, the screen cast and book will
run about $100...

...i'm in chapter 3 with the "Beginning Ruby" book and I hope to finish it
on Wednesday and then get back to Rails...

...i'll take a look at your question on Tuesday...

Good weekend

----- Original Message -----
From: "Patrick Lynch" <[email protected]>
To: "ruby-talk ML" <[email protected]>
Sent: Friday, May 27, 2011 6:22 PM
Subject: Variable scopes with code blocks.
 
P

Phillip Gawlowski

Hello!

That said, I'm aware of the limits you have with local variable being
incapable of accessing variables defined inside of a code block, but is
there any exception to this rule?

What you can do is declaring the variable before the block, and access
it within the block. Like so:
a =3D [] # Let's store data in an array
(1..3).each do |i| ?> a << i # We append the index i to the array
end =3D> 1..3
puts a # Now contains [1, 2, 3].

--=20
Phillip Gawlowski

A method of solution is perfect if we can forsee from the start,
and even prove, that following that method we shall attain our aim.
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0-- Leibnitz
 
J

Justin Collins

Hello!

Novice here. I'm reading Beginning Ruby and Beginning Rails by Apres and
building both applications they walk you through. Additionally, I'm
taking courses at lynda dot com and attempting to build a simple
application myself.

That said, I'm aware of the limits you have with local variable being
incapable of accessing variables defined inside of a code block, but is
there any exception to this rule?

Example:
_____________

1.times do
File.open("text.txt").each {|a| puts a}
end

puts a
# This where I get my error.
_____________

Is there anything I can do to 'puts a' that will allow it to return the
content it was passed inside of the code block?

Ultimately, I'd like to store the 'text.txt' as an array so I can call
.uniq! on it... But we don't need to get into that in this thread.

I hope my question makes sense.

Thank you in advanced,
Aaron

In light of your ultimate goal, consider using
File.readlines("text.txt") [1].

Also note that in your example you are opening the file without ever
closing it. If you pass a block to File.open(), it will ensure the file
is closed [2].

[1] http://rdoc.info/stdlib/core/1.9.2/IO.readlines
[2] http://rdoc.info/stdlib/core/1.9.2/File.open


-Justin
 
R

Robert Klemme

In light of your ultimate goal, consider using File.readlines("text.txt")
[1].

Or rather File.foreach. File.readlines should only be used if you
need all lines of the file in memory for example because you need to
go through them multiple times and you know the file is not too large.
For making lines unique there are different options available
depending on the fact whether the order is important.

I find the first one the most elegant:

# order doesn't matter && we are on 1.9
require 'set'
unique =3D File.foreach("text.txt").to_set

# order does matter or on 1.8.6 or earlier
require 'set'
set =3D Set.new
unique =3D []
File.foreach("text.txt") {|l| unique << l if set.add? l}

Or, a bit more involved:

h =3D Hash.new []
File.foreach("setup.log") {|l| h.fetch(l) {h[l] =3D h.default << l}}
unique =3D h.default

You can also use a variant of what I once proposed:
http://viewsourcecode.org/why/redhanded/bits/klemmeSSilentHash.html

h =3D {}
unique =3D File.foreach("text.txt").inject([]) {|a,line| h[line] ||=3D a <<=
line}

...
Also note that in your example you are opening the file without ever clos= ing
it. If you pass a block to File.open(), it will ensure the file is closed
[2].
+1!

[1] http://rdoc.info/stdlib/core/1.9.2/IO.readlines
[2] http://rdoc.info/stdlib/core/1.9.2/File.open

Cheers

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,698
Latest member
LydiaHalle

Latest Threads

Top