1. ホーム
  2. ruby

[解決済み] 変数_(アンダースコア)はどこで、どのように指定するのですか?

2023-05-02 21:13:58

質問

ほとんどの人が知っているのは _ のIRBにおける特別な意味は、最後の戻り値のためのホルダーであることですが、これは ではなく であり、私がここで尋ねていることではありません。

代わりに、私が質問しているのは _ について質問しているのです。ここでは、「気にしない変数」のような特別な振る舞いをするようです。 Prolog ). そのユニークな振る舞いを示す、いくつかの有用な例を紹介します。

lambda { |x, x| 42 }            # SyntaxError: duplicated argument name
lambda { |_, _| 42 }.call(4, 2) # => 42
lambda { |_, _| 42 }.call(_, _) # NameError: undefined local variable or method `_'
lambda { |_| _ + 1 }.call(42)   # => 43
lambda { |_, _| _ }.call(4, 2)  # 1.8.7: => 2
                                # 1.9.3: => 4
_ = 42
_ * 100         # => 4200
_, _ = 4, 2; _  # => 2

これらはすべてRubyで直接実行されました( puts が追加されています)、IRB の追加機能との衝突を避けるために、IRB ではなく Ruby で直接実行されました。

これはすべて私自身の実験の結果であり、この動作に関するドキュメントはどこにも見当たりません (確かに、検索するのが最も簡単なことではありません)。最終的には、このすべてが内部的にどのように動作しているのかに興味があり、SoftBank> の特別な機能をより正確に理解することができます。 _ . ですから、私はドキュメントへの参照と、できれば Ruby のソースコード (と、おそらくは RubySpec ) がどのように _ がRubyでどのような振る舞いをするのかを明らかにします。

注:この大部分は この議論 @Niklas B.

どのように解決するのですか?

引数名の重複" エラーを抑制するために、ソースに特別な処理があります。エラーメッセージが表示されるのは shadowing_lvar_gen の内部 parse.y , 1.9.3版では以下のようになります。 :

static ID
shadowing_lvar_gen(struct parser_params *parser, ID name)
{
    if (idUScore == name) return name;
    /* ... */

idUScore で定義されている id.c のようにします。

REGISTER_SYMID(idUScore, "_");

同様の特別な処理は warn_unused_var :

static void
warn_unused_var(struct parser_params *parser, struct local_vars *local)
{
    /* ... */
    for (i = 0; i < cnt; ++i) {
        if (!v[i] || (u[i] & LVAR_USED)) continue;
        if (idUScore == v[i]) continue;
        rb_compile_warn(ruby_sourcefile, (int)u[i], "assigned but unused variable - %s", rb_id2name(v[i]));
    }
}

の2行目で警告が抑制されていることがわかると思います。 for ループの2行目で警告が抑制されていることがわかります。

の唯一の特別な扱いは _ は、1.9.3 のソースで見つけた唯一の特別な処理です: 名前の重複エラーは抑制され、未使用変数の警告は抑制されています。この2つ以外には _ は他の変数と同じように単なる古い変数です。の(マイナーな)特殊性についてのドキュメントは知りません。 _ .

Ruby 2.0では idUScore == v[i] のテストが warn_unused_var への呼び出しに置き換わります。 is_private_local_id :

if (is_private_local_id(v[i])) continue;
rb_warn4S(ruby_sourcefile, (int)u[i], "assigned but unused variable - %s", rb_id2name(v[i]));

is_private_local_id で始まる変数に対する警告を抑制します。 _ :

if (name == idUScore) return 1;
/* ... */
return RSTRING_PTR(s)[0] == '_';

ではなく、単に _ そのものではなく、です。そのため、2.0では少し緩やかになっています。