2

在用另一种语言长期编码后回到 Ruby 后,我经常假设foo.sort, foo.map {...},foo.sub /bar/, 'zip'改变foo. 当然我的意思是foo.sort!,等等。但这通常需要 3 或 4 次调试才能注意到。同时,排序被计算出来,但没有分配给任何东西。我可以让 ruby​​ 警告丢失的左值,就像 C 编译器警告函数被忽略的返回值一样吗?

4

2 回答 2

2

你的意思是像 Perl 有点臭名昭著的“map在 void 上下文中使用”?我不知道Ruby有这样的事情。听起来你需要更多的单元测试来捕捉这样的错误,然后它们才能深入到你的代码中,以至于被认为是错误。

请记住,Ruby 比 Perl 等语言灵活得多。例如,以下代码可能有用:

def rewrite(list)
  list.map do |row|
    row += '!'
  end
end

现在从技术上讲,这是map在 void 上下文中,但因为它被用作返回值,它可能会在其他地方被捕获。调用者有责任使用它。将方法本身标记为某种警告是从大多数 linting 类型工具可以执行的操作中删除的级别。

于 2016-12-04T22:25:50.660 回答
1

这是一个非常基本的解析器:

@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) }

它会检查当前目录中的每个 ruby​​ 脚本,看是否有sort,map或.sub!=putsprintreturn

这只是一个开始,但也许它可以帮助您找到一些低调的果实。但是,有很多误报。

更复杂的版本可以使用抽象语法树,例如Ripper

于 2016-12-04T23:16:46.677 回答