In Ruby, Is Truthiness Idiomatic for a Method Name Ending with a Question Mark

In ruby, is truthiness idiomatic for a method name ending with a question mark?

It is usual for methods ending with ? to return either true or false but it is not systematic and no core method will assume it.

An example in the core classes is Numeric#nonzero? which never returns true or false.

42.nonzero? # => 42

The library Set has add? and delete? too. I wish Enumerable#one? returned nil or false to distinguish cases where the count is zero from when it is greater than one.

A similar example are the comparison operators (<, >, ...), which usually return only true or false. Here again exceptions exist for Module's operators that will return nil instead when the two modules are not related:

Array > Enumerable  # => false
Array > Fixnum # => nil

Should a method ending in ? (question mark) return only a boolean?

A method ending with ? should return a value which can be meaningfully evaluated to true or false. If you want to ensure a boolean return, you can do so by adding a double bang to the finder.

def is_subscribed?(feed_url)
!!Subscription.find_by_user_id_and_feed_id(self[ :id ], Feed.find_by_feed_url(feed_url))
end

How can I write method with question mark using define_method

What you want is this:

define_method("#{roleVal}?") { ... }

How to define an inner method whose name finish with a question mark and that has access to the outer method variables?

How to define an inner method whose name finish with a question mark and that has access to the outer method variables?

Ruby doesn't have inner methods, so you cannot define one.

Does checking the truthiness of a method also run it in a conditional statement (if)?

Sure, that method is called, executed and its return value is used as your if condition.

Just to recap: only nil and false are falsey value, any other value is considered truthy.

Method returning true instead of false for certain arguments

The problem with your code is that this line:

str.split.select { |x| !x.include?("o" "O") && !x.include?("x" "X") }

will return an empty array [] in a situation where the string has no 'x's or 'o's. In Ruby, any array is considered truthy, even an empty one. So your code is always returning true here. You can fix it by checking that the array is empty:

def XO(str)
x = str.count("o" "O")
y = str.count ("x" "X")
if x == y
true
elsif
str.split.select { |x| !x.include?("o" "O") && !x.include?("x" "X") }.empty?
true
else
false
end
end

This code will run fine and do what you want. However, it is overly complicated! If you look at your requirements:

  • returns true if a string has the same amount of 'x's and 'o's
  • returns false if there are more x's than o's and vice versa
  • returns true when NO x's and o's are present.

When there are no x's and no o's, you could say there are in fact 0 x's and 0 o's, which means there is the same amount of 'x's and 'o's. Which means you can just do this:

def XO(str)
x = str.count("o" "O")
y = str.count ("x" "X")
x == y
end

In situations where there aren't any 'x's or 'o's, you'll have 0 == 0 which returns true, just like you want.

How does Ruby evaluate the class of an object when evaluating the truthiness in a condition?

There are only two objects which evaluate falsy. Ruby simply checks whether the object is one of those two. Period.

Note that one of the foundations of OO is simulation: an object can simulate another object. This is not true here: it is impossible to simulate nil or false. This is one of those annoying cases where Ruby violates OO, very similar to Object#equal?.



Related Topics



Leave a reply



Submit