Saturday, January 13, 2007

XOR

While making my scope_out plugin, I wanted to ensure that exactly one of the 2 possible hash keys (:value or :conditions) were passed to the method. Rather than using a long and ugly if statement, I wanted to use the xor operator (^). Unfortunately ^ is not a regular boolean operator and is not defined for strings or arrays which can be passed as values to my hash. So I came up with this as a workaround:

if (options[:value] && true) ^ (options[:conditions] && true)
#do stuff
else
raise "use either :value or :conditions, but not both"
end


The return value of an and expression is the right hand side of that expression if the left part is true. Therefore the hash values are both coerced into either boolean or nil types, both of which define the ^ method.



Update:
Since publishing the plugin I realized that there are reasons where you would want to pass nil or false to options[:value] so I have changed the code to the following:


if (options.has_key?(:value) ^ options.has_key?(:conditions)
#do stuff
else
raise "use either :value or :conditions, but not both"
end

No comments: