【发布时间】:2021-08-28 01:21:55
【问题描述】:
以下两个作用域生成相同的结果,哪种语法更可取,还有其他区别吗?
scope :paid, lambda { |state| where(state: state) }
scope :paid, ->(state) { where(state: state) }
【问题讨论】:
标签: ruby-on-rails ruby lambda
以下两个作用域生成相同的结果,哪种语法更可取,还有其他区别吗?
scope :paid, lambda { |state| where(state: state) }
scope :paid, ->(state) { where(state: state) }
【问题讨论】:
标签: ruby-on-rails ruby lambda
由于可读性原因,最好对单行块使用新语法->(在 Ruby 1.9 中引入),对多行块使用 lambda。示例:
# single-line
l = ->(a, b) { a + b }
l.call(1, 2)
# multi-line
l = lambda do |a, b|
tmp = a * 3
tmp * b / 2
end
l.call(1, 2)
这似乎是在bbatsov/ruby-style-guide 建立的社区公约。
所以,在你的情况下,会更好:
scope :paid, ->(state) { where(state: state) }
【讨论】:
-> 是文字语法,如"。其含义由语言规范确定。
Kernel#lambda 是一种方法,就像任何其他方法一样。它可以被覆盖、删除、覆盖、monkeypatched、拦截……
因此,从语义上讲,它们是非常不同的。
它们的性能也可能不同。 Kernel#lambda至少会有方法调用的开销。执行引擎实际上无法知道 Kernel#lambda 在运行时做了什么(因为它可能会被猴子补丁)也排除了任何静态优化,尽管我不相信任何现有的 Ruby 执行引擎以任何有意义的方式静态优化 lambda 文字。
【讨论】:
没有区别,两者都返回相同的Proc对象:
irb(main):033:0> lambda {|x| x*x}
=> #<Proc:0x007ff525b55b90@(irb):33 (lambda)>
irb(main):034:0> ->(x) {x*x}
=> #<Proc:0x007ff525b7e068@(irb):34 (lambda)>
在我看来,-> 更具可读性。
【讨论】:
市场的答案是正确的答案。一个快速的补充——如果需要一个多行 lambda 作为参数,有两种方法可以工作。例如,在模型中创建范围,您可能需要考虑:
class User < ApplicationRecord
# Bad - this will error because we are passing a block as an argument in
# a method without parenthesis
scope cool_users lambda do |arg|
# some long query
end
# OK - when parenthesis are added, the lambda block will work
# without error (and passes rubocop). However, using parenthesis
# around a lambda block looks weird IMO
scope(cool_users lambda do |arg|
# some long query
end)
# Good - replacing do / end with {} functions without error, passes
# rubocop and looks good IMO
scope cool_users lambda { |arg|
# some long query
}
end
【讨论】: