<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -17,10 +17,22 @@ local create_table = function(...)
   return { ... }
 end
 
+local make_generator_mt = function(fn)
+  return
+  {
+    __index = function(t, k)
+      local v = fn(k)
+      t[k] = v
+      return v
+    end;
+  }
+end
+
 return
 {
   do_nothing = do_nothing;
   identity = identity;
   invariant = invariant;
   create_table = create_table;
+  make_generator_mt = make_generator_mt;
 }</diff>
      <filename>lua-nucleo/functional.lua</filename>
    </modified>
    <modified>
      <diff>@@ -20,13 +20,15 @@ local do_nothing,
       identity,
       invariant,
       create_table,
+      make_generator_mt,
       functional_exports =
       import 'lua-nucleo/functional.lua'
       {
         'do_nothing',
         'identity',
         'invariant',
-        'create_table'
+        'create_table',
+        'make_generator_mt'
       }
 
 --------------------------------------------------------------------------------
@@ -133,4 +135,59 @@ end)
 
 --------------------------------------------------------------------------------
 
+test:tests_for &quot;make_generator_mt&quot;
+
+--------------------------------------------------------------------------------
+
+test &quot;make_generator_mt-nil&quot; (function()
+  local num_calls = 0
+
+  local mt = make_generator_mt(
+      function(k)
+        num_calls = num_calls + 1
+        return nil
+      end
+    )
+
+  local t = setmetatable({ }, mt)
+
+  ensure_equals(&quot;no calls&quot;, num_calls, 0)
+  ensure_equals(&quot;get 42&quot;, t[42], nil)
+  ensure_equals(&quot;one call&quot;, num_calls, 1)
+  ensure_equals(&quot;get A&quot;, t[&quot;A&quot;], nil)
+  ensure_equals(&quot;two calls&quot;, num_calls, 2)
+  ensure_equals(&quot;get 42 again&quot;, t[42], nil)
+  ensure_equals(&quot;nill not cached&quot;, num_calls, 3)
+end)
+
+test &quot;make_generator_mt-echo&quot; (function()
+  local num_calls = 0
+
+  local mt = make_generator_mt(
+      function(k)
+        num_calls = num_calls + 1
+        return k
+      end
+    )
+
+  local t = setmetatable({ [&quot;A&quot;] = &quot;B&quot; }, mt)
+
+  ensure_equals(&quot;no calls&quot;, num_calls, 0)
+  ensure_equals(&quot;get 42&quot;, t[42], 42)
+  ensure_equals(&quot;one call&quot;, num_calls, 1)
+  ensure_equals(&quot;get 42 again&quot;, t[42], 42)
+  ensure_equals(&quot;value cached&quot;, num_calls, 1)
+
+  ensure_equals(&quot;predefined value&quot;, t[&quot;A&quot;], &quot;B&quot;)
+  ensure_equals(&quot;still one call&quot;, num_calls, 1)
+
+  local k = {}
+  ensure_equals(&quot;get {}&quot;, t[k], k)
+  ensure_equals(&quot;two calls&quot;, num_calls, 2)
+  ensure_equals(&quot;get {} again&quot;, t[k], k)
+  ensure_equals(&quot;still two calls&quot;, num_calls, 2)
+end)
+
+--------------------------------------------------------------------------------
+
 assert(test:run())</diff>
      <filename>test/functional.lua</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>0d47551da2c7e3a27154e66b184eccb6e891e7be</id>
    </parent>
  </parents>
  <author>
    <name>Alexander Gladysh</name>
    <email>agladysh@gmail.com</email>
  </author>
  <url>http://github.com/lua-nucleo/lua-nucleo/commit/6d26f477280fac445a296c820c2d3d81d439567f</url>
  <id>6d26f477280fac445a296c820c2d3d81d439567f</id>
  <committed-date>2009-11-14T16:39:11-08:00</committed-date>
  <authored-date>2009-11-14T16:39:11-08:00</authored-date>
  <message>functional: make_generator_mt</message>
  <tree>bf2e5ae3ab4fbdf1c78a46eb455f457a42ef6553</tree>
  <committer>
    <name>Alexander Gladysh</name>
    <email>agladysh@gmail.com</email>
  </committer>
</commit>
