After returning to Ruby from a long stint coding in another language, I regularly assume that foo.sort
, foo.map {...}
, foo.sub /bar/, 'zip'
will change foo. Of course I meant foo.sort!
, etc. But that usually takes 3 or 4 debugging potshots before I notice. Meanwhile, the sort is calculated, but then isn't assigned to anything. Can I make ruby warn about that missing lvalue, like a C compiler warns of a function's ignored return value?

- 2,934
- 2
- 35
- 56
-
Figuring out whether a method returns a value or not is unfortunately equivalent to solving the Halting Problem. – Jörg W Mittag Dec 04 '16 at 23:30
2 Answers
You mean like Perl's somewhat infamous "using map
in void context"? I don't know of Ruby having such a thing. Sounds like you need more unit testing to catch mistakes like this before they can worm into your code deeply enough to be considered bugs.
Keep in mind Ruby's a lot more flexible than languages like Perl. For example, the following code might be useful:
def rewrite(list)
list.map do |row|
row += '!'
end
end
Now technically that's a map
in a void context, but because it's used as a return value it might be captured elsewhere. It's the responsibility of the caller to make use of it. Flagging the method itself for some sort of warning is a level removed from what most linting type tools can do.

- 208,517
- 23
- 234
- 262
Here's a very basic parser :
@forgetful_methods = %w(sort map sub)
Dir['*.rb'].each do |script|
File.readlines(script).each.with_index(1) do |line, i|
@forgetful_methods.each do |method|
if line =~ /\.#{method}(?!!)/ && $` !~ /(=|\b(puts|print|return)\b|^#)/
puts format('%-25s (%3d) : %s', script, i, line.strip)
end
end
end
end
# =>
# brace_globbing.rb ( 13) : subpatterns.map{|subpattern| explode_extglob(match.pre_match+subpattern+match.post_match)}.flatten
# delegate.rb ( 11) : @targets.map { |t| t.send(m, *args) }
It checks every ruby script in the current directory for sort
, map
or sub
without !
that aren't preceded by =
, puts
, print
or return
.
It's just a start, but maybe it could help you find some of the low hanging fruits. There are many false positives, though.
A more complex version could use abstract syntax trees, for example with Ripper.

- 52,989
- 9
- 71
- 124
-
Mittag's "halting problem" comment, and tadman's concrete example, indeed suggest that low-hanging fruit is the best one can hope for. A few false positives from such a test are tolerable. – Camille Goudeseune Dec 05 '16 at 18:26