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

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

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

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

我想你可以选择一些简单的东西

 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"] 

虽然你的问题是“不,我不关心尝试和安全导航操作员之间的微小行为差异。” 鉴于你已经写了一个gem,并注意到以下事实

FastTry和ActiveSupport之间的差异#test

我们的目标不是与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 

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

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

特色/目标:

  • 利用安全导航操作员(&。),同时提高可读性
  • 与其他实现(如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