Search code examples
rubymemoizationprocruby-1.8.7

does memoization works inside of a proc?


I have the following method:

def download_link_for(site,title=nil)
  template = proc {|word|(title ?  "%s_#{title}_csv": "%s_csv") % word}

  if site.send(template.call("update")) == false
    x.a "Generate", :href => "/#{template.call("generate")}/#{site.id}"
  else
    xpr "Generating.."
  end
  if site.send(template.call("latest")) > 0 && site.send(template.call("update")) == false
    %|

  <a href="/#{template.call("download")}/#{site.id}" class="tooltip-left" title="Download the #{title} as a .csv file" id="download_pdf">
    <img src="/images/csv_download.png" alt="Download"/>
  </a>
  (#{timedate(site.send(template.call("latest")))})
    |

  end
end

The issue is the proc. I want to know if memoization works inside of a proc? specifically for:

title ?  "%s_#{title}_csv": "%s_csv"

Bearing in mind I'm working with ruby 1.8.7 though information on 1.9+ would be also be welcomed.

The main issue is that the ternary inside of the proc only ever needs to be worked out the first time so I don't want it to calculate it every time the proc get's called.

EDIT: My idea was to use currying like so:

template = proc {|tem,word|tem % word}.curry(type ?  "%s_#{type}_csv" : "%s_csv")

but for some reason it keeps responding with no implicit conversion of String into Integer I think ruby is interpreting % as modulus rather than as a string template. Even wrapping tem like so "#{tem}" didn't really work.

Also, curry wouldn't really work for me as it's not available in 1.8.7, but it was worth a shot.


Solution

  • Not sure why you need to curry. Can't you just use an instance variable to store/memoize the results of the ternary operation?

    template = proc { |word| @title ||= (title ? "%s_#{title}_csv" : "%s_csv"); @title % word }
    

    In irb:

    template = proc { |word| @title ||= word }
    
    template.call "hello"
     => "hello" 
    
    template.call "goodbye"
     => "hello"