質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

2回答

503閲覧

instance_evalについて

hoge_nakatani

総合スコア63

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2020/01/22 02:02

m = Module.new CONST = "Constant in Toplevel" _proc = Proc.new do CONST = "Constant in Proc" end m.instance_eval(<<-EOS) CONST = "Constant in Module instance" def const CONST end EOS m.module_eval(&_proc) p m.const

module M CONST = "Hello, world" end M.instance_eval(<<-CODE) def say CONST end CODE p M::say

①の「m.instance_eval(<<-EOS)」は繋がって出力されるのに
②はの「M.instance_eval(<<-CODE)」はエラーになるのはなぜなのでしょうか?
同じ文字列の「instance_eval」なのに処理が異なる理由が調べましたがわかりませんでした。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/01/22 02:14

M.instance_eval(<<-CODE)では、どのようなエラーが出ましたか?
hoge_nakatani

2020/01/22 11:55

お世話になっています。 uninitialized constant #<Class:M>::CONST 9:in `<main>' というえらーが返ってきます。
guest

回答2

0

ベストアンサー

エラーメッセージを見ると、Mの特異クラスのCONSTを参照しようとしています。

instance_evalはリファレンスには、

オブジェクトのコンテキストで文字列 expr またはオブジェクト自身をブロックパラメータとするブロックを評価してその結果を返します。

と書いてありますが、特異クラスとの関係がよくわからないので、Ruby言語のJIS規格書を見てみました。

b) レシーバが特異クラスと関連付けられていない場合,新しい特異クラス M を作る。
c) レシーバが特異クラスと関連付けられている場合,その特異クラスを M とする。
d) Moduleクラスのclass_evalメソッドの手順b)から最後の手順までを実行する

ということで、レシーバーオブジェクトの特異クラスのclass_evalと同じ動きのようです。
つまり、②は、

Ruby

1M.singleton_class.class_eval(<<-CODE) 2 def say 3 CONST 4 end 5CODE

と同じです。CONSTは特異クラスで定義されていないので、その祖先である[Module, Object, Kernel, BasicObject]の各クラス/モジュールを探しますが、どこでもCONSTは定義されていないので、未定義エラーになります。

投稿2020/01/22 14:35

otn

総合スコア84423

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

instance_evalではなく定数定義のタイミングの問題だと思います。

rb

1module M; end 2M.instance_eval(<<-CODE) 3 CONST = "Hello, world" 4 def say 5 CONST 6 end 7CODE 8p M::say

ならば同じような動きになると思います。

逆に

rb

1m = Module.new { |obj| obj::CONST = "Constant in Module instance" } 2m.instance_eval(<<-EOS) 3 def const 4 CONST 5 end 6EOS 7p m.const

とすれば同じエラーが起きます。

説明見返したらおかしなことを言っていたので修正しました。
これ以降の説明は自信がないのでわかる方いたら修正をお願いします。

NameError(uninitialized constant)が発生する経緯をさらに追記すると、
今回のMmといったはModuleクラスのインスタンスです。
それに対してinstance_evalを使ってメソッド定義した場合、定義されるメソッドはそのオブジェクト限定のModuleクラスのインスタンス変数となります。
で、Moduleクラスからはそのオブジェクト内で定義された定数を参照できないのでuninitialized constantと言われるんだと思います。

投稿2020/01/22 04:00

編集2020/01/22 05:13
Mugheart

総合スコア2340

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問