new to Ruby - pls help in translating this

C

Corey Jewett

Or, in keeping with the DRY and KISS principles I humbly submit the
lowly shell command, uniq, instead of Ruby at all:

$ uniq -d <file>

e.g.

/tmp corey$ cat foo
1
1
2
3
3
4
/tmp corey$ uniq -d foo
1
3
/tmp corey$

Although, it was interesting to see the diversity of Ruby solutions.

Corey
 
P

pat eyler

Or, in keeping with the DRY and KISS principles I humbly submit the
lowly shell command, uniq, instead of Ruby at all:

$ uniq -d <file>

e.g.

/tmp corey$ cat foo
1
1
2
3
3
4
/tmp corey$ uniq -d foo
1
3
/tmp corey$

but it doesn't always work:
pate@linux:~/scratch> cat nums
1
2
3
4
4
5
6
5
7
pate@linux:~/scratch> uniq -d files
uniq: files: No such file or directory
pate@linux:~/scratch> uniq -d nums
4
pate@linux:~/scratch>


you need to do:
pate@linux:~/scratch> sort -n nums | uniq -d
4
5


but if this is supposed to be part of a larger program, shell
is probably the wrong way to go about it.
 
G

Gregory Brown

Why? Backticks are great.

Platform independence?

Granted I get away with a lot via MingGW, but if you want to code on
Linux / OS X and work for people who want the code to run on
Windows... well... platform independance is important

Though it does of course depend what you're working on. :)
 
C

Chad Perrin

Platform independence?

Granted I get away with a lot via MingGW, but if you want to code on
Linux / OS X and work for people who want the code to run on
Windows... well... platform independance is important

Though it does of course depend what you're working on. :)

Good point. Okay, you win.

. . except when I'm writing unix administration scripts.
 
G

Gregory Brown

Good point. Okay, you win.

. . . except when I'm writing unix administration scripts.

Of COURSE! :)
You can even port a lot of those straight to windows via MSys and MinGW.
(Or it's ugly cousin Cygwin)
 
W

William James

Eric said:
seen = {}

ARGF.each do |elem|
print elem if seen.include? elem
seen[elem] = true
end

seen = {}
while s = gets
print s if seen.key? s
seen[ s ] = nil
end

Or:

seen = Hash.new(0)
while s = gets
print s if ( seen += 1 ) > 1
end
 
W

William James

William said:
Eric said:
seen = {}

ARGF.each do |elem|
print elem if seen.include? elem
seen[elem] = true
end

seen = {}
while s = gets
print s if seen.key? s
seen[ s ] = nil
end

Or:

seen = Hash.new(0)
while s = gets
print s if ( seen += 1 ) > 1
end


seen, s = Hash.new(0)
print s if ( seen += 1 ) > 1 while s = gets
 
W

William James

William said:
William said:
Eric said:
seen = {}

ARGF.each do |elem|
print elem if seen.include? elem
seen[elem] = true
end

seen = {}
while s = gets
print s if seen.key? s
seen[ s ] = nil
end

Or:

seen = Hash.new(0)
while s = gets
print s if ( seen += 1 ) > 1
end


seen, s = Hash.new(0)
print s if ( seen += 1 ) > 1 while s = gets


seen = Hash.new(0)
print if ( seen[$_] += 1 ) > 1 while gets
 
E

Eric Hodel

William said:
William said:
Eric Hodel wrote:

seen = {}

ARGF.each do |elem|
print elem if seen.include? elem
seen[elem] = true
end

seen = {}
while s = gets
print s if seen.key? s
seen[ s ] = nil
end

Or:

seen = Hash.new(0)
while s = gets
print s if ( seen += 1 ) > 1
end


This is starting to get pointlessly obfuscated.
seen, s = Hash.new(0)
print s if ( seen += 1 ) > 1 while s = gets


Stop. You're making things hard to read for the new people.
seen = Hash.new(0)
print if ( seen[$_] += 1 ) > 1 while gets

I can't read that so I don't know how you expect someone new to Ruby
to read it.

I've never seen 'ruby golf' do anything positive. I find it
especially inappropriate to be performing these vile manipulations
while trying to show new people idiomatic Ruby like they asked for:
 
W

William James

Eric said:
William said:
William James wrote:
Eric Hodel wrote:

seen = {}

ARGF.each do |elem|
print elem if seen.include? elem
seen[elem] = true
end

seen = {}
while s = gets
print s if seen.key? s
seen[ s ] = nil
end

Or:

seen = Hash.new(0)
while s = gets
print s if ( seen += 1 ) > 1
end


This is starting to get pointlessly obfuscated.
seen, s = Hash.new(0)
print s if ( seen += 1 ) > 1 while s = gets


Stop. You're making things hard to read for the new people.
seen = Hash.new(0)
print if ( seen[$_] += 1 ) > 1 while gets

I can't read that so I don't know how you expect someone new to Ruby
to read it.


A standard Ruby idiom: instead of 3 lines . . .

if test
print "ok"
end

.. . . 1 line:

print "ok" if test

Also, as in Awk, "print" with no argument prints the line just read.
Very simple. If one needs to explicitly refer to the line just read,
one uses "$_".

And "while gets" is simpler and clearer than "ARGF.each do |elem|".
 
J

James Edward Gray II

Also, as in Awk, "print" with no argument prints the line just read.
Very simple. If one needs to explicitly refer to the line just read,
one uses "$_".

And "while gets" is simpler and clearer than "ARGF.each do |elem|".

You would get a lot of support in Perland, but this kind of code is
very out of fashion in the Ruby community.

James Edward Gray II
 
C

Chad Perrin

You would get a lot of support in Perland, but this kind of code is
very out of fashion in the Ruby community.

I can see, for readability's sake, wanting to avoid non-explicit data
handling like using "print" with no argument. Yes, that's the sort of
thing that allows three lines of Perl to do the same work at a dozen or
more of many other languages, but it's not very clear and is easy to
break later when maintaining the script.

I don't see any particular reason to regard "ARGF.each do |elem|" as
better than "while gets", though. The latter of the two is more like
natural language, reads clearly, and is pretty much intuitively
understandable even to people who have never touched the language
before. As I understand it, the "Ruby way" tends toward simplicity,
elegance, and ease of reading, writing, and maintaining. From what I
can see, "while gets" satisfies those preferences better than "ARGF.each
do |elem|". In fact, I'd say that regardless of whether "ARGF.each do
|elem|" is what "everyone uses", it is "while gets" that seems to best
suit the spirit of the "Ruby way".

. . and even if I'm missing some esoteric point regarding how the
language works, and the way "while gets" operates does NOT suit as well
as I think at first glance, perhaps it SHOULD.

Please let me know if I'm missing something. I've got a head full of
snot today, and the sinus pressure might just be making me stupid.
 
J

Joel VanderWerf

Chad Perrin wrote:
...
I don't see any particular reason to regard "ARGF.each do |elem|" as
better than "while gets", though. The latter of the two is more like

"ARGF.each do |elem|" has two advantages:

(1) easier to modify to use a different iteration method, such as map or
grep.

(2) easier to modify to use a different kind of enumerable, like an
array or string, rather than a file or a duck-file like ARGF.

(1) and (2) mean that code written using "ARGF.each do |elem|" can more
easily be abstracted/refactored into library code. Of course, if you are
writing a one-liner...

Also, I prefer being explicit about the variable elem, rather than using
$_, but that's me.
 
J

James Edward Gray II

I can see, for readability's sake, wanting to avoid non-explicit data
handling like using "print" with no argument.

`while gets` is also "non-explicit". It makes an assignment you do
not see. Compare with:

ARGF ... each ... |line|

That shows the whole process:

take the input files ... one line at a time ... and slot them
right here

You would be surprised how hard the gets() version can make it to see
errors. Here's actual code from a Ruby Quiz submission, that
certainly does not work as the author intended (though it may work
fine in many cases):

# ...

if $0 == __FILE__
cwstr = nil
if FileTest.file?( ARGV[0] )
File.open( ARGV[0] ) { cwstr = gets(nil) }
end
$stdout << CrossWord.build( cwstr )
end

It took me a while to spot the issue. How about you?

Many Rubyists also think something like `line` is prettier than $_.

I hear you though. I came to Ruby through Perl and in the beginning,
I used the default variable plenty. I won't be surprised if you
search the archives and find me on the other side of this
discussion. Now though, I've come to value Ruby's elegance and $_
just looks wrong to me. I guess you can say I'm assimilated.

The moral: $_ works fine (for now!). Use it if you like. Ignore
our sneers. ;)

James Edward Gray II
 
C

Chad Perrin

(1) easier to modify to use a different iteration method, such as map or
grep.

(2) easier to modify to use a different kind of enumerable, like an
array or string, rather than a file or a duck-file like ARGF.

(1) and (2) mean that code written using "ARGF.each do |elem|" can more
easily be abstracted/refactored into library code. Of course, if you are
writing a one-liner...

See, I knew I was being stupid about something. Thanks for setting me
straight.
 
C

Chad Perrin

`while gets` is also "non-explicit". It makes an assignment you do
not see. Compare with:

I was assuming a distinction between "explicit operation of the
language" and "explicit understanding of the intended functionality of
your code". Some issues with maintainability of something like "wile
gets" have been pointed out to me, though, and I retract my earlier
ramble. Mostly.
 
D

dblack

--8323328-1892095387-1135807992=:9248
Content-Type: MULTIPART/MIXED; BOUNDARY="8323328-1892095387-1135807992=:9248"

This message is in MIME format. The first part should be readable text,
while the remaining parts are likely unreadable without MIME-aware tools.

--8323328-1892095387-1135807992=:9248
Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed
Content-Transfer-Encoding: QUOTED-PRINTABLE

Hi --

quantities =3D Hash.new{|h, k| h[k]=3D0}
ARGF.each{|l| quantities[l.chomp.to_i] +=3D 1}
=20
=20
Since you're doing a h[x] +=3D 1 thing, you don't need to do the
auto-assignment in the block:

quantities =3D Hash.new(0)
=20
will work fine.

yes, saw that after pressing the submit button, but as said before
using this form of Hash.new is source of hard to track bugs.

[I didn't see this post until just now.]

I don't think so. The only problems I've ever seen people encounter
with it are from not knowing that:

Hash.new([])

will always give you the same object. But once you know that, and
therefore know when not to use it, it should be fine.


David

--=20
David A. Black
(e-mail address removed)

"Ruby for Rails", from Manning Publications, coming April 2006!
http://www.manning.com/books/black
--8323328-1892095387-1135807992=:9248--
--8323328-1892095387-1135807992=:9248--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,479
Members
44,900
Latest member
Nell636132

Latest Threads

Top