代码之家  ›  专栏  ›  技术社区  ›  Weston Ganger

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

  •  3
  • Weston Ganger  · 技术社区  · 6 年前

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

    所以我的问题是在Ruby2.3+中,有没有一种方法可以为安全导航操作员别名或猴子补丁一种方法? &. 自定义方法名IE。 s.fast_try(:upcase!).fast_try(:downcase) 而不是写作 s&.upcase!&.downcase

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

    2 回复  |  直到 6 年前
        1
  •  9
  •   engineersmnky    6 年前

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

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

    当你的问题表明, “不,我不关心Try和安全导航操作员之间的细微行为差异。” ,鉴于你已经写了一个宝石并注意到了以下几点

    FastTry和ActiveSupport的区别

    我们的目标不是保持与Try方法的ActiveSupport版本的任何一致性。不过,我还是想保持一个简单的差异列表。如果您发现此处应记录的差异,请创建公关或问题。

    尚未报告

    我认为谨慎的提一下,这里的两个词之间存在着明显的、潜在的尖锐的区别 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
    
        2
  •  0
  •   Weston Ganger    6 年前

    我已经创建了一个gem来基于这个stackoverflow答案中的信息来解决这个问题。

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

    特点/目标:

    • 在提高可读性的同时,使用安全的导航操作员(&)。
    • 比其他实现(如ActiveSupport Try方法)提高性能
    • 如果无法避免,不要担心最模糊的参数/语法限制。简单和快速是关键。
    • 提供的方法应与安全导航操作员非常相似。如果需要保留ActiveSupport Try的确切行为,只需为FastTry设置自己的自定义方法名。
    • 唯一的依赖项是Ruby2.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