1
\$\begingroup\$

I've got the following code, which works, but seems repetitive. Under DRY principle, how can I clean this up?

puts "Blurt out a word"
word = gets.chomp
word_list = []
word_list.push word

until word == ""
  word = gets.chomp
  word_list.push word
end

puts word_list.sort
\$\endgroup\$

migrated from stackoverflow.com Aug 14 '12 at 18:23

This question came from our site for professional and enthusiast programmers.

6
\$\begingroup\$
puts "Blurt out a word"
word_list = []
while word_list.last != ""
  word_list << gets.chomp
end
puts word_list.sort

If you prefer the until:

puts "Blurt out a word"
word_list = []
until word_list.last == ""
  word_list << gets.chomp
end
puts word_list.sort

You can also do it shorter:

puts "Blurt out a word"
word_list = []
word_list << gets.chomp until word_list.last == "" 
puts word_list.sort

Remark: The last (empty) line is also returned. To skip the empty line you may use:

puts word_list[0..-2].sort
\$\endgroup\$
2
\$\begingroup\$

Perhaps

puts 'Blurt..'
puts STDIN.take_while{|line| line !~ /^$/}.map(&:chomp).sort

Edit: Why is this better? Because unlike other approaches it never modifies a variable that is assigned once. Thus it preserves the referential integrity. That is this is a functional programming approach in comparison with others which (as of now) follow an imperative model. The succinctness that results from it is just a bonus.

\$\endgroup\$
  • \$\begingroup\$ you code solo, don't you? \$\endgroup\$ – Ryan Miller Aug 15 '12 at 19:24
  • \$\begingroup\$ too hard to read? \$\endgroup\$ – rahul Aug 16 '12 at 2:51
  • \$\begingroup\$ i can read it just fine, understanding what it is doing is taking a lot longer than it should. \$\endgroup\$ – Ryan Miller Aug 16 '12 at 13:55
  • \$\begingroup\$ +1. @Ryan: This is simple functional programming style, IMO we should expect a competent team to have no problems with it. @rahul: If you have the abstraction String#present? you can even write a slightly more declarative STDIN.take_while(&:present?).map(&:chomp).sort. \$\endgroup\$ – tokland Aug 25 '12 at 19:26
1
\$\begingroup\$

Keeping as much of your style as possible, the simple way to avoid repetition is to pull the repetitive phrases inside your loop.

Now I'm assuming that what prevented you from doing this was the fact that Ruby's 'until' loop evaluates the exit condition at the top of the loop, which will therefore throw an error unless you've initialised 'word'.

This inconvenience can be avoided by moving from an 'until' loop to an infinite loop with an internal test / decision / exit condition, like so:

puts "Blurt out a word"
word_list = []
loop do
word= gets.chomp
    if word == "" 
        break
    else 
        word_list.push word
    end 
end
puts word_list.sort

Now 'word' is defined before the exit condition is evaluated. And as a useful aside, a blank entry is not inserted into 'word_list'.

There are of course many other ways of doing this -- Ruby allows for cleverness over clarity. The above simply refactors your code and removes the repetition.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.