Ruby - 是否可以将方法别名为安全导航操作符

时间:2018-05-22 15:33:21

标签: ruby-on-rails ruby

Ruby 2.3引入了安全导航操作符,但我发现它的语法过于离散,在短暂扫描代码时很容易错过。相反,我更喜欢try的语法,因为它看起来更加明显和有意。

所以我的问题是在Ruby 2.3+中,有没有办法将安全导航操作符&.的方法别名或猴子修补为自定义方法名称,即。 s.fast_try(:upcase!).fast_try(:downcase)而不是撰写s&.upcase!&.downcase

主要思想是尝试提高性能,而不是try方法等其他实现。不,我不关心尝试和安全导航操作员之间的微小行为差异。此外,如果无法避免,我不介意一些模糊的论证限制,只需指出它们。

2 个答案:

答案 0 :(得分:8)

我猜你可以选择像

这样简单的东西
class Object
  def fast_try(meth,*args,&block)
    self&.public_send(meth,*args,&block)
  end
end

例如:

["string","STRING","pOw"].map do |s| 
  s.fast_try(:upcase!)
     .fast_try(:chars)
     .fast_try(:find, ->{"No S"}) { |a| a == "S" }
     .fast_try(:prepend, "!")
end
#=> ["!S",nil,"!No S"]

虽然您的问题表明,“不,我不关心尝试和安全导航操作员之间的轻微行为差异。”,鉴于您已经编写了一个宝石,并注意到以下内容

  

FastTry和ActiveSupport之间的差异#Try

     

我们的目标不是与try方法的ActiveSupport版本保持任何一致性。但是,我想保留一份简单的差异列表。如果您发现应在此处记录的差异,请创建PR或问题。

     

还没有报道

我觉得谨慎地提到,2之间存在明显的,可能是尖锐的差异,这里有Repl Spec来显示差异并且为了这个答案以及链接可能会死亡的事实该规范的输出如下:

ActiveSupport#try vs. Safe Navigation (&.)
  #try
    handles would be NoMethodError with nil (using #respond_to?)
    does not work on a BasicObject
    behaves like a method call
      with no method name given
        when block_given?
          yields self to a block with arity > 0
          evaluates block with arity == 0 in the context of self
        when no block_given?
          raises an ArgumentError
      with a method_name given
        a non nil object
          uses public_send for message transmission
        nil
          calls NilClass#try and returns nil
  #try!
    does not handle NoMethodError
    does not work on a BasicObject
    behaves like a method call
      with no method name given
        when block_given?
          yields self to a block with arity > 0
          evaluates block with arity == 0 in the context of self
        when no block_given?
          raises an ArgumentError
      with a method_name given
        a non nil object
          uses public_send for message transmission
        nil
          calls NilClass#try and returns nil
  &. (safe navigation)
    does not handle NoMethodError
    raises a SyntaxError with no method name given when block_given?
    raises a SyntaxError with no method name given when no block_given?
    works on a BasicObject
    does not act like a method call
      with a method_name given
        a non nil object
          &. is not called
        nil
          returns nil without a method call

答案 1 :(得分:0)

我已根据此StackOverflow答案中的信息创建了一个gem来解决此问题。

fast_try是安全导航操作符的简单方法包装器。

功能/目标:

  • 在提高可读性的同时使用安全导航操作员(&amp ;.)
  • 提高性能,而不是其他实现,例如ActiveSupport#try方法
  • 如果无法避免,请不要担心大多数模糊的参数/语法限制。简单和速度是关键。
  • 提供的方法应该与安全导航操作符非常相似。如果您需要保留ActiveSupport的确切行为,请尝试为FastTry设置自己的自定义方法名称。
  • 唯一的依赖是Ruby 2.3+。它不需要任何其他Rails / ActiveSupport,但它也可以很好地使用它!

在初始化程序中:

FastTry.method_names = [:try, :custom_try, :try!]
require 'fast_try/apply'

用法:

str.try(:upcase).try(:downcase)

# the above statement is now equivalent to using the safe navigation operator Ex.
str&.upcase&.downcase