Reading from file without end-of-lines

hi,
i’m trying to read a few text values from single file:

if File.exists?(file)
File.open(file, ‘r+’) do |f|
value1 = f.gets.strip
value2 = f.gets.strip
value3 = f.gets.strip
value4 = f.gets.strip
end
end

each value is stored in separate line and ‘strip’ above is used only to
get rid of end-of-line characters. is there any easier way to do the
same?

thanks,
jm.

each value is stored in separate line and ‘strip’ above is used only to
get rid of end-of-line characters. is there any easier way to do the same?

I tend to strip out all such characters at once, before operating on any
line.

File.readlines(file).map { |line| line.strip }.each do |line|

end

In your case, I guess that would be

lines = File.readlines(file).map { |line| line.strip }
value1 = lines.shift
value2 = lines.shift

etc.

or

v1, v2, v3, v4 = lines.shift(4)

On Fri, Dec 9, 2011 at 9:58 AM, Gavin S. [email protected]
wrote:

each value is stored in separate line and ‘strip’ above is used only to
get rid of end-of-line characters. is there any easier way to do the same?

You could start by not defining individual variables with indexed
names but using an array.

value2 = lines.shift

etc.

or

v1, v2, v3, v4 = lines.shift(4)

Executing File.readlines completely is inefficient if the file is
large and only the first four lines are needed.

One could do

values = File.open(file) do |f|
f.first(4).map! &:strip!
end

Or even shorter

values = File.foreach(“cl”).first(4).map! &:strip!

If there are proper names for variables one can do

name, street, zip, city = File.foreach(“cl”).first(4).map! &:strip!

:wink:

Kind regards

robert

Robert K. [email protected] writes:

[cut]

values = File.foreach(“cl”).first(4).map! &:strip!

If there are proper names for variables one can do

name, street, zip, city = File.foreach(“cl”).first(4).map! &:strip!

This is exactly what I tried to figure out. thanks guys :slight_smile:

jm.

On Fri, Dec 9, 2011 at 7:28 AM, Gavin S. [email protected]
wrote:

On Fri, Dec 9, 2011 at 8:18 PM, Robert K.
[email protected] wrote:

values = File.foreach(“cl”).first(4).map! &:strip!

Very elegant. Except for that ghastly & :slight_smile:

What isn’t elegant about the `&'?

On Fri, Dec 9, 2011 at 2:28 PM, Gavin S. [email protected]
wrote:

On Fri, Dec 9, 2011 at 8:18 PM, Robert K.
[email protected] wrote:

values = File.foreach(“cl”).first(4).map! &:strip!

Very elegant. Except for that ghastly & :slight_smile:

Absolutely agree! We could remedy this by allowing a single argument
to Enumerable#map which would be interpreted as method name to send to
objects. OTOH, does it warrant a change request?

Kind regards

robert

On Fri, Dec 9, 2011 at 8:18 PM, Robert K.
[email protected] wrote:

values = File.foreach(“cl”).first(4).map! &:strip!

Very elegant. Except for that ghastly & :slight_smile:

On Fri, Dec 9, 2011 at 2:42 PM, Wayne B. [email protected] wrote:

when I’ve read files, I’ve never closed them! I’ve always been under the
assumption that reading a file closed the I/O stream automatically when
completed. Have I been under the wrong assumption from the get go?

When you read in the info in a block, the file closes automatically.
Otherwise you have to manually close it.

Wayne B. писал 09.12.2011 18:42:

when completed. Have I been under the wrong assumption from the get
go?

Wayne

No, files aren’t automatically closed upon encountering EOF. You may
want,
for example, rewind the file cursor to the start or middle of the file.

On the other hand, this construct automatically closes file after
execution
leaves the block:
doc = File.open(“blossom.xml”) do |f|
Nokogiri::XML(f)
end

Note that File.open returns the value which the block has returned,
allowing
you to write such constructs. Most of the other yielding methods do it
a bit
different: for example, Array (and, generally, anything Enumerable)
returns
self to allow for method chaining.

While doing some reading this morning on nokogiri, I noticed that they
used this opening a file:

f = File.open(“blossom.xml”)
doc = Nokogiri::XML(f)
f.close

when I’ve read files, I’ve never closed them! I’ve always been under the
assumption that reading a file closed the I/O stream automatically when
completed. Have I been under the wrong assumption from the get go?

Wayne

Josh C. [email protected] writes:

Very elegant. Except for that ghastly & :slight_smile:

What isn’t elegant about the `&'?

looks like reference operator in C ? :slight_smile:

cheers,
jm.

What isn’t elegant about the `&’?

It is not elegant because the rest of the line uses . ! ? and ()
which are used basically everywhere else in Ruby code, whereas
& is used solely for … something related to blocks.

It does not feel in-sync with the rest of the ruby code.

It is confusing for newcomers as well.

Just look at it again to compare:

.map! &:strip!

Besides, that in this example, & requires the :symbol, which
is even more confusing to newcomers.

I am aware that the & notation here is syntactic sugar but it
is still not elegant. The person who mentioned that before me
is spot on - it is not elegant at all.

(Btw, ruby complained about the lack of () in this example,

warning: `&’ interpreted as argument prefix

so the proper way would be:)

.map!(&:strip!)

Which is even uglier. Perl is greeting Ruby again.

R. Klemme also agreed here:

Absolutely agree! We could remedy this by allowing a single
argument to Enumerable#map which would be interpreted as
method name to send to objects. OTOH, does it warrant
a change request?

The problem lies with the &: notation in itself. It is shorter
and thus people will use it. But it does not change the fact
that it simply is ugly.

I myself can live with that, but personally I’d rather explain
easier syntax to newcomers to ruby - they need to understand
both Symbols and Procs and methods ending in “!” when seeing
this. And I feel this is somewhat needless.

Just changing Enumerable#map alone isn’t going to help them
that much I fear.

Sadly, Ruby is going that direction lately, with the introduction
of the -> syntax notation, which I absolutely loathe. Perhaps
others love it but I for one don’t think we should evolve
in a perl-tradition - in 10 years people may suddenly think
that perl 6 looks better than ruby because it may have less
line noise …

looks like reference operator in C ? :slight_smile:

That too. Reminds me of pointers.

But to me, it does not feel in sync with the rest of the
ruby code. I think design should try to be minimalistic when
possible and not confusing, when possible.

I am going to think of an example of combining
->
with
.map!(&:strip!)
and a regex just to show that Ruby can be uglier than Perl.

On Sat, Dec 10, 2011 at 1:38 AM, Josh C. [email protected]
wrote:

Very elegant. Except for that ghastly & :slight_smile:

What isn’t elegant about the `&'?

It twists my head trying to think about how it works. Nothing else in
Ruby is like that. (OK, continuations…)

As Robert suggests, this would be so much better

values = File.foreach(“cl”).first(4).map :strip

What could be easier to understand than “send :strip to each element
of the collection”?

On Sat, Dec 10, 2011 at 2:18 PM, Marc H. [email protected]
wrote:

The problem lies with the &: notation in itself. It is shorter
and thus people will use it. But it does not change the fact
that it simply is ugly.

Please note that this is not “&:” notation - it is just “&” because
the colon belongs to the symbol name.

Sadly, Ruby is going that direction lately, with the introduction
of the → syntax notation, which I absolutely loathe. Perhaps

It is quite appealing for mathematically inclined, I believe.

others love it but I for one don’t think we should evolve
in a perl-tradition - in 10 years people may suddenly think
that perl 6 looks better than ruby because it may have less
line noise …

So you are claiming that perl 6 will exist in ten years from now -
quite risky IMHO. :wink:

Cheers

robert

On 2011-12-10, at 8:18 AM, Marc H. wrote:

It is not elegant because the rest of the line uses . ! ? and ()
which are used basically everywhere else in Ruby code, whereas
& is used solely for … something related to blocks.

Solely may be an exaggeration. & is used in other places, for example
bit-wise and e.g. 5 & 4 is 4.

Mike

Mike S. [email protected]
http://www.stok.ca/~mike/

The “`Stok’ disclaimers” apply.

On Sat, Dec 10, 2011 at 15:07, Robert K.
[email protected] wrote:

On Sat, Dec 10, 2011 at 2:18 PM, Marc H. [email protected] wrote:

Sadly, Ruby is going that direction lately, with the introduction
of the → syntax notation, which I absolutely loathe. Perhaps

It is quite appealing for mathematically inclined, I believe.

Not that that’s a prescription for a good programming language.
Remember, APL was originally just a mathematical notation. For those
of you who haven’t heard of it… there’s a good reason for that! :slight_smile:

-Dave

On Fri, Dec 9, 2011 at 7:27 PM, Gavin S. [email protected]
wrote:

values = File.foreach(“cl”).first(4).map :strip

What could be easier to understand than “send :strip to each element
of the collection”?

I disagree. & is known to invoke to_proc and place the result in the
block slot, and Symol#to_proc is known to be ->(obj) { obj.send self }
(or some equivalent). This is everywhere in Ruby, every method has a
block
slot, and you can put any block into it with the ampersand. The
map(:strip) by contrast is it’s own pattern, the only other place I’ve
seen it is in sum = numbers.reduce(0, :+)

Also, it means the dev is disassociating themselves from the functional
paradigm, which means other relevant uses will be less mentally
accessible
e.g. filenames.map &File.method(:read)

On Sat, Dec 10, 2011 at 7:18 AM, Marc H. [email protected]
wrote:

It does not feel in-sync with the rest of the ruby code.

I do not share this opinion.

It is confusing for newcomers as well.

It is better that they learn about it than hide from it. Methods have a
magic block slot, Rubyists need to know this and know how to use it.

This makes me think of when I didn’t understand the $LOAD_PATH,
because
Ruby <1.9.2 included “.” in it. Sure it made it easier for newbies like
me,
but it left a huge gap in my understanding that caused numerous problems
until I eventually figured it out when moving to latest rubies where I
had
to deal with it.

Just look at it again to compare:

I don’t think the & is syntactic sugar. You could say a + b is
syntactic sugar for a.+(b), but what is lines.map! &:strip!
syntactic
sugar for?

As an aside, this, brings up that this code is buggy. Since strip!
modifies
the string, there is no need for map. Especially considering that strip!
is
expected to be used by modifying the string, not relying on its return
value (which I think is much more egregious than using & to access the
block slot), so it’s return values are not consistent:

lines = %W[line1\n line2]
lines.map! &:strip!
lines # => [“line1”, nil]

To avoid this bug, use lines.each &:strip! Which brings up the point,
if
you change map such that you can lines.map! :strip! then realize you
need
to use the each form, lines.each :strip will not work. This is
inconsistent (and changing each is impractical as it is implemented on
each collection rather than being inherited from Enumerable) but
&:strip
will, again, work everywhere.

(Btw, ruby complained about the lack of () in this example,

so the proper way would be:)

.map!(&:strip!)

I keep warnings off, I would write .each &:strip! (or, more probably
.each &:chomp!, given this particular use case)

I myself can live with that, but personally I’d rather explain
easier syntax to newcomers to ruby - they need to understand
both Symbols and Procs and methods ending in “!” when seeing
this. And I feel this is somewhat needless.

Methods ending in ! are exactly the same as methods that don’t end in !.
Any differences are just convention, and the conventions around it are
so
inconsistent that they’re practically meaningless. So this is like
saying
“they need to understand methods containing underscores” when talking
about
to_s

On Sat, Dec 10, 2011 at 11:35 PM, Josh C. [email protected]
wrote:

To avoid this bug, use lines.each &:strip! Which brings up the point, if
you change map such that you can lines.map! :strip! then realize you need
to use the each form, lines.each :strip will not work. This is
inconsistent (and changing each is impractical as it is implemented on
each collection rather than being inherited from Enumerable) but &:strip
will, again, work everywhere.

Josh, thanks for catching this in my example!

Methods ending in ! are exactly the same as methods that don’t end in !.
Any differences are just convention, and the conventions around it are so

Well, what you said in the sentence above is also “just convention”.
We could have #foo and #foo! with totally different behavior.

Kind regards

robert

On Sat, Dec 10, 2011 at 9:35 PM, Dave A.
[email protected] wrote:

On Sat, Dec 10, 2011 at 15:07, Robert K. [email protected] wrote:

On Sat, Dec 10, 2011 at 2:18 PM, Marc H. [email protected] wrote:

Sadly, Ruby is going that direction lately, with the introduction
of the → syntax notation, which I absolutely loathe. Perhaps

It is quite appealing for mathematically inclined, I believe.

Not that that’s a prescription for a good programming language.

Which I did not claim. The point was that there are people who like
this and that all such things are a matter of taste which is hardly
debatable. :slight_smile:

Kind regards

robert