tags:

views:

151

answers:

7

Why isnt that working:

>> s = "hi"                                                             
=> "hi"                                                                 
>> s == ("hi"|"ho")                                                     
NoMethodError: undefined method `|' for "hi":String                     
 from (irb):2                                                           
>>

I don't get it.. Is there a solution for this kind of syntax? Because

s == ("hi"|"ho") 
#is shorther than 
s == "hi" || s == "ho"
+5  A: 

In most high level languages that syntax will not work, you have to stick to the longer syntax of:

s == "hi" || s == "ho"

Note that | is a bitwise or, whereas || is a regular or

AlbertoPL
+1  A: 

You could make it work that way:

irb> class Pair
       def initialize(strA,strB)
         @strA,@strB = strA,strB
       end
       def ==(string)
         string == @strA || string == @strB
       end
       def |(other)
         Pair.new(self,other)
       end
     end
#=> nil
irb> class String
       def |(other)
         Pair.new(self,other)
       end
       alias old_equals :==
       def ==(other)
         if other.kind_of? Pair
           other == self
         else
           old_equals other
         end
       end
     end
#=> nil
irb> ("one"|"two") == "one"
#=> true
irb> ("one"|"two") == "two"
#=> true
irb> ("one"|"two") == "three"
#=> false
irb> "one" == ("one"|"two")
#=> true
irb> "three" == ("one"|"two"|"three")
#=> true

But since this involves some monkey-patching of a fairly lowlevel class, I wouldn't advise relying on it. Other people will hate reading your code.

rampion
I'm... I'm not going to downvote you, because that's really a very neat answer to the question... but if you ever come near a codebase I maintain with that, I have a half-brick in a sock with your name lovingly engraved in it. Sound good?
Stephen Veiss
oh agreed. Just because it can be done doesn't mean it should be.
rampion
I've upvoted this because it's clever, but I agree with you that I would avoid doing this sort of thing in code you expect anyone but yourself to use.
Greg Campbell
+1  A: 

Ruby supports binary 'or' and other binary operations on values of type Fixnum and Bignum, meaning any integer. Bitwise operations aren't supported on strings or any other type, as far as I know.

As other people have mentioned, you probably want something other than binary operations altogether. However, you can easily get integer representations of characters, so you can compare characters like so:

a = "Cake"
b = "Pie"
puts a[0] | b[0] # Prints "83" - C is 67 and P is 80.

You can get an array of the comparisons easily with some conversions.

a = "Cake"
b = "Pie " # Strings of uneven length is trivial but more cluttered.

a_arr = a.split(//)
b_arr = b.split(//)
c_arr = []

a.each_with_index { |char, i| c.push(a[i].to_i | b[i].to_i) }
# If you *really* want an ASCII string back...
c = c_arr.collect(&:chr).join
Jesse Millikan
+8  A: 

Yes, the bitwise operator | is not defined in the String class: http://ruby-doc.org/core/classes/String.html

Consider this for expressiveness:

["hi", "ho"].include? myStr

irb(main):001:0> s = "hi"
=> "hi"
irb(main):002:0> ["hi", "ho"]
=> ["hi", "ho"]
irb(main):003:0>  ["hi", "ho"].include? s
=> true
irb(main):004:0> s = "foo"
=> "foo"
irb(main):005:0>  ["hi", "ho"].include? s
=> false
Aaron F.
Yep, if you have a list of values that you want to test for, just test if the list includes the value rather than poking through each item individually to see if they match.
Chuck
+3  A: 

You could use the include? method on array if you've got several == tests to do:

["hi", "ho"].include?(s)

Not shorter for two checks admittedly but it will be shorter for three or more.

Shadwell
+1  A: 

This syntax doesn't exist in any language as far as I know.

What you are saying

s == ("hi"|"ho")

Literally translates to 'bitwise OR the strings "hi" and "ho" together and then compare them with s'. If you can't see why this is not what you are looking for, try writing down the ASCII codes for "hi" and "ho" and then bitwise ORing them together. You are going to get complete gibberish.

muusbolla
A: 

You could use a regex:

Like so:

regex = /hi|ho/
s = "hi"
t = "foo"

s =~ regex
#=> 0

t =~ regex
#=> nil