diff options
| author | mo khan <mo@mokhan.ca> | 2021-12-22 14:53:01 -0700 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2021-12-22 14:53:01 -0700 |
| commit | b06ef5e5ee2c24da0b6b813f07ea33676d8de220 (patch) | |
| tree | b4500a70faed2abe7480153919554cad5e9c179e | |
| parent | 55c6b27396a2a9d68cdfebe871159ed20b4cea17 (diff) | |
feat: Add Memoizable module
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -rw-r--r-- | lib/straw.rb | 20 | ||||
| -rw-r--r-- | test/test_memoizable.rb | 49 |
3 files changed, 71 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index f788ccf..12cd96c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## [Unreleased] +- feat: Add Memoizable module + ## [0.1.0] - 2021-12-22 - Initial release diff --git a/lib/straw.rb b/lib/straw.rb index 1a7bad2..5ca7d12 100644 --- a/lib/straw.rb +++ b/lib/straw.rb @@ -4,4 +4,24 @@ require_relative "straw/version" module Straw class Error < StandardError; end + + module Memoizable + def memoize(key) + if memoized?(key) + instance_variable_get(var_for(key)) + else + instance_variable_set(var_for(key), yield) + end + end + + def memoized?(key) + instance_variable_defined?(var_for(key)) + end + + private + + def var_for(key) + "@#{key}" + end + end end diff --git a/test/test_memoizable.rb b/test/test_memoizable.rb new file mode 100644 index 0000000..05b5be6 --- /dev/null +++ b/test/test_memoizable.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require "test_helper" + +describe ::Straw::Memoizable do + def setup + item_clazz = Class.new do + include ::Straw::Memoizable + + attr_reader :calls + + def initialize + @calls = Hash.new { |h, k| h[k] = 0 } + end + + def value(item) + memoize(:value) do + @calls[:value] += 1 + item + end + end + end + @subject = item_clazz.new + end + + describe "#memoize" do + describe "when the result has not been memoized" do + it "computes the result only once" do + instance = Object.new + 2.times { _(@subject.value(instance)).must_equal instance } + + _(@subject.calls[:value]).must_equal 1 + end + + it "caches a nil value to prevent duplicate calls" do + 2.times { assert_nil(@subject.value(nil)) } + + _(@subject.calls[:value]).must_equal 1 + end + + it "caches a false value to prevent duplicate calls" do + 2.times { _(@subject.value(false)).must_equal false } + + _(@subject.calls[:value]).must_equal 1 + end + end + end +end + |
