Ruby idom needed

What’s the best ruby idiom for the following Perl:

open(EMAIL, "<$EMAIL_FILE") or die "Failed to open $EMAIL_FILE";
my %hash = map {chomp; split /\=/} (<EMAIL>);
close (EMAIL);

(the above reads a file containing text like

key1=value1
key2=value2

into a hash.

So far I have:

h = {}
f = File.open(“fred.ini”, “r”)
f.each_line{|l| s = l.chomp.split("="); h[s[0]] = s[1]}
f.close

···

Robert Cowham

You can condense that into one line:

File.readlines(“fred.ini”){…}

The rest looks pretty much as good as you’re gonna get.

Tim Bates

···

On Sun, 24 Nov 2002 09:11 pm, Robert Cowham wrote:

f = File.open(“fred.ini”, “r”)
f.each_line{|l| s = l.chomp.split(“=”); h[s[0]] = s[1]}
f.close


tim@bates.id.au

In article Xns92D06BB23793rcvaccapernacouk@130.133.1.4,

···

Robert Cowham rc@vaccaperna.co.uk wrote:

What’s the best ruby idiom for the following Perl:

open(EMAIL, "<$EMAIL_FILE") or die "Failed to open $EMAIL_FILE";
my %hash = map {chomp; split /\=/} (<EMAIL>);
close (EMAIL);

(the above reads a file containing text like

key1=value1
key2=value2

into a hash.

So far I have:

h = {}
f = File.open(“fred.ini”, “r”)
f.each_line{|l| s = l.chomp.split(“=”); h[s[0]] = s[1]}
f.close

h = {}
File.foreach(“fred.ini”) do |line|
key, value = line.chomp.split(“=”)
h[key] = value
end

Ross

Hi –

What’s the best ruby idiom for the following Perl:

open(EMAIL, "<$EMAIL_FILE") or die "Failed to open $EMAIL_FILE";
my %hash = map {chomp; split /\=/} (<EMAIL>);
close (EMAIL);

(the above reads a file containing text like

key1=value1
key2=value2

into a hash.

So far I have:

h = {}
f = File.open(“fred.ini”, “r”)
f.each_line{|l| s = l.chomp.split(“=”); h[s[0]] = s[1]}
f.close

A couple of possibilities:

h = Hash[*File.new(“fred.ini”).read.split(/=|\n/)]

h = {}
File.new(“fred.ini”).each {|l| h.update(Hash[*l.chomp.split(“=”)])}

David

···

On Sun, 24 Nov 2002, Robert Cowham wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

[snip]

h = {}
f = File.open(“fred.ini”, “r”)
f.each_line{|l| s = l.chomp.split(“=”); h[s[0]] = s[1]}
f.close
[snip]

(IO.readlines ‘foo’).each {|line| (hash ||= {}).store *(line.chomp.split ‘=’)}

-a

···

On 24 Nov 2002, Robert Cowham wrote:

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

I like #scan. It looks quite readable to me:

h =
File.open(‘fred.ini’).read.scan(/(\w+)=(\w+)/) { h[$1] = $2 }

Massimiliano

···

On Sun, Nov 24, 2002 at 07:41:26PM +0900, Robert Cowham wrote:

(the above reads a file containing text like

key1=value1
key2=value2

into a hash.

Hi,

h = {}
f = File.open(“fred.ini”, “r”)
f.each_line{|l| s = l.chomp.split(“=”); h[s[0]] = s[1]}
f.close

h = Hash[*File.new(“fred.ini”).read.split(/=|\n/)]

I like the above, but wondered it it leaves the file open?
Here’s a slightly modified version:

h = Hash[*File.open(“fred.ini”){|f| f.read.split(/=|\n/)}]

Regards,

Bill

···

From: dblack@candle.superlink.net

On Sun, 24 Nov 2002, Robert Cowham wrote:

Hi –

[snip]

h = {}
f = File.open(“fred.ini”, “r”)
f.each_line{|l| s = l.chomp.split(“=”); h[s[0]] = s[1]}
f.close
[snip]

(IO.readlines ‘foo’).each {|line| (hash ||= {}).store *(line.chomp.split ‘=’)}

You need to have the ‘hash’ variable be in scope already when you
start accumulating, because otherwise…

irb(main):006:0> (IO.readlines ‘conf.txt’).each {|line|
(hash ||= {}).store *(line.chomp.split ‘=’); p hash}
{“key1”=>“value1”}
{“key2”=>“value2”}

…you get a new ‘hash’ each time through :slight_smile: (and nothing
visible once the iteration finishes)

David

···

On Mon, 25 Nov 2002, ahoward wrote:

On 24 Nov 2002, Robert Cowham wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Thank you! This is clear and still concise. The other responses seem
to gravitate towards Perl-like one-liners. But this defeats the
purpose of writing in Ruby—to avoid Perl obfuscations. The above is
much more readable and also much more idiomatic than many of the
others. This should go into athe Ruby Cookbook (if it were still up).

···

Ross Shaw rshaw1961@yahoo.com.au wrote in message news: Robert Cowham rc@vaccaperna.co.uk wrote:

What’s the best ruby idiom for the following Perl:

open(EMAIL, "<$EMAIL_FILE") or die "Failed to open $EMAIL_FILE";
my %hash = map {chomp; split /\=/} (<EMAIL>);
close (EMAIL);

(the above reads a file containing text like

key1=value1
key2=value2

into a hash.

So far I have:

h = {}
f = File.open(“fred.ini”, “r”)
f.each_line{|l| s = l.chomp.split(“=”); h[s[0]] = s[1]}
f.close

h = {}
File.foreach(“fred.ini”) do |line|
key, value = line.chomp.split(“=”)
h[key] = value
end

Ross

h = Hash[*File.new("fred.ini").read.split(/=|\n/)]

I like the above, but wondered it it leaves the file open?

The file will be closed when it will be garbage collected.

Guy Decoux

h = {}
File.foreach(“fred.ini”) do |line|
key, value = line.chomp.split(“=”)
h[key] = value
end

Ross

Thank you! This is clear and still concise. The other responses
seem
to gravitate towards Perl-like one-liners. But this defeats the
purpose of writing in Ruby—to avoid Perl obfuscations. The above
is
much more readable and also much more idiomatic than many of the
others. This should go into athe Ruby Cookbook (if it were still
up).

Well said; I found this to be the best balanced between rubyish and
still readable.

···

=====

Yahoo IM: michael_s_campbell


Do you Yahoo!?
Yahoo! Mail Plus – Powerful. Affordable. Sign up now.

Would this be better if you changed split to:

key, value = line.strip.split(/=/,2)

That way, you could handle things like

key1 = Fred = 2 #=> ‘key1’ => “Fred = 2”

···

On Monday, 25 November 2002 at 11:02:41 +0900, Damon wrote:

Ross Shaw rshaw1961@yahoo.com.au wrote in message news: Robert Cowham rc@vaccaperna.co.uk wrote:

What’s the best ruby idiom for the following Perl:

open(EMAIL, "<$EMAIL_FILE") or die "Failed to open $EMAIL_FILE";
my %hash = map {chomp; split /\=/} (<EMAIL>);
close (EMAIL);

(the above reads a file containing text like

key1=value1
key2=value2

into a hash.

h = {}
File.foreach(“fred.ini”) do |line|
key, value = line.chomp.split(“=”)
h[key] = value
end


Jim Freeze

Nothing is faster than the speed of light …

To prove this to yourself, try opening the refrigerator door before the
light comes on.

Hi –

h = {}
File.foreach(“fred.ini”) do |line|
key, value = line.chomp.split(“=”)
h[key] = value
end

Ross

Thank you! This is clear and still concise. The other responses seem
to gravitate towards Perl-like one-liners. But this defeats the
purpose of writing in Ruby—to avoid Perl obfuscations. The above is
much more readable and also much more idiomatic than many of the
others. This should go into athe Ruby Cookbook (if it were still up).

Uh oh, I think I might be an obfuscation suspect :slight_smile: But please – I
must insist that my obfuscations be denounced as Ruby obfuscations,
not Perl ones :slight_smile: Perl is a red herring here; Perl style isn’t
necessarily a point of reference at all, one way or the other, when
one decides to use Ruby or to do specific things in Ruby.

I personally put reading a config file in a kind of utilitarian,
“let’s just do this and move on” category – and those types of things
I do like to trim down to near-minimum code. It’s my impression that
that can actually add to the overall clarity of a program file. But a
lot of this is in the eye of the beholder. Ross’s code certainly
looks fine to me.

Idiomatic-ness is of course hard to measure. But I definitely like
the Hash[*array] idiom. It’s a technique that would be more familiar
and would probably seem more idiomatic if it were used more often, and
would be used more often if it seemed more familiar… so someone’s
got to break the cycle :slight_smile:

David

···

On Mon, 25 Nov 2002, Damon wrote:

Ross Shaw rshaw1961@yahoo.com.au wrote in message news: Robert Cowham rc@vaccaperna.co.uk wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

In article d287614.0211241749.63173bf7@posting.google.com,

Ross Shaw rshaw1961@yahoo.com.au wrote in message news: Robert

What’s the best ruby idiom for the following Perl:

open(EMAIL, "<$EMAIL_FILE") or die "Failed to open $EMAIL_FILE";
my %hash = map {chomp; split /\=/} (<EMAIL>);
close (EMAIL);

(the above reads a file containing text like

key1=value1
key2=value2

into a hash.

So far I have:

h = {}
f = File.open(“fred.ini”, “r”)
f.each_line{|l| s = l.chomp.split(“=”); h[s[0]] = s[1]}
f.close

h = {}
File.foreach(“fred.ini”) do |line|
key, value = line.chomp.split(“=”)
h[key] = value
end

Ross

Thank you! This is clear and still concise. The other responses seem
to gravitate towards Perl-like one-liners. But this defeats the
purpose of writing in Ruby—to avoid Perl obfuscations. The above is
much more readable and also much more idiomatic than many of the
others. This should go into athe Ruby Cookbook (if it were still up).

I have to come clean. I only did this implementation because I could not
for the life of me figure out how to get Hash update working with an
array (as per many of the other solutions). I looked up my Pickaxe and
Ruby in a Nutshell and still could not work it out. So it was only dumb
ignorance that left me with what I had.

But on reflection and given your appreciation I am happier with what I
did put up.

Ross

···

adamon@mailandnews.com (Damon) wrote:

Cowham rc@vaccaperna.co.uk wrote:

<

h = Hash[*File.new(“fred.ini”).read.split(/=|\n/)]

I like the above, but wondered it it leaves the file open?

The file will be closed when it will be garbage collected.

You again!!! ;-D

Hehe…

Intriuging. It’s indeed good to learn GC will cause the file to
be closed (makes sense.)

I don’t know if I worry too much, but that does set off my potential-
danger-alarm meter a bit, depending on conceivable circumstances:
for instance, if the above were in a loop. Would it be possible to
run out of file handles before GC was called?

If so, I would personally find myself resistant to adopting the
idiom of letting GC close file handles, as I would view the
relationship between the opener of the handles, and GC, as a
potential race condition lurking in my code. . . . But it could be
I worry too much. :slight_smile:

Regards,

Bill

···

From: “ts” decoux@moulon.inra.fr

Hmmm…rubyish… that’s awful close to rubish. :slight_smile:

···

On Monday, 25 November 2002 at 11:23:52 +0900, Michael Campbell wrote:

Well said; I found this to be the best balanced between rubyish and
still readable.


Jim Freeze

All bridge hands are equally likely, but some are more equally likely
than others.
– Alan Truscott

Would this be better if you changed split to:

key, value = line.strip.split(/=/,2)
Oops, should read…

···

On Monday, 25 November 2002 at 11:24:40 +0900, Jim Freeze wrote:

key, value = line.strip.split(/\s*=\s*/,2)


Jim Freeze

One way to make your old car run better is to look up the price of a
new model.

dblack@candle.superlink.net wrote in
news:Pine.LNX.4.44.0211242202400.3367-100000@candle.superlink.net:

Hi –

Ross Shaw rshaw1961@yahoo.com.au wrote in message news:
Robert Cowham rc@vaccaperna.co.uk wrote:

h = {}
File.foreach(“fred.ini”) do |line|
key, value = line.chomp.split(“=”)
h[key] = value
end

Ross

Thanks all for the suggestions - very interesting for a Ruby newbie!

···

On Mon, 25 Nov 2002, Damon wrote:


Robert Cowham

“Bill Kelly” billk@cts.com writes:

From: “ts” decoux@moulon.inra.fr

The file will be closed when it will be garbage collected.

I don’t know if I worry too much, but that does set off my potential-
danger-alarm meter a bit, depending on conceivable circumstances:
for instance, if the above were in a loop. Would it be possible to
run out of file handles before GC was called?

Nope - the interpreter checks and runs GC if it runs out of file handles:

file = fopen(fname, mode);
if (!file) {
if (errno == EMFILE || errno == ENFILE) {
    rb_gc();
    file = fopen(fname, mode);
}
if (!file) {
    rb_sys_fail(fname);
}
}

Cheers

Dave

for instance, if the above were in a loop. Would it be possible to
run out of file handles before GC was called?

no,

If so, I would personally find myself resistant to adopting the
idiom of letting GC close file handles, as I would view the
relationship between the opener of the handles, and GC, as a
potential race condition lurking in my code. . . . But it could be
I worry too much. :slight_smile:

Well, you must know that some persons like me are stupid and forget to
close the files and I frequently write

pigeon% cat b.rb
#!/usr/bin/ruby
require 'bz2'

a = File.new("aa", "w")
bz2 = BZ2::Writer.new(a)
12.times {|i| bz2.puts i }
pigeon%

pigeon% b.rb
pigeon%

pigeon% bunzip2 < aa
0
1
2
3
4
5
6
7
8
9
10
11
pigeon%

If the file is not automatically closed, I will lost many data :-)))

Guy Decoux