Ruby Case ステートメントとピン留めは、attr_reader では機能しません

概要

このコードは動作します:

class Hello
  def initialize
    @name = "Paul"
  end

  def say_name(maybe_name)
    name = self.name
    case maybe_name
    in ^name
      puts "Hello, Paul!"
    else
      puts "No match"
    end
  end

  private

  attr_reader :name
end

Hello.new.say_name("Paul") # "Hello, Paul!"

ただし、name = self.name を削除すると、ピン留めされた変数に対してローカル変数名が取得されません。

これは Ruby のバグですか、それとも意図されたものですか?ローカル変数でのみ機能すると思いますか?この行を削除すると、say_hello メソッド内で name が nil になりますが、定義されています。

解決策

その特定のエラーは意図的なものです。存在しないローカル変数を参照すると、例外が発生します。

ドキュメントに記載されているように、これはあらゆる種類の変数で動作します。「インスタンス変数、グローバル変数、クラス変数を固定することもできます」。ただし、単純な ^variable 構文はメソッドでは機能しません。コードを機能させるには、インスタンス変数 @name を直接参照する必要があります。

case maybe_name
in ^@name
  # ...
end

または、「括弧を使用して任意の式の結果をピン留めする」ことができる ^(式) 構文を使用します: (「任意の式」はメソッド呼び出しです)

case maybe_name
in ^(name)
  # ...
end