Add bin and edit workflow
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 9s

This commit is contained in:
2026-09-16 13:11:16 -06:00
parent c8ac4fcae5
commit 4cee170d66
17576 changed files with 895740 additions and 2 deletions
@@ -0,0 +1,134 @@
= Memoizable
Memoizable allows
require 'facets/memoizable'
The classic example is calculating the Fibonacci sequence.
class Fibonacci
include Memoizable
def fib( num )
return num if num < 2
fib(num - 1) + fib(num - 2)
end
memoize :fib
end
The first time will take a moment to calculate.
f = Fibonacci.new
f.fib(100)
The second time will be returned almost instantly.
f = Fibonacci.new
f.fib(100)
The following example makes if very clear what memoize is doing.
class MemoExample
include Memoizable
attr_accessor :a
memoize :a
end
m = MemoExample.new
m.a = 10
m.a #=> 10
m.a = 20
m.a #=> 10
Even though @a is assigned to 20, the method #a continues to return 10.
Memoizable is designed to handle a number of typically problematic aspects
of memoization implementations. First a memoizable object can be frozen.
f = Fibonacci.new
f.freeze
f.fib(100)
Memoizable objects are freezable because it does not use an instance variable
to store the memoized return values. Instead it uses a global class instance
variable in +Memoizable.cache+.
However, this also means the memoization cache is not preserved when an object
is duplicated. If this behavior is desired an aditional module is provided
called `Memoizable::Copy`. When the `Memoiazble::Copy` module is included into
a class it not only adds the #memoize class methods but also includes
an #initialize_copy method, which copies the appropriate cache entries when
#dup or #clone is used. Keep this in mind. It is important to call #super if you
override the #initialize_copy method in a class that uses `Memoizable::Copy`.
class MemoExample2
include Memoizable::Copy
attr_accessor :a
memoize :a
end
m = MemoExample2.new
m.a = 10
m.a #=> 10
n = m.dup
n.a = 20
n.a #=> 10
The `#memoize` method also accepts a few options that can be used to modify
the behvior of the memoizaiton. To memoize a method across all objects
of the same class and not just per-object, set the `:class` option to true.
class MemoExample3
include Memoizable
attr_accessor :a
memoize :a, :class=>true
end
m = MemoExample3.new
m.a = 10
m.a #=> 10
n = MemoExample3.new
n.a #=> 10
Memoization is indexed based on arguments passed to the method, as can be seen
in the Fibonacci example. Methods can also be memoized by name only, forgoing
any indexing based on arguments passed. To do this, set the `:arguments`
option to +false+.
class MemoExample4
include Memoizable
def f(n)
n + n
end
memoize :f, :arguments=>false
end
m = MemoExample4.new
m.f(1)
m.f(2) #=> 2
m.f(3) #=> 2
Blocks passed to a method normally have only a present vs. non-present effect
on the memoization index. In other words the return value of a method will be
cached under one key if a block is passed to it and under a different index
if not. It doesn't matter if blocks passed in actually differ, since
the only way to compare blocks is by their +object_id+ and it is very rare
for the exact same block object to be reused.
Finally, the `:freeze` option can be used to freeze the memoized results.
class MemoExample5
include Memoizable
def f(n)
(n + n).to_s
end
memoize :f, :freeze=>true
end
m = MemoExample5.new
m.f(1).frozen? #=> true
m.f(2).frozen? #=> true