class Original
  CONST = :original
  $global = :original
  @@class = :original

  def create_proc
    @instance = :original
    local = :original

    return Proc.new{
      p caller
      p self
      p __FILE__
      p __LINE__
      p CONST
      p $global
      p @@class
      p @instance
      p local

      def new_method_by_proc_at_method
      end
      # 縺薙ｌ縺ｯ讒区枚繧ｨ繝ｩ繝ｼ縺ｫ縺ｪ繧九�縺ｧ繧ｳ繝｡繝ｳ繝亥喧
      # NEW_CONST_BY_PROC_AT_METHOD = :proc_at_method
      @@new_class_by_proc_at_method = :proc_at_method
    }
  end

  def modify
    @instance = :modified
    local = :modfied
  end

  CONST = :modified
  $global = :modified
  @@class = :modified
end

class Other
  CONST = :other
  @@class = :other
  $global = :other

  def call(proc, method_name, const_name, classvar_name)
    local = :other
    @instance = :other

    self.class.__send__(:define_method, :foo, proc)
    self.foo

    case
    when Original.method_defined?(method_name)
      p :original
    when Other.method_defined?(method_name)
      p :other
    when self.respond_to?(method_name)
      p [:singleton, method_name, Original.methods]
    else
      raise
    end

    case
    when Original.const_defined?(const_name)
      p :original
    when Other.const_defined?(const_name)
      p :other
    when (class << self; self end).const_defined?(const_name)
      p :singleton
    else
      p :not_defined
    end

    case
    when (Original.__send__(:class_variable_get, classvar_name) rescue false)
      p :original
    when (Other.__send__(:class_variable_get, classvar_name) rescue false)
      p :other
    when ((class << self; self end).__send__(:class_variable_get, classvar_name) rescue false)
      p :singleton
    else
      raise
    end
  end
end

orig = Original.new
proc_by_method = orig.create_proc
proc_by_class = class Original
  local = :class
  @instance = :class
  @@class = :class
  CONST = :class

  proc = Proc.new {
    p caller
    p self
    p __FILE__
    p __LINE__
    p CONST
    p $global
    p @@class
    p @instance
    p local

    def new_method_by_proc_at_class
    end
    NEW_CONST_BY_PROC_AT_CLASS = :proc_at_class
    @@new_class_by_proc_at_class = :proc_at_class
  }

  @instance = :modified
  @@class = :modified
  CONST = :modified

  proc
end
orig.modify # インスタンス変数を変更してしまう。
            # 関係ないのが自明だけれども、ローカル変数も。

other = Other.new
other.call(proc_by_method, :new_method_by_proc_at_method, :NEW_CONST_BY_PROC_AT_METHOD, :@@new_class_by_proc_at_method)
puts

other = Other.new
other.call(proc_by_class, :new_method_by_proc_at_class, :NEW_CONST_BY_PROC_AT_CLASS, :@@new_class_by_proc_at_class)
puts


