Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > seeking advice on Ruby code style

Reply
Thread Tools

seeking advice on Ruby code style

 
 
Alexandru E. Ungur
Guest
Posts: n/a
 
      01-11-2007
Hi all,

I recently recently released my first vim script, nothing big, it
just toggles words between true/false, on/off, etc. You can find
more here http://vim.sourceforge.net/scripts/s...script_id=1748
if you want.

The thing is, I'm not sure if I chose the most elegant/beautiful/**
way to solve the problem, basically I ended up deciding between
two ways of handling the problem:

class String
@@pairs = [ %w[on off], %w[yes no], %w[true false] ]

def toggle_word1
pair = @@pairs.select{|p| p.include?(downcase)}.flatten
return nil if pair.empty?
antiword = pair[pair.index(downcase) ^ 1]
case self
when upcase then return antiword.upcase
when downcase then return antiword.downcase
when capitalize then return antiword.capitalize
else return antiword
end
end

def toggle_word2
pair = @@pairs.select{|p| p.include?(downcase)}.flatten
wordcase = %w[upcase downcase capitalize].detect {|c| send(c) == self} || "downcase"
pair.empty? ? nil : pair[pair.index(downcase) ^ 1].send(wordcase)
end
end

Both toggle_word1 and toggle_word2 are doing the exact same thing, that is:
"Yes".toggle_word1 # => "No"
"No".toggle_word2 # => "Yes"
and so on.

My question is, which is more elegant, more... rubyful ?
I like that toggle_word1 is almost like plain english, especially
that "case" construct, but I like in toggle_word2 that the same "case"
construct was replaced with a single line of code, well with two
actually. However perhaps toggle_word2 is a little too much
code golfing...?


Thank you in advance for your comments,
Have a nice day everyone,
Alex

 
Reply With Quote
 
 
 
 
Gregory Seidman
Guest
Posts: n/a
 
      01-11-2007
On Thu, Jan 11, 2007 at 10:49:29PM +0900, Alexandru E. Ungur wrote:
> I recently recently released my first vim script, nothing big, it
> just toggles words between true/false, on/off, etc. You can find
> more here http://vim.sourceforge.net/scripts/s...script_id=1748
> if you want.

[...]

Here's a cleaner implementation (assuming I understand it correctly):

class String
PAIRS = Hash[*%w(on off yes no true false)]
PAIRS.to_a.each { |v,k|
v.freeze
k.freeze
PAIRS[k] = v
}
PAIRS.freeze

def toggle_word
return self unless antiword = PAIRS[downcase]
case self
when upcase
antiword.upcase
when downcase
antiword.downcase
when capitalize
antiword.capitalize
else
antiword
end
end

end

Note that I am avoiding class variables (which are almost always the wrong
choice, see
http://www.oreillynet.com/ruby/blog/..._variab_1.html
) and using a constant instead. The freezing is optional, but I like to
freeze what my constants point to. Notice that I am reversing all the
entries in the hash so it's easy to toggle both ways. I kept the case
statement from toggle_word1 over the golfing in toggle_word2, but I'll
point out that Ruby only requires a return when short-circuiting.

> Thank you in advance for your comments,
> Have a nice day everyone,
> Alex

--Greg


 
Reply With Quote
 
 
 
 
gwtmp01@mac.com
Guest
Posts: n/a
 
      01-11-2007

On Jan 11, 2007, at 8:49 AM, Alexandru E. Ungur wrote:
> My question is, which is more elegant, more... rubyful ?
> I like that toggle_word1 is almost like plain english, especially
> that "case" construct, but I like in toggle_word2 that the same "case"
> construct was replaced with a single line of code, well with two
> actually. However perhaps toggle_word2 is a little too much
> code golfing...?


I think in both cases you are repeating too much work that could be
done ahead of time. How about:

class String
base = %w[on off yes no true false]
all = base
all += base.map {|x| x.upcase }
all += base.map {|x| x.capitalize }
t = Hash[*all]
TOGGLE = t.merge t.invert

def toggle_word3
TOGGLE[self] || TOGGLE[downcase]
end
end

if __FILE__ == $0
require 'test/unit'

class My_Test < Test::Unit::TestCase
def test_toggle_word3
assert_equal('off', 'on'.toggle_word3)
assert_equal('Off', 'On'.toggle_word3)
assert_equal('YES', 'NO'.toggle_word3)
assert_equal('yes', 'nO'.toggle_word3)
assert_equal('false', 'true'.toggle_word3)
assert_equal(nil, 'unknown'.toggle_word3)
end
end
end


Gary Wright




 
Reply With Quote
 
Gregory Seidman
Guest
Posts: n/a
 
      01-11-2007
On Thu, Jan 11, 2007 at 11:40:52PM +0900, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
[...]
> TOGGLE = t.merge t.invert


Yow, how did I miss Hash#invert? That's beautiful.

--Greg


 
Reply With Quote
 
William James
Guest
Posts: n/a
 
      01-11-2007

Alexandru E. Ungur wrote:
> Hi all,
>
> I recently recently released my first vim script, nothing big, it
> just toggles words between true/false, on/off, etc. You can find
> more here http://vim.sourceforge.net/scripts/s...script_id=1748
> if you want.
>
> The thing is, I'm not sure if I chose the most elegant/beautiful/**
> way to solve the problem, basically I ended up deciding between
> two ways of handling the problem:
>
> class String
> @@pairs = [ %w[on off], %w[yes no], %w[true false] ]
>
> def toggle_word1
> pair = @@pairs.select{|p| p.include?(downcase)}.flatten
> return nil if pair.empty?
> antiword = pair[pair.index(downcase) ^ 1]
> case self
> when upcase then return antiword.upcase
> when downcase then return antiword.downcase
> when capitalize then return antiword.capitalize
> else return antiword
> end
> end
>
> def toggle_word2
> pair = @@pairs.select{|p| p.include?(downcase)}.flatten
> wordcase = %w[upcase downcase capitalize].detect {|c| send(c) == self} || "downcase"
> pair.empty? ? nil : pair[pair.index(downcase) ^ 1].send(wordcase)
> end
> end
>
> Both toggle_word1 and toggle_word2 are doing the exact same thing, that is:
> "Yes".toggle_word1 # => "No"
> "No".toggle_word2 # => "Yes"
> and so on.
>
> My question is, which is more elegant, more... rubyful ?
> I like that toggle_word1 is almost like plain english, especially
> that "case" construct, but I like in toggle_word2 that the same "case"
> construct was replaced with a single line of code, well with two
> actually. However perhaps toggle_word2 is a little too much
> code golfing...?
>
>
> Thank you in advance for your comments,
> Have a nice day everyone,
> Alex


class String
def toggle_word3
words = %w[on off yes no true false]
word = words[ i = words.index(downcase) ]
anti = words[ i + (i%2>0 ? -1 : 1 ) ]
%w( capitalize upcase ).each{|meth|
return anti.send(meth) if word.send(meth) == self }
anti
end
end

 
Reply With Quote
 
Alexandru E. Ungur
Guest
Posts: n/a
 
      01-11-2007
Boy, am I glad I asked for advice...
I hesitated for a few days to ask for advice on this, since I thought:
this is too easy, how to ask for advice on such a simple problem?, I
mean, in how many ways you can toggle a word, right? Now I feel really
dumb... as I've seen, the answer is: in many and **very**
interesting ways.
Simply amazing and enlightening...

A *big* thank you to you all!
All the best,
Alex

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Seeking C# references about Ruby Code block functionality dkmd_nielsen Ruby 3 05-18-2007 01:04 PM
Seeking advice about JavaScript code/style psema4 Javascript 2 07-23-2006 11:07 PM
new to ruby, seeking advice en.eric.m@gmail.com Ruby 4 05-17-2006 02:22 PM
Seeking advice on what to buy for Win98/XP home network... Sunny Side Wireless Networking 7 07-31-2004 01:47 AM
Need help with Style conversion from Style object to Style key/value collection. Ken Varn ASP .Net Building Controls 0 04-26-2004 07:06 PM



Advertisments