38829


ruby で、 `attr_reader :foo` のように、 reader のみを定義した変数に対して、  
別のメソッドの中で、上の `attr_reader` で用いたシンボルである `:foo` を用いて、 set_variable したくなりました。

その際に、 `Object#instance_variable_set` は、`:foo` は引数として受け付けずに、  
`:@foo` とする必要があることを知りました。

[code]

    obj.instance_variable_set(:foo, 1)
    #=> `foo' is not allowed as an instance variable name
    
    obj.instance_variable_set(:@foo, 1)
    #=> OK
    
[/code]

そこで生じた疑問が次です。

  * `instance_variable_set(:foo, 1)` で @foo に bind してくれた方がシンプルな気がしたのですが、関数がこのような動作になっている、何か特別が理由があったりするのでしょうか？

というのも、今やりたいことを、今自分が持っている知識でやろうとすると、こうなりました。

[code]

    class Foo
      attr_reader :foo
      def set_var_by_sym(sym, val)
        var_sym = ('@' + sym.id2name).intern
        instance_variable_set(var_sym, val)
      end
    end
    
[/code]

なんというか、少し、無駄に面倒なコードになっている気がしたので。。


CC BY-SA 3.0
2017-10-18T04:10:33.353
38820
2017-10-18T08:20:23.467
754
question
ruby
ruby instance_variable_set はなぜ @ マークのリテラルが必要？


`instance_variable_set`は引数として文字列を受け付けるので単に文字列の中で式展開でシンボルを埋め込むだけでよさそうです。

参考: <https://docs.ruby-lang.org/en/2.4.0/Object.html#method-i-
instance_variable_set>

[code]

    class Foo
      attr_reader :foo
      def set_var_by_sym(sym, val)
        instance_variable_set("@#{sym}", val)
      end
    end
    
[/code]

またSymbolに値を式展開して埋め込みたいなら以下のようにも書けます。

[code]

    class Foo
      attr_reader :foo
      def set_var_by_sym(sym, val)
        instance_variable_set(:"@#{sym}", val)
      end
    end
    
[/code]

> instance_variable_set(:foo, 1) で @foo に bind
> してくれた方がシンプルな気がしたのですが、関数がこのような動作になっている、何か特別が理由があったりするのでしょうか？

何をもってシンプルと捉えるかは人それぞれだと思いますが`:@foo`を渡すと`@foo`に値が入る方が直接対応していてシンプルではないでしょうか?

Rubyの動作については以下のサイトからバグレポートやフィーチャーリクエストを送ることが出来ます。  
`:foo`で`@foo`にbindしてほしいユースケースがあるのであれば、フィーチャーリクエストを送ってみるとよさそうです。  
<https://bugs.ruby-lang.org/>


CC BY-SA 3.0
2017-10-18T06:10:32.907
38829
2017-10-18T06:10:32.907
2599
38820
answer


正確なところは思想を知っている人でないと答えられないので、想像です。正確なところは個々で回答を得るのは難しいと思います。

リファレンスの[インスタンス変数の説明](https://docs.ruby-
lang.org/ja/latest/doc/spec=2fvariables.html#instance)には

> `@'で始まる変数はインスタンス変数

とあり、また、[Object#instance_variables](https://docs.ruby-
lang.org/ja/latest/method/Object/i/instance_variables.html)の戻り値が

[code]

    [:@foo, :@bar]
    
[/code]

となることを考えると、インスタンス変数の変数名は'@'を含めたもの、つまり`@var`は`var`にインスタンス変数であることを示すマーク`@`+変数名`var`、ではなく`@var`で一つの変数名で、`@`から始まっているのでインスタンス変数として扱われる、という考え方であろうと想像できます。


CC BY-SA 3.0
2017-10-18T08:20:23.467
38835
2017-10-18T08:20:23.467
5793
38820
answer