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.

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?

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)

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,
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 ...

···

--
Posted via http://www.ruby-forum.com/\.

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.

···

--
Posted via http://www.ruby-forum.com/\.

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?

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

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)

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

···

On Fri, Dec 9, 2011 at 9:58 AM, Gavin Sinclair <gsinclair@gmail.com> wrote:

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

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

Mike

···

On 2011-12-10, at 8:18 AM, Marc Heiler 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.

--

Mike Stok <mike@stok.ca>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.

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 Sat, Dec 10, 2011 at 2:18 PM, Marc Heiler <shevegen@linuxmail.org> wrote:

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

Robert Klemme <shortcutter@googlemail.com> 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.

Very elegant. Except for that ghastly & :slight_smile:

···

On Fri, Dec 9, 2011 at 8:18 PM, Robert Klemme <shortcutter@googlemail.com> wrote:

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

...

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 Sat, Dec 10, 2011 at 15:07, Robert Klemme <shortcutter@googlemail.com> wrote:

On Sat, Dec 10, 2011 at 2:18 PM, Marc Heiler <shevegen@linuxmail.org> wrote:

--
LOOKING FOR WORK! What: Ruby (on/off Rails), Python, other modern languages.
Where: Northern Virginia, Washington DC (near Orange Line), and remote work.
See: davearonson.com (main) * codosaur.us (code) * dare2xl.com (excellence).
Specialization is for insects. (Heinlein) - Have Pun, Will Babble! (Aronson)

What isn't elegant about the `&'?

···

On Fri, Dec 9, 2011 at 7:28 AM, Gavin Sinclair <gsinclair@gmail.com> wrote:

On Fri, Dec 9, 2011 at 8:18 PM, Robert Klemme > <shortcutter@googlemail.com> 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 2:28 PM, Gavin Sinclair <gsinclair@gmail.com> wrote:

On Fri, Dec 9, 2011 at 8:18 PM, Robert Klemme > <shortcutter@googlemail.com> wrote:

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

Very elegant. Except for that ghastly & :slight_smile:

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

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

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

···

On Sat, Dec 10, 2011 at 9:35 PM, Dave Aronson <rubytalk2dave@davearonson.com> wrote:

On Sat, Dec 10, 2011 at 15:07, Robert Klemme <shortcutter@googlemail.com> wrote:

On Sat, Dec 10, 2011 at 2:18 PM, Marc Heiler <shevegen@linuxmail.org> 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.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

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

···

On Fri, Dec 9, 2011 at 2:42 PM, Wayne Brisette <wbrisett@att.net> 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?

--
http://richardconroy.blogspot.com | http://twitter.com/RichardConroy

Wayne Brisette писал 09.12.2011 18:42:

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

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.

···

--
   WBR, Peter Zotov.

Josh Cheek <josh.cheek@gmail.com> 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.

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 1:38 AM, Josh Cheek <josh.cheek@gmail.com> wrote:

>
> Very elegant. Except for that ghastly & :slight_smile:
>
What isn't elegant about the `&'?

> >
> > 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"?

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)`

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:

.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.

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 Fri, Dec 9, 2011 at 7:27 PM, Gavin Sinclair <gsinclair@gmail.com> wrote:

On Sat, Dec 10, 2011 at 1:38 AM, Josh Cheek <josh.cheek@gmail.com> wrote:

On Sat, Dec 10, 2011 at 7:18 AM, Marc Heiler <shevegen@linuxmail.org> wrote:

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.

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 11:35 PM, Josh Cheek <josh.cheek@gmail.com> wrote:

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