ruby - 当接收器为零时,Ruby 安全导航运营商是否评估其参数?

标签 ruby safe-navigation-operator

题:
当接收器为 &. 时,Ruby 安全导航操作符 ( nil ) 是否评估其参数?
例如:

logger&.log("Something important happened...")
  • "Something important happened..."字符串在这里评估?
  • 您能否提供一个权威来源,证明或否认这一事实?
  • 或者建议一种如何检查它的方法?

  • 提前致谢。

    为什么我要寻找这个问题的答案?
    我的代码库中有如下代码:
    logger.log("Something important happened. (#{Time.current})") if verbose
    
    我的主要目标是消除 if verbose 的重复。每当我调用 log 时检查方法,因为很容易忘记它,而且您根本不会收到有关误用的通知。
    灵感来自 Tell, don't ask原则,
    我已搬家 if verbose检查内部 log方法实现。
    class Logger
      # ...
      
      def log(message)
        return unless verbose
    
        # ...
      end
    end
    
    def logger
      @logger ||= Logger.new
    end
    
    logger.log("Something important happened. (#{Time.current})")
    
    这种方法简化了我的代码,因为我已经解决了我的主要问题 - 我不需要记住放置 if verbose每当我调用 log方法,
    但我收到了另一个问题。"Something important..."字符串总是被评估,不管 verbosetruefalse .
    因此,我彻底改变了解决方案:
  • logger返回 nilverbosefalse .
  • Ruby 安全导航操作符应该用在 log 前面调用。

  • def logger
      @logger ||= Logger.new if verbose
    end
    
    logger&.log("Something important happened. (#{Time.current})")
    
    结果我把最初的记不住if verbose的问题换掉了检查内存 &.调用。
    但是,无论如何,我认为这是一种改进,因为忘记使用安全导航操作符会引发 NoMethodError ,换句话说,通知 log方法误用。
    所以现在,为了确保“安全导航运算符(operator)方法”实际上是解决我的问题的“更好”选择,
    我需要确切地知道 Ruby 中的安全导航操作符是否在其接收器为 nil 时评估其参数。 .

    最佳答案

    引自 the syntax documentation对于安全导航运算符(operator):

    &., called “safe navigation operator”, allows to skip method call when receiver is nil. It returns nil and doesn't evaluate method's arguments if the call is skipped.


    因此,您的 log 的论点如果 logger 不评估方法是 nil当你把它称为
    logger&.log("something happened at #{Time.now}")
    

    话虽如此,请注意 Ruby 核心记录器为您的确切问题提供了不同的解决方案,即避免在日志级别过高时评估潜在的昂贵参数。
    Ruby 核心记录器实现了它的 add方法是这样的(简化):
    class Logger
      attr_accessor :level
    
      def initialize(level)
        @level = level.to_i
      end
    
      def add(severity, message = nil)
        return unless severity >= level
        
        message ||= yield
        log_device.write(message)
      end
    
      def info(message = nil, &block)
        add(1, message, &block)
      end
    end
    
    然后您可以将其用作
    logger = Logger.new(1)
    logger.info { "something happened at #{Time.now}" }
    
    在这里,只有当日志级别足够高以至于实际使用消息时才会评估块。

    关于ruby - 当接收器为零时,Ruby 安全导航运营商是否评估其参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63022321/

    相关文章:

    Ruby 文件 IO 定界符?

    ruby - Vagrant ssh 使用 -c 或 --COMMAND 导致 session 关闭

    html - 是否有类似安全导航运算符的东西可以用于数组?

    ruby - NilCheck 修复了安全导航运算符 (&.)

    c# - 为什么 null 条件运算符会更改常规属性访问?

    ruby-on-rails - jRails 替代品

    ruby - 寻找一个匹配所有单词的正则表达式,除了那些[括号内]

    ruby - 如何确定 Ruby 脚本的 shell 执行上下文?

    ruby - nil 的安全导航运算符 (&.)

    ruby - 使用 Hash#dig 或 Lonely operator(&.) 安全地为嵌套哈希赋值