什么是PHP的紧凑型Ruby相当于什么?

时间:2013-07-02 10:22:51

标签: php ruby

鉴于一些local variables,在Ruby中compact最简单的方法是什么?

def foo
  name = 'David'
  age = 25
  role = :director
  ...
  # How would you build this:
  # { :name => 'David', :age => 25, :role => :director }
  # or
  # { 'name' => 'David', 'age' => 25, 'role' => :director }
end

在PHP中,我可以这样做:

$foo = compact('name', 'age', 'role');

2 个答案:

答案 0 :(得分:9)

我的原始答案得到了显着改善。如果你继承自Binding,它会更清晰。 to_sym就在那里,因为旧版本的ruby将local_variables作为字符串。

实例方法

class Binding
  def compact( *args )
    compacted = {}
    locals = eval( "local_variables" ).map( &:to_sym )
    args.each do |arg|
      if locals.include? arg.to_sym
        compacted[arg.to_sym] = eval( arg.to_s ) 
      end 
    end 
    return compacted
  end
end

<强>使用

foo = "bar"
bar = "foo"
binding.compact( "foo" ) # => {:foo=>"bar"}
binding.compact( :bar ) # => {:bar=>"foo"}

原始回答

这是我能找到的行为类似于Php compact的方法 -

方式

def compact( *args, &prok )
  compacted = {}
  args.each do |arg|
    if prok.binding.send( :eval, "local_variables" ).include? arg
      compacted[arg.to_sym] = prok.binding.send( :eval, arg ) 
    end
  end 
  return compacted
end

示例用法

foo = "bar"
compact( "foo" ){}
# or
compact( "foo", &proc{} )

虽然它并不完美,因为你必须通过一个过程。我愿意接受有关如何改进这一点的建议。

答案 1 :(得分:2)

这是Bungus回答的一个变种,但是这里的单行是非常丑陋的,但不会扩展Binding或其他任何东西:

foo = :bar
baz = :bin
hash = [:foo, :baz].inject({}) {|h, v| h[v] = eval(v.to_s); h }
# hash => {:baz=>:bin, :foo=>:bar}

你也可以通过滥用块绑定使其看起来像一个方法调用 - 再次,Bungus原始答案的变体:

module Kernel
  def compact(&block)
    args = block.call.map &:to_sym
    lvars = block.binding.send(:eval, "local_variables").map &:to_sym
    (args & lvars).inject({}) do |h, v|
      h[v] = block.binding.send(:eval, v.to_s); h
    end
  end
end

foo = :bar
baz = :bin
compact {[ :foo, :bar, :baz ]}
# {:foo=>:bar, :baz=>:bin}

(我只是告诉自己{[..]}是垃圾压缩符号。)

如果你使用binding_of_caller gem,你可以放弃proc 显式绑定:

require 'binding_of_caller'
module Kernel
  def compact(*args)
    lvars = binding.of_caller(1).send(:eval, "local_variables").map &:to_sym
    (args.map(&:to_sym) & lvars).inject({}) do |h, v|
      h[v] = binding.of_caller(2).send(:eval, v.to_s); h
    end
  end
end

foo = :bar
baz = :bin
compact :foo, :bar, :baz
# {:foo=>:bar, :baz=>:bin}

警告,这很慢。在生产代码中,您可能永远不应该尝试这样做,而只是保留一个值的哈希,以便程序员必须在您没有追捕并在睡眠中杀死您之后保持这一点。