0

所以,这就是我到目前为止所拥有的:

  # @return [Array<Hash>] of variables ([Placeholders, actual variables])
  def variables
      # @return [Hash] of all variables. 
      #     If actual variables are named teh same as the placeholders, the placeholders will be over written.
      #     This implementation of merging hashes of an array will work even if we add more elements to the 
      #     variables array.
      self.class.send(:define_method, "variables.flatten") do
        return self.variables.inject{|placeholders, vars| placeholders.merge(vars || {})}
      end

    return [placeholder_variables, self.variable_data]
  end

我希望能够做到:

my_object.variables # => return the Array<Hash>

但也能做到

my_object.variables.flatten # => return a single merged hash

我刚做的问题

def variables.flatten

是当我运行控制台时,我收到一条错误消息,说variables没有定义(或者只是我之前放的任何东西.flatten

.flatten有没有办法只在属性上定义我的自定义方法variables?(正常<Array>.flatten在这里不起作用,因为我需要合并哈希。)

4

4 回答 4

1

直接回答:在自己的模块中定义方法,然后包含在你返回的数组中:

module SpecialFlatten
  def flatten
    first.update last
  end
end

...然后...

def variables
  vals = [placeholder_variables, self.variable_data]
  return vals.extend(SpecialFlatten)
end

但在这种情况下,更好的选择可能是这样做:

def variables(*flags)
  if flags.include? :flatten
    placeholder_variables.update self.variable_data
  else
    [placeholder_variables, self.variable_data]
  end
end
于 2013-08-07T11:11:51.493 回答
0

我认为不可能定义“variables.flatten”方法。为了证明这一点,让我们通过这个例子来检查:

require 'ruby_parser'

RubyParser.new.parse(<<-EOF)
  my_object.variables.flatten
EOF
#=> s(:call,
 s(:call, s(:call, nil, :my_object, s(:arglist)), :variables, s(:arglist)),
 :flatten,
 s(:arglist))

如您所见variablesflatten它们是不同的标记,它们不能合并为一个标记,这是一个解析问题。

但是您可能缺少一件事-那就是可链接性。该方法variables返回变量数组,如果它们响应 flatten 方法,结果将是平坦的。如果他们没有响应该方法,您应该flatten为这些对象实现方法。

于 2012-10-12T13:09:15.203 回答
0

您可以在返回值上定义单例方法。

def variables
  result = [placeholder_variables, self.variable_data]
  # redefine method flatten on the result array
  def result.flatten
    # did not understand what you are trying to do here
    # self is the array here
    inject{|placeholders, vars| placeholders.merge(vars || {})}
  end
  return result # return the array with added method
end

然而,这几乎总是一个坏主意。

于 2012-10-12T14:11:43.427 回答
0

Array#flatten方法是 Ruby 核心的一部分,所以我建议不要更改它,尤其是当您与其他开发人员一起工作时。您似乎正在尝试符合现有接口。我会寻找替代方案,但您可以在方法的返回值上覆盖 flattenvariables方法。

def variables
  [placeholder_variables, self.class.variable_data].tap do |vars|
    vars.instance_eval do
      def flatten
        inject{|result, vars_hash| result.merge!(vars_hash)}
      end
    end
  end
end
于 2012-10-12T14:14:00.447 回答