Is there a convention for memoization in a method call?

前端 未结 6 1512
清酒与你
清酒与你 2021-02-19 04:14

I want to avoid reevaluation of a value in method call. Untill now, I was doing this:

def some_method
  @some_method ||= begin
    # lot\'s of code
  end
end


        
相关标签:
6条回答
  • 2021-02-19 04:35

    I usually use begin, end as per your first example, but if there's a bit more code, I just look if the variable exists, no need to create another method just for that.

    def some_method
      return @some_method if @some_method
      # lot's of code
      @some_method
    end
    
    0 讨论(0)
  • 2021-02-19 04:45

    There is one more way, more Java-style I think.

    First of all you should implement annotations, like "Java-style annotations in Ruby" and "How to simulate Java-like annotations in Ruby?".

    Then you should add annotation like _cacheable that will said to method that it should return instance variable and if it is null it should calculate it by invoking method, so your code will be more clear:

    _cacheable
    def some_method
       # do_some_work
    end
    
    0 讨论(0)
  • 2021-02-19 04:45

    I use the memoist gem, which lets you easily memoize a method without having to alter your original method or create two methods.

    So for example, instead of having two methods, file_size and calculate_file_size, and having to implement the memoization yourself with an instance variable:

    def file_size
      @file_size ||= calculate_file_size
    end
    
    def calculate_file_size
      # code to calculate the file size
    end
    

    you can just do this:

    def file_size
      # code to calculate the file size
    end
    memoize :file_size
    

    Each memoized function comes with a way to flush the existing value.

    object.file_size       # returns the memoized value
    object.file_size(true) # bypasses the memoized value and rememoizes it
    

    So calling object.file_size(true) would be the equivalent of calling object.calculate_file_size...

    0 讨论(0)
  • 2021-02-19 04:53

    I would do it like this:

    def filesize
      @filesize ||= calculate_filesize
    end
    
    private
    
    def calculate_filesize
      # ...
    end
    

    So I'd just name the method differently, as I think it makes more sense.

    0 讨论(0)
  • 2021-02-19 04:53

    I don't like the bang either. I use

    def some_method 
      @some_method_memo ||= some_method_eval 
    end 
    
    private 
    
    def some_method_eval
      # lot's of code 
    end 
    

    Here eval is shorthand for evaluation. I like the way this reads and also that it makes the public interface concise.

    I despise conventions that rely on underscores as distinguishing marks: they are both error prone and require that I remember YAMC (yet another meaningless convention). The Ada language, designed for safety-critical applications, does not allow leading, trailing, or multiple underscores. Nice idea.

    0 讨论(0)
  • 2021-02-19 04:53

    I normally do it like in Agis answer or:

    def filesize() @filesize ||=
      calculate_filesize
    end
    

    BTW:

    I often use this memoization technique:

    def filesize() @_memo[:filesize] ||=
      calculate_filesize
    end
    

    Which will allow you to later clear all memoized variables with one simple @_memo.clear. The @_memo variable should be initialized like this Hash.new { |h, k| h[k] = Hash.new }. It gives you many of the adventages of using ActiveSupport::Memoize and similar meta programmed techniques which might be much slower.

    0 讨论(0)
提交回复
热议问题