2

別の言語での長いコーディングから Ruby に戻った後、私は定期的にfoo.sort, foo.map {...},foo.sub /bar/, 'zip'がfooを変更すると思い込んでいます。もちろん、私はfoo.sort!などを意味していました。しかし、それは通常、気付く前に 3 つか 4 つのデバッグ ポットショットが必要です。一方、並べ替えは計算されますが、何にも割り当てられません。C コンパイラが関数の無視された戻り値を警告するように、左辺値の欠落について Ruby に警告させることはできますか?

4

2 に答える 2

2

Perl のやや悪名高い「map無効なコンテキストでの使用」のようなものですか? Rubyにそんな機能があるとは知りませんでした。バグと見なされるほどコードに深く侵入する前に、このような間違いを検出するために、より多くの単体テストが必要なようです。

Ruby は Perl などの言語よりもはるかに柔軟であることを覚えておいてください。たとえば、次のコード役立つ場合があります。

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

技術的mapには無効なコンテキストですが、戻り値として使用されるため、他の場所でキャプチャされる可能性があります。それを利用するのは呼び出し元の責任です。ある種の警告のためにメソッド自体にフラグを立てることは、ほとんどの 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) }

現在のディレクトリ内のすべてsortのruby​​ スクリプトをチェックしmapます。sub!=putsprintreturn

これはほんの始まりにすぎませんが、簡単に達成できる成果を見つけるのに役立つかもしれません。ただし、多くの偽陽性があります。

より複雑なバージョンでは、Ripperなどの抽象構文ツリーを使用できます。

于 2016-12-04T23:16:46.677 に答える