Reputation: 61540
I am working in Ruby and have found the need to have conditional return statements at the end of some/most of my methods.
Here is what I have:
# <ident-list> -> [ident] <ident-A>
def ident_list(keys)
id = nil
ident_a_node = nil
## method hidden
return IdentifierListNode.new(id, ident_a_node) unless id.nil?
return nil
end
Is there a better/cleaner way to go about this with multiple returns?
Upvotes: 1
Views: 7171
Reputation: 10825
While you can make the return into a one-liner, this is one of those cases where I think being a little more explicit and skimmable is worth it. This is certainly debatable, but after working on a lot of different teams with rubyists I think that if you go to a one line version there's a good chance that you (or another member of your team) may misinterpret the potential exit states when looking at the code later.
I'd suggest:
def ident_list(keys)
id = nil
ident_a_node = nil
## method hidden
return IdentifierListNode.new(id, ident_a_node) unless id.nil?
nil
end
or if you don't care about the difference between false/nil in this case, even better:
def ident_list(keys)
id = nil
ident_a_node = nil
## method hidden
return IdentifierListNode.new(id, ident_a_node) if id
nil
end
Pretty much everyone who has worked in ruby for a little while understands that a final value in a method is implicitly returned (i.e. this will return nil if no return beforehand) - and you can get that a glance. My experience is that lots of people who have worked with ruby for a long time still get tripped up by variations of && and less explicit conditional returns.
If you are determined to use a one-liner, I'd go with Ryan's answer, mostly because it's an idiom that is used fairly commonly and less likely to be confused:
def ident_list(keys)
id = nil
ident_a_node = nil
## method hidden
id && IdentifierListNode.new(id, ident_a_node)
end
One caveat to this approach is that you actually end up with three possible return states instead of two (the other options will only return nil or your new IdentifierListNode
):
IdentifierListNode
objectUpvotes: 1
Reputation: 1015
When using double ampersands (AND operator), the right hand will return, so you can shorten Adrian's answer to this:
return (id && IdentifierListNode.new(id, ident_a_node))
As the first part of the condition checks for the presence of id, nil will be returned. If this is the last statement, you can remove the "return" altogether since it's implied in Ruby, leaving just:
id && IdentifierListNode.new(id, ident_a_node)
Tested with the following:
def check(input)
input && input * 2
end
check(nil) # => nil
check(123) # => 246
Upvotes: 3
Reputation: 6436
As it stands you'll be making nil checks all over the place.
I know this might not answer directly your question, but you should try to adopt other coding pattern. Worth reading:
How to avoid “!= null” statements in Java?
Upvotes: 0
Reputation: 4539
The last line before the end
can be simply
IdentifierListNode.new(id, ident_a_node) unless id.nil?
The last statement executed is the return value of the method. If id
is nil, the statement will evaluate as nil, and if not then the new IdentifierListNode instance will be returned.
Upvotes: 5
Reputation: 7725
return (id.nil? ? nil : IdentifierListNode.new(id, ident_a_node))
Upvotes: 1