[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

How can a code block access an object's variables?

Ruby Novice

5/29/2008 3:31:00 PM

Dear Rubyists,

I am a novice Ruby developer who is interested in figuring out a way to
design something like what is demonstrated below. The reason why
each_line would not work in this example is because when you pass a
block of code to the FileReader object, the memory (members of
FileReader) is not shared with the block of code that is sent to
FileReader.

Maybe I have the wrong idea for how this would be designed. I just
think it would be very convenient to do this sort of thing because I
could re-use the code to open a file and read lines and only pass it
code blocks pertainant to what I want to do with those lines of code.

Please note that I do not only want to do this for an open file/read
line script. It would also be useful if you were expanding an IP range
that exceeds what you could store into an array object because you could
write an each_host method that takes in a block of code that relates to
what you want to do to each host.

class FileReader

def initialize(fname, &block)
@filename = fname
end
def each_line(&block)
begin
source = File.new(@filename, "r")
rescue => err
exit
end
begin
while(line = source.readline)

line.strip!
if((line == "") || (line =~ /[\t+\s+]/))
next
end
block.call
end
rescue EOFError
source.close
rescue => err
puts "[!] #{err}"
exit
end
end

end
my_reader = FileReader.new(ARGV[0])
my_reader.each_line { puts line
# do more parsing stuff here
}
--
Posted via http://www.ruby-....

4 Answers

Rick DeNatale

5/29/2008 5:05:00 PM

0

On Thu, May 29, 2008 at 11:30 AM, Jacob Rubynovice <l33tb0y@gmail.com> wrote:
> Dear Rubyists,
>
> I am a novice Ruby developer who is interested in figuring out a way to
> design something like what is demonstrated below. The reason why
> each_line would not work in this example is because when you pass a
> block of code to the FileReader object, the memory (members of
> FileReader) is not shared with the block of code that is sent to
> FileReader.
>
> Maybe I have the wrong idea for how this would be designed. I just
> think it would be very convenient to do this sort of thing because I
> could re-use the code to open a file and read lines and only pass it
> code blocks pertainant to what I want to do with those lines of code.
>
> Please note that I do not only want to do this for an open file/read
> line script. It would also be useful if you were expanding an IP range
> that exceeds what you could store into an array object because you could
> write an each_host method that takes in a block of code that relates to
> what you want to do to each host.
>
> class FileReader
>
> def initialize(fname, &block)
> @filename = fname
> end
> def each_line(&block)
> begin
> source = File.new(@filename, "r")
> rescue => err
> exit
> end
> begin
> while(line = source.readline)
>
> line.strip!
> if((line == "") || (line =~ /[\t+\s+]/))
> next
> end
> block.call
> end
> rescue EOFError
> source.close
> rescue => err
> puts "[!] #{err}"
> exit
> end
> end


This can be made much shorter using Ruby conventions:

class FileReader

def initialize(fname, &block)
@filename = fname
end

def each_line
source = File.open(@filename, "r") do |f| # this will
automatically close the file
f.each do | line | # This avoids having to check for
end-of-file explicitly.
line.strip!
yield line unless ((line == "") || (line =~ /[\t+\s+]/))
end
end
rescue => err # Note that a method definition itself acts like begin/end
puts "[!] #{err}"
exit
end
end

The two inner lines:
line.strip!
yield line unless ((line == "") || (line =~ /[\t+\s+]/))

could be combined as:

yield line unless ((line.strip! == "") || (line =~ /[\t+\s+]/))

But I think that the two line form might be a little clearer.

I'm not sure just what you expect the regex to be doing, as you've
coded it it's going to skip any line which
has at least one tab followed immediately by at least one whitespace
character regardless of anything else in the line.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...

Robert Klemme

5/29/2008 8:29:00 PM

0

On 29.05.2008 19:04, Rick DeNatale wrote:
> On Thu, May 29, 2008 at 11:30 AM, Jacob Rubynovice <l33tb0y@gmail.com> wrote:
>> Dear Rubyists,
>>
>> I am a novice Ruby developer who is interested in figuring out a way to
>> design something like what is demonstrated below. The reason why
>> each_line would not work in this example is because when you pass a
>> block of code to the FileReader object, the memory (members of
>> FileReader) is not shared with the block of code that is sent to
>> FileReader.
>>
>> Maybe I have the wrong idea for how this would be designed. I just
>> think it would be very convenient to do this sort of thing because I
>> could re-use the code to open a file and read lines and only pass it
>> code blocks pertainant to what I want to do with those lines of code.
>>
>> Please note that I do not only want to do this for an open file/read
>> line script. It would also be useful if you were expanding an IP range
>> that exceeds what you could store into an array object because you could
>> write an each_host method that takes in a block of code that relates to
>> what you want to do to each host.
>>
>> class FileReader
>>
>> def initialize(fname, &block)
>> @filename = fname
>> end
>> def each_line(&block)
>> begin
>> source = File.new(@filename, "r")
>> rescue => err
>> exit
>> end
>> begin
>> while(line = source.readline)
>>
>> line.strip!
>> if((line == "") || (line =~ /[\t+\s+]/))
>> next
>> end
>> block.call
>> end
>> rescue EOFError
>> source.close
>> rescue => err
>> puts "[!] #{err}"
>> exit
>> end
>> end
>
>
> This can be made much shorter using Ruby conventions:
>
> class FileReader
>
> def initialize(fname, &block)
> @filename = fname
> end
>
> def each_line
> source = File.open(@filename, "r") do |f| # this will
> automatically close the file
> f.each do | line | # This avoids having to check for
> end-of-file explicitly.
> line.strip!
> yield line unless ((line == "") || (line =~ /[\t+\s+]/))
> end
> end
> rescue => err # Note that a method definition itself acts like begin/end
> puts "[!] #{err}"
> exit
> end
> end
>
> The two inner lines:
> line.strip!
> yield line unless ((line == "") || (line =~ /[\t+\s+]/))
>
> could be combined as:
>
> yield line unless ((line.strip! == "") || (line =~ /[\t+\s+]/))
>
> But I think that the two line form might be a little clearer.
>
> I'm not sure just what you expect the regex to be doing, as you've
> coded it it's going to skip any line which
> has at least one tab followed immediately by at least one whitespace
> character regardless of anything else in the line.

No, the complete expression will skip empty lines as well we lines that
contain either a tab, a space (which includes tab IIRC) or a plus sign.

irb(main):004:0> /[\t+\s+]/ =~ " "
=> 0
irb(main):005:0> /[\t+\s+]/ =~ "+"
=> 0
irb(main):007:0> /\s/ =~ "\t"
=> 0

Even shorter

File.foreach file do |line|
next if /^\s*$/ =~ line
line.chomp!
# whatever
end

You can even stick this into a method, e.g.

def File.each_non_empty file
foreach file do |line|
next if /^\s*$/ =~ line
line.strip!
yield line
end
end

Note that the regular expression that was posted originally is most
likely wrong.

Kind regards

robert

Ruby Novice

5/30/2008 3:15:00 PM

0

Robert Klemme wrote:
> On 29.05.2008 19:04, Rick DeNatale wrote:
>>> Maybe I have the wrong idea for how this would be designed. I just
>>> class FileReader
>>> begin
>>> rescue => err
>> def initialize(fname, &block)
>> end
>>
>> could be combined as:
>>
>> yield line unless ((line.strip! == "") || (line =~ /[\t+\s+]/))
>>
>> But I think that the two line form might be a little clearer.
>>
>> I'm not sure just what you expect the regex to be doing, as you've
>> coded it it's going to skip any line which
>> has at least one tab followed immediately by at least one whitespace
>> character regardless of anything else in the line.
>
> No, the complete expression will skip empty lines as well we lines that
> contain either a tab, a space (which includes tab IIRC) or a plus sign.
>
> irb(main):004:0> /[\t+\s+]/ =~ " "
> => 0
> irb(main):005:0> /[\t+\s+]/ =~ "+"
> => 0
> irb(main):007:0> /\s/ =~ "\t"
> => 0
>
> Even shorter
>
> File.foreach file do |line|
> next if /^\s*$/ =~ line
> line.chomp!
> # whatever
> end
>
> You can even stick this into a method, e.g.
>
> def File.each_non_empty file
> foreach file do |line|
> next if /^\s*$/ =~ line
> line.strip!
> yield line
> end
> end
>
> Note that the regular expression that was posted originally is most
> likely wrong.
>
> Kind regards
>
> robert

You are correct. I was wrong with that regular expression. I was
trying to make a regular expression that ignores lines that only contain
white space- tabs, spaces, newlines (although newlines/returns are
automatically removed with the strip method).

Additionally, I just want to thank all of you for your suggestions.
They have been tremendously helpful. I think that the code block
feature of Ruby can be used to save tons of re-coding that would
otherwise need to be done in most of the modern conventional programming
languages.
--
Posted via http://www.ruby-....

Rick DeNatale

5/30/2008 6:01:00 PM

0

On Thu, May 29, 2008 at 4:29 PM, Robert Klemme
<shortcutter@googlemail.com> wrote:
> On 29.05.2008 19:04, Rick DeNatale wrote:

>> yield line unless ((line.strip! == "") || (line =~ /[\t+\s+]/))
>>
>> But I think that the two line form might be a little clearer.
>>
>> I'm not sure just what you expect the regex to be doing, as you've
>> coded it it's going to skip any line which
>> has at least one tab followed immediately by at least one whitespace
>> character regardless of anything else in the line.
>
> No, the complete expression will skip empty lines as well we lines that
> contain either a tab, a space (which includes tab IIRC) or a plus sign.

Right you are, for some reason I failed to see the square brackets.
Maybe I DO need new glasses. <G>
--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...