[ruby-list:50656] Re: [質問] 関数内にて引数に渡された変数の変数名を取得

From: Seiei Miyagi <hanachin@...>
Date: 2018-03-22 03:57:43 UTC
List: ruby-list #50656
Miyagiです。

かなり無理やりな感じですがTracePointを使ってこういう感じで書けそうです。

music = {
  ex1: 'Play the top pop station'
}

def tbl_say(tbl,ex)
  unless tbl.has_key?(ex)
    puts "[ERROR] #{ex} is not in #{$tbl_name}"
  end
end

TracePoint.trace(:line) do |tp|
  $b = tp.binding
end

TracePoint.trace(:call) do |tp|
  return unless tp.method_id == :tbl_say
  tbl = tp.binding.local_variable_get(:tbl)
  $tbl_name = $b.local_variables.detect {|v| $b.local_variable_get(v) == tbl }
end

tbl_say(music,:ex1)
tbl_say(music,:ex2)

TracePoint以外でも、呼び出し元のbindingが取れれば実装できそうです。
Cygwinの環境で動くか分からないですがbinding_of_caller gemなどを使えば以下のように書けそうです。

require 'binding_of_caller'

music = {
  ex1: 'Play the top pop station'
}

def tbl_say(tbl,ex)
  unless tbl.has_key?(ex)
    b = binding.of_caller(1)
    var = b.local_variables.detect {|v| b.local_variable_get(v) == tbl }
    puts "[ERROR] #{ex} is not in #{var}"
  end
end

tbl_say(music,:ex1)
tbl_say(music,:ex2)

単純に呼び出し側でdef music.to_s; "music"; endとして事前にto_sで変数名を返すようにするのが一番かんたんかもしれません。

On Thu, Mar 22, 2018 at 10:00 AM,  <yamataka@u08.itscom.net> wrote:
> 山口と申します。
>
> yama@roswell:~$ uname -a
> CYGWIN_NT-6.1 JPC20316739 2.10.0(0.325/5/3) 2018-02-02 15:16 x86_64
> Cygwin
> yama@roswell:~$ ruby -v
> ruby 2.3.6p384 (2017-12-14 revision 9808) [x86_64-cygwin]
> last_commit=ruby 2.3.3
>
> の環境で、下記のコードにて、
>
> music = {
>   ex1: 'Play the top pop station'
> }
>
> def tbl_say(tbl,ex)
>   unless tbl.has_key?(ex)
>     puts "[ERROR] #{ex} is not in #{tbl}"
>   end
> end
>
> tbl_say(music,:ex1)
> tbl_say(music,:ex2)
> # [ERROR] ex2 is not in {:ex1=>"Play the top pop station"}
> # ではなく
> # [ERROR] ex2 is not in music と表示させたい
>
> tbl_say関数の引数、tblに渡された music の変数名を取得したいのですが
> よい記述方法があれば、ご教示いただけないでしょうか
>
>



-- 
;; Seiei Miyagi <hanachin@gmail.com>

In This Thread