[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

passing a variable from a block back to the method

James Dinkel

8/19/2008 5:22:00 AM

I have several files that I have to read, check the contents, and then
write any changes. I overloaded the File class to help me out with
this:

----------------------------------------------------------
class File

def self.change(filename)

# read the file, execute a block, then write the file
File.open(filename, 'r+') do |file|
lines = file.readlines
yield lines
# return if not changing anything
file.pos = 0
file.print lines
file.truncate(file.pos)
end
end
end
----------------------------------------------------------

The method is called with:

----------------------------------------------------------
File.change('awesomefile') do |contents|
contents.collect! do |line|
# magic happens
# decide not to change anything
end
end
----------------------------------------------------------

This is a huge waste if the files don't change (as they often don't).
The problem I'm having is with the "# decide not to change anything" in
the block and passing that back to the method so "# return if not
changing anything" knows the answer. I'm not sure if I can pass an
instance variable around to do this? I don't really know how that would
work since I don't really have an instance of file to work with.

Maybe someone has some ideas?
--
Posted via http://www.ruby-....

16 Answers

Jesús Gabriel y Galán

8/19/2008 6:14:00 AM

0

On Tue, Aug 19, 2008 at 7:21 AM, James Dinkel <jdinkel@gmail.com> wrote:
> I have several files that I have to read, check the contents, and then
> write any changes. I overloaded the File class to help me out with
> this:

> This is a huge waste if the files don't change (as they often don't).
> The problem I'm having is with the "# decide not to change anything" in
> the block and passing that back to the method so "# return if not
> changing anything" knows the answer. I'm not sure if I can pass an
> instance variable around to do this? I don't really know how that would
> work since I don't really have an instance of file to work with.
>
> Maybe someone has some ideas?

Untested, but what about:


----------------------------------------------------------
class File

def self.change(filename)

# read the file, execute a block, then write the file
File.open(filename, 'r+') do |file|
lines = file.readlines
new_lines = yield lines
# return if not changing anything
return unless new_lines
file.pos = 0
file.print new_lines
file.truncate(file.pos)
end
end
end
----------------------------------------------------------

The method is called with:

----------------------------------------------------------
File.change('awesomefile') do |contents|
contents.collect! do |line|
# magic happens
# decide not to change anything --> the last statement evaluates to nil
nil

# when you want to return the new lines
end
end
----------------------------------------------------------

Of course you should change the logic in the block to not be within a
collect! when you want
to return nil.

Hope this helps,

Jesus.

Michael Morin

8/19/2008 6:37:00 AM

0

James Dinkel wrote:
> I have several files that I have to read, check the contents, and then
> write any changes. I overloaded the File class to help me out with
> this:
>
> ----------------------------------------------------------
> class File
>
> def self.change(filename)
>
> # read the file, execute a block, then write the file
> File.open(filename, 'r+') do |file|
> lines = file.readlines
> yield lines
> # return if not changing anything
> file.pos = 0
> file.print lines
> file.truncate(file.pos)
> end
> end
> end
> ----------------------------------------------------------
>
> The method is called with:
>
> ----------------------------------------------------------
> File.change('awesomefile') do |contents|
> contents.collect! do |line|
> # magic happens
> # decide not to change anything
> end
> end
> ----------------------------------------------------------
>
> This is a huge waste if the files don't change (as they often don't).
> The problem I'm having is with the "# decide not to change anything" in
> the block and passing that back to the method so "# return if not
> changing anything" knows the answer. I'm not sure if I can pass an
> instance variable around to do this? I don't really know how that would
> work since I don't really have an instance of file to work with.
>
> Maybe someone has some ideas?

This works well. However, you have to be careful the last statement in
your block doesn't accidentally evaluate to nil, so I added a true at
the end just in case.

class File

def self.change(filename)

# read the file, execute a block, then write the file
File.open(filename, 'r+') do|file|
lines = file.readlines

# return if not changing anything
return if yield(lines) == false

file.pos = 0
file.print lines
file.truncate(file.pos)
end
end
end

File.change('test.txt') do|contents|
break false if contents.size < 5

contents.each do|c|
c.gsub!(/[[:digit:]]/, 'X')
end

true
end

You can also use catch and throw. I think this method is a little cleaner.

class File

def self.change(filename)
catch(:nochanges) do
# read the file, execute a block, then write the file
File.open(filename, 'r+') do|file|
lines = file.readlines

# return if not changing anything
return if yield(lines) == false

file.pos = 0
file.print lines
file.truncate(file.pos)
end
end
end
end

File.change('test.txt') do|contents|
throw :nochanges if contents.size < 5

contents.each do|c|
c.gsub!(/[[:digit:]]/, 'X')
end
end

--
Michael Morin
Guide to Ruby
http://ruby....
Become an About.com Guide: beaguide.about.com
About.com is part of the New York Times Company

James Dinkel

8/19/2008 1:37:00 PM

0

Michael Morin wrote:
>
> You can also use catch and throw. I think this method is a little
> cleaner.
>

ah, I think I like the catch and throw method. That's pretty close to
what I was visualizing in my head.

Just one thing though:

> class File
>
> def self.change(filename)
> catch(:nochanges) do
> # read the file, execute a block, then write the file
> File.open(filename, 'r+') do|file|
> lines = file.readlines
>
> # return if not changing anything
> return if yield(lines) == false
>
> file.pos = 0
> file.print lines
> file.truncate(file.pos)
> end
> end
> end
> end
>

You left in the "return if yield(lines) == false", was that a typo? I'm
guessing it was.
--
Posted via http://www.ruby-....

Michael Morin

8/19/2008 11:50:00 PM

0

James Dinkel wrote:
> Michael Morin wrote:
>> You can also use catch and throw. I think this method is a little
>> cleaner.
>>
>
> ah, I think I like the catch and throw method. That's pretty close to
> what I was visualizing in my head.
>
> Just one thing though:
>
>> class File
>>
>> def self.change(filename)
>> catch(:nochanges) do
>> # read the file, execute a block, then write the file
>> File.open(filename, 'r+') do|file|
>> lines = file.readlines
>>
>> # return if not changing anything
>> return if yield(lines) == false
>>
>> file.pos = 0
>> file.print lines
>> file.truncate(file.pos)
>> end
>> end
>> end
>> end
>>
>
> You left in the "return if yield(lines) == false", was that a typo? I'm
> guessing it was.

Oh yeah, that is a typo left over from the other example. That line
should read just "yield lines".

--
Michael Morin
Guide to Ruby
http://ruby....
Become an About.com Guide: beaguide.about.com
About.com is part of the New York Times Company

James Dinkel

8/20/2008 3:01:00 PM

0

Michael Morin wrote:
>
> Oh yeah, that is a typo left over from the other example. That line
> should read just "yield lines".

That's what I figured. Thanks a bunch. My method ended up like this:
----------------------------------------------------------
class File

def self.change(filename)

# read the file, execute a block, then write the file
File.open(filename, 'r+') do |file|
lines = file.readlines
catch :nochanges
yield lines
file.pos = 0
file.print lines
file.truncate(file.pos)
end
end
end
end
----------------------------------------------------------
--
Posted via http://www.ruby-....

Ramon F Herrera

8/12/2012 3:42:00 PM

0

On Aug 10, 11:45 am, AlleyCat <al...@aohell.com> wrote:
> In article <78a31575-d7ab-4a20-94b9-
> 67635153a...@n18g2000yqn.googlegroups.com>, tracey12em...@gmail.com
> says...
>
>
>
> > Mary Katharine Ham,
>

> Typical lietard-libtard post..

What you just did was calling Rush Limbaugh liberal.

Tracey IS the Rush Limbaugh of Usenet.

How long have you been posting, anyway? Tracey is easily one of THE
most prolific and THE most replied poster. Everybody knows his/her
ideology, which is fundamentalist right winger.

Take for instance, Tracey hated the idea of Marco Rubio as VP
candidate, because he is ethnic.

The only question is the gender of Tracey, a point that s/he has never
bothered to clarify.

Your point was made somehow, however, the OP is typical of right
wingers. See my other post.

-Ramon

Bye Bye Glove

8/12/2012 5:09:00 PM

0

On 8/12/2012 8:57 AM, Paul Duca wrote:
> we KNOW the Republicans care about women

It's obvious how Dems feel about them after what they did to Hillary in
'08...

Bye Bye Glove

8/12/2012 5:10:00 PM

0

On 8/12/2012 9:41 AM, Ramon F. Herrera wrote:
> How long have you been posting, anyway?

How long until you cease?

Ramon F Herrera

8/12/2012 5:16:00 PM

0

On Aug 12, 12:10 pm, Bye Bye Glove <o...@s.ic> wrote:
> On 8/12/2012 9:41 AM, Ramon F. Herrera wrote:
>
> > How long have you been posting, anyway?
>

> How long until you cease?

When you pry my keyboard from my cold, dead hands.

-RFH

ps: How' that for the 1st+2nd???

Bye Bye Glove

8/12/2012 6:34:00 PM

0

On 8/12/2012 11:16 AM, Ramon F. Herrera wrote:
> On Aug 12, 12:10 pm, Bye Bye Glove<o...@s.ic> wrote:
>> On 8/12/2012 9:41 AM, Ramon F. Herrera wrote:
>>
> > > How long have you been posting, anyway?
> >
>
> > How long until you cease?
>
> When you pry my keyboard from my cold, dead hands.

Is that an invitation?