天天看點

藝術的Ruby 優雅代碼 關于變量初始化和傳回值

[url=http://ozmm.org/posts/return_early.html]Chris Wanstrath[/url]曾有一篇博文優化初始化變量和傳回值。下面是一些進一步的讨論:

原始的醜陋代碼如下:

def logger
  unless @logger
    @logger = Logger.new(STDOUT)
    @logger.level = Logger::WARN
  end
  @logger
end
           

Chris'的改進:

def logger
  return @logger if defined? @logger
  @logger = Logger.new(STDOUT)
  @logger.level = Logger::WARN
  @logger
end
           

作者本人更傾向:

def logger
  @logger || begin
    @logger = Logger.new(STDOUT)
    @logger.level = Logger::WARN
    @logger
  end
end
           

值得探讨的是,部落客的願意是希望用@logger ||=的方式表達,如果有一個構造函數傳回本身會看起來更漂亮。或者,在加上一個反射,如下:

def logger
  @logger ||= default_logger
end

def default_logger
  logger = Logger.new(STDOUT)
  logger.level = Logger::WARN
  logger
end
           

當然,如果你有更強的風格,也可寫成這樣:

def logger
  @logger ||= Logger.new(STDOUT).tap {|l| l.level = Logger::WARN}
end
           

另外,defined? @logger 和if @logger并不一樣,如下:

[quote]>> defined?(@logger)

=> nil

>> @logger

=> nil

>> @logger = nil

=> nil

>> defined?(@logger)

=> "instance-variable"[/quote]

是以,當你試圖判斷@logger是否為nil的時候,defined?往往不是你需要的,要當心使用。