【问题标题】:Ruby library like Hashie that can use lambdas as properties像 Hashie 这样可以使用 lambdas 作为属性的 Ruby 库
【发布时间】:2013-01-09 22:45:13
【问题描述】:

是否有一个像 Hashie 一样工作的 Ruby 库,除了它可以将 lambda 作为属性并在访问该属性时调用它?

例如,我想要这样的东西:

# Lash = Lambda-able hash
lash = Lash.new(
  someProperty:      "Some value",
  someOtherProperty: ->{ Time.now }
)

lash.someProperty      # => "Some value"
lash.someOtherProperty # => 2013-01-25 16:36:45 -0500
lash.someOtherProperty # => 2013-01-25 16:36:46 -0500

【问题讨论】:

  • 它没有通用性,因为它只有在 proc 的 arity 为零时才有意义。
  • 为什么没有普遍性?
  • 当值是 proc 时,您希望它被自动评估(调用),对吗?如果它有论据,那么是什么提供了论据? proc 不能在没有参数的情况下被调用,除非它的元数为零。
  • 我在下面提供的实现适用于参数。如果你的 proc/lambda 有参数,你应该用参数调用它。例如。 lash.somePropertyThatTakesArguments(someArgument).
  • 其次,更重要的是,如果你不想要参数,不要给它一个带参数的块。

标签: ruby hash configuration


【解决方案1】:

这是我的实现:

class Lash < BasicObject
  def self.new hash
    ::Class.new do
      hash.each do |key, value|
        method_body = if value.respond_to? :call
                        ->(*args){ self.instance_exec(*args, &value) }
                      else
                        ->{ value }
                      end
        define_method(key, &method_body)
      end
    end.new
  end
end

【讨论】:

    【解决方案2】:

    几天前我想要类似的东西,最终使用了 Hashie 2.0.0.beta,它为您提供了可以与您自己的 Hash 子类一起使用的扩展:

    require 'hashie'
    require 'hashie/hash_extensions' 
    
    class Lash < Hash
      include Hashie::Extensions::MethodAccess
    
      def [](key)
        val = super(key)
        if val.respond_to?(:call) and val.arity.zero?
          val.call
        else
          val
        end
      end
    end
    

    这让您可以执行以下操作:

    l = Lash.new
    #=> {}
    
    l.foo = 123
    #=> 123
    
    l.bar = ->{ Time.now }
    #=> #<Proc:0x007ffab3915f18@(irb):58 (lambda)>
    
    l.baz = ->(x){ 10 * x }
    #=> #<Proc:0x007ffab38fb4d8@(irb):59 (lambda)>
    
    l.foo
    #=> 123
    
    l.bar
    #=> 2013-01-26 15:36:50 +0100
    
    l.baz
    #=> #<Proc:0x007ffab38fb4d8@(irb):59 (lambda)>
    
    l.baz[5]
    #=> 50
    

    注意:这仅适用于 Hashie 2.0.0.beta,您可以通过 Bundler 将这一行添加到您的 Gemfile 中:

    gem 'hashie', :git => 'git://github.com/intridea/hashie.git'
    

    或者,不使用 Bundler,使用 specific_install gem:

    gem install specific_install
    gem specific_install -l git://github.com/intridea/hashie.git
    

    【讨论】:

      猜你喜欢
      • 2010-12-18
      • 2013-06-04
      • 1970-01-01
      • 1970-01-01
      • 2017-11-20
      • 2019-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多