加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – .尝试vs \u0026\u0026表现

发布时间:2020-12-17 02:47:48 所属栏目:百科 来源:网络整理
导读:假设我有一个来自SQL查询的传入值,如下所示: grok = Foo.select(:foo_attr1,:foo_attr2).first foo_attr2是一个可以为空的字段.现在假设我需要对输出进行处理(如果存在的话). krug = grok.foo_attr2.try(:bar).try(:baz)gnar = grok.foo_attr2 grok.foo_att
假设我有一个来自SQL查询的传入值,如下所示:

grok = Foo.select(:foo_attr1,:foo_attr2).first

foo_attr2是一个可以为空的字段.现在假设我需要对输出进行处理(如果存在的话).

krug = grok.foo_attr2.try(:bar).try(:baz)
gnar = grok.foo_attr2 && grok.foo_attr2.bar.baz # Assumes bar will always return output that can be baz'd

这两个操作中哪一个更好用,为什么?

解决方法

使用gnar = grok.foo_attr2&& grok.foo_attr2.bar.baz肯定会更快,因为它使用Ruby的逻辑运算符完成.虽然Rails引入了 try,但还有其他if-else条件检查.来自代码:

# File activesupport/lib/active_support/core_ext/object/try.rb,line 41
def try(*a,&b)
  if a.empty? && block_given?
    yield self
  else
    public_send(*a,&b) if respond_to?(a.first)
  end
end

好吧,这是一个基准,以准确显示我想说的内容:

class Object
  def try(*a,&b)
    if a.empty? && block_given?
      yield self
    else
      public_send(*a,&b) if respond_to?(a.first)
    end
  end
end

class Foo
  attr_reader :a
  def initialize(a = nil)
    @a = a    
  end
end

require "benchmark"


bar = Foo.new
baz = Foo.new(1)

n = 10000000
Benchmark.bm(40) do |x|
  x.report("try"){ n.times { bar.a.try(:class).try(:to_s) } }
  x.report("&& "){ n.times { baz.a && baz.a.class.to_s } }
end

结果是:

user      system      total        real
try      10.800000  0.030000   10.830000  ( 10.829770)
&&        3.940000   0.010000   3.950000  (  3.944375)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读