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

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

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

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

Q&A

解決済

3回答

297閲覧

メソッドの中に式を書くとエラーになる

Sonono

総合スコア85

Ruby

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

0グッド

0クリップ

投稿2018/07/04 05:54

前提・実現したいこと

ピカチュウとゼニガメが攻撃しあうコードを書こうとしています。
下のソースコードで、
puts ピカチュウ.life-ゼニガメ.power
のほうは正しく表示されますが、battle メソッドの中に試しに入れてみたところエラーが出てしまいます。なぜでしょうか。

発生している問題・エラーメッセージ

24 test.rb:23:in `battle': undefined local variable or method `"\u30D4\u30AB\u30C1\u30E5\u30A6"' for main:Object (NameError) from test.rb:44:in `<main>'

該当のソースコード

Ruby

1class Pokemon 2 attr_accessor :name, :life, :power 3 def initialize(name, life, power) 4 @name = name 5 @life = life 6 @power = power 7 end 8 9 10end 11 12 13ピカチュウ = Pokemon.new("ピカチュウ", 30, 13) 14ゼニガメ = Pokemon.new("ゼニガメ", 35, 6) 15 16 17puts ピカチュウ.life-ゼニガメ.power 18 19 20def battle 21 puts ピカチュウ.life.class 22 puts "#{ピカチュウ.life-ゼニガメ.power}" 23 24#puts ピカチュウ.life-ゼニガメ.power これもだめでした 25 26end

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

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

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

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

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

guest

回答3

0

ベストアンサー

Rubyの仕様です。

Rubyにおいては

  • スコープ内で定義されたメソッドから上位スコープに存在するローカル変数は(普通には)参照できない
  • スコープ内で定義されたブロックから上位スコープに存在するローカル変数は参照でき

こうなっています


裏技

ruby

1class Pokemon 2 attr_accessor :name, :life, :power 3 def initialize(name, life, power) 4 @name = name 5 @life = life 6 @power = power 7 end 8end 9 10 11ピカチュウ = Pokemon.new("ピカチュウ", 30, 13) 12ゼニガメ = Pokemon.new("ゼニガメ", 35, 6) 13 14 15puts ピカチュウ.life-ゼニガメ.power 16 17define_method :"ぴかちゅう", ->{ピカチュウ} 18define_method :"ぜにがめ", ->{ゼニガメ} 19 20def battle 21 puts ぴかちゅう.life.class 22 puts "#{ぴかちゅう.life-ぜにがめ.power}" 23end 24 25battle

積極的に使うとメソッド呼び出しなのかローカル変数なのか分からなくなりますが
たまにDSL作る時などに使う技ですね。

上述したようにブロックならば上位スコープとローカル変数を共有します。
そのため、ブロックでメソッドを定義してやればよかったりします。

問題点としてブロックで定義すると普通のメソッドよりも遅くなる事が知られています。

投稿2018/07/04 06:38

asm

総合スコア15147

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

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

0

素直に行くのなら、こういうのとかでしょうか?

ruby

1def battle A, B 2 puts A.life.class 3 puts "#{A.life-B.power}" 4end 5 6battle ピカチュウ, ゼニガメ

投稿2018/07/04 11:37

mkgrei

総合スコア8560

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

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

0

  • ファイルの文字コードはUTF-8でしょうか、Shift-JISでしょうか

(追記: エラー文字列から察するに、UTF-16ですね。)

  • Rubyを実行する際に、文字コードに見合ったオプション(UTF8なら -Ku、SJISなら -Ks)をつけて実行した場合、どうなるでしょうか

(追記:RubyではスクリプトとしてUTF-16を扱うことはできないようです。適切にスクリプトファイルの文字コードを変換する必要があります。)


追記:
エラーの内容については、asmさんのおっしゃる通り、スコープの問題でした。。。

投稿2018/07/04 06:01

編集2018/07/04 06:48
kazto

総合スコア7196

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

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

Sonono

2018/07/04 06:08

c:\ruby>ruby test.rb -Ku 24 test.rb:23:in `battle': undefined local variable or method `"\u30D4\u30AB\u30C1\u30E5\u30A6"' for main:Object (NameError) from test.rb:43:in `<main>' オプションのつけ方がこれで会っているかわからないのですがこうなってしまいました。
kazto

2018/07/04 06:08

追記をご参照ください。
kazto

2018/07/04 06:10

また、手っ取り早く解決したい場合は、「ピカチュウ」「ゼニガメ」などの変数名をローマ字に修正することで解決するかと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問