tins 1.43.0 → 1.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.contexts/code_comment.rb +5 -8
  3. data/.contexts/lib.rb +0 -2
  4. data/CHANGES.md +12 -0
  5. data/README.md +158 -6
  6. data/Rakefile +19 -16
  7. data/examples/let.rb +8 -40
  8. data/examples/mail.rb +0 -1
  9. data/examples/turing.rb +3 -1
  10. data/lib/tins/alias.rb +1 -0
  11. data/lib/tins/annotate.rb +37 -27
  12. data/lib/tins/ask_and_send.rb +41 -0
  13. data/lib/tins/attempt.rb +39 -0
  14. data/lib/tins/bijection.rb +34 -0
  15. data/lib/tins/case_predicate.rb +21 -0
  16. data/lib/tins/complete.rb +16 -0
  17. data/lib/tins/concern.rb +64 -0
  18. data/lib/tins/date_dummy.rb +36 -4
  19. data/lib/tins/date_time_dummy.rb +34 -2
  20. data/lib/tins/deep_dup.rb +9 -2
  21. data/lib/tins/deprecate.rb +12 -0
  22. data/lib/tins/dslkit.rb +559 -83
  23. data/lib/tins/duration.rb +120 -5
  24. data/lib/tins/expose.rb +54 -5
  25. data/lib/tins/extract_last_argument_options.rb +9 -0
  26. data/lib/tins/file_binary.rb +104 -21
  27. data/lib/tins/find.rb +114 -11
  28. data/lib/tins/generator.rb +10 -2
  29. data/lib/tins/go.rb +81 -4
  30. data/lib/tins/hash_bfs.rb +4 -2
  31. data/lib/tins/hash_symbolize_keys_recursive.rb +62 -4
  32. data/lib/tins/hash_union.rb +47 -2
  33. data/lib/tins/if_predicate.rb +31 -0
  34. data/lib/tins/implement.rb +50 -0
  35. data/lib/tins/limited.rb +54 -5
  36. data/lib/tins/lines_file.rb +81 -2
  37. data/lib/tins/lru_cache.rb +54 -17
  38. data/lib/tins/memoize.rb +86 -58
  39. data/lib/tins/method_description.rb +87 -4
  40. data/lib/tins/minimize.rb +39 -11
  41. data/lib/tins/module_group.rb +27 -2
  42. data/lib/tins/named_set.rb +20 -0
  43. data/lib/tins/null.rb +86 -15
  44. data/lib/tins/once.rb +61 -4
  45. data/lib/tins/p.rb +44 -8
  46. data/lib/tins/partial_application.rb +66 -7
  47. data/lib/tins/proc_compose.rb +58 -1
  48. data/lib/tins/proc_prelude.rb +97 -10
  49. data/lib/tins/range_plus.rb +30 -2
  50. data/lib/tins/require_maybe.rb +36 -0
  51. data/lib/tins/responding.rb +39 -0
  52. data/lib/tins/secure_write.rb +24 -4
  53. data/lib/tins/sexy_singleton.rb +45 -48
  54. data/lib/tins/string_byte_order_mark.rb +33 -2
  55. data/lib/tins/string_camelize.rb +31 -2
  56. data/lib/tins/string_underscore.rb +33 -2
  57. data/lib/tins/string_version.rb +179 -10
  58. data/lib/tins/subhash.rb +35 -10
  59. data/lib/tins/temp_io.rb +7 -0
  60. data/lib/tins/temp_io_enum.rb +19 -0
  61. data/lib/tins/terminal.rb +31 -9
  62. data/lib/tins/thread_local.rb +67 -5
  63. data/lib/tins/time_dummy.rb +46 -21
  64. data/lib/tins/to.rb +15 -0
  65. data/lib/tins/to_proc.rb +17 -4
  66. data/lib/tins/token.rb +56 -1
  67. data/lib/tins/unit.rb +288 -149
  68. data/lib/tins/version.rb +1 -1
  69. data/lib/tins/write.rb +14 -3
  70. data/lib/tins/xt/blank.rb +81 -2
  71. data/lib/tins/xt/concern.rb +51 -0
  72. data/lib/tins/xt/full.rb +56 -11
  73. data/lib/tins/xt/irb.rb +46 -2
  74. data/lib/tins/xt/method_description.rb +0 -12
  75. data/lib/tins/xt/minimize.rb +7 -0
  76. data/lib/tins/xt/named.rb +71 -16
  77. data/lib/tins/xt/proc_compose.rb +4 -0
  78. data/lib/tins/xt/subhash.rb +11 -0
  79. data/lib/tins/xt/time_freezer.rb +43 -6
  80. data/lib/tins/xt.rb +1 -3
  81. data/lib/tins.rb +16 -3
  82. data/tests/duration_test.rb +4 -0
  83. data/tests/from_module_test.rb +30 -2
  84. data/tests/implement_test.rb +6 -8
  85. data/tests/lines_file_test.rb +2 -0
  86. data/tests/lru_cache_test.rb +12 -0
  87. data/tests/method_description_test.rb +14 -20
  88. data/tests/partial_application_test.rb +4 -0
  89. data/tests/proc_prelude_test.rb +1 -1
  90. data/tests/scope_test.rb +1 -1
  91. data/tests/string_version_test.rb +2 -0
  92. data/tests/to_test.rb +6 -6
  93. data/tins.gemspec +9 -9
  94. metadata +23 -41
  95. data/lib/tins/count_by.rb +0 -21
  96. data/lib/tins/deep_const_get.rb +0 -64
  97. data/lib/tins/timed_cache.rb +0 -51
  98. data/lib/tins/uniq_by.rb +0 -23
  99. data/lib/tins/xt/count_by.rb +0 -7
  100. data/lib/tins/xt/deep_const_get.rb +0 -7
  101. data/lib/tins/xt/uniq_by.rb +0 -25
  102. data/tests/count_by_test.rb +0 -17
  103. data/tests/deep_const_get_test.rb +0 -37
  104. data/tests/uniq_by_test.rb +0 -31
  105. /data/{COPYING → LICENSE} +0 -0
data/lib/tins/limited.rb CHANGED
@@ -1,8 +1,34 @@
1
1
  require 'thread'
2
2
 
3
3
  module Tins
4
+ # Tins::Limited provides a thread pool implementation that limits the number
5
+ # of concurrent threads running simultaneously.
6
+ #
7
+ # This class implements a producer-consumer pattern where you can submit
8
+ # tasks that will be executed by a fixed number of worker threads, preventing
9
+ # resource exhaustion from too many concurrent operations.
10
+ #
11
+ # @example Basic usage
12
+ # limited = Tins::Limited.new(3) # Limit to 3 concurrent threads
13
+ #
14
+ # limited.process do |l|
15
+ # 10.times do
16
+ # l.execute { puts "Task #{Thread.current.object_id}" }
17
+ # end
18
+ # l.stop # Stop processing new tasks
19
+ # end
20
+ #
21
+ # @example With named thread group
22
+ # limited = Tins::Limited.new(5, name: 'worker_pool')
23
+ # # Threads will be named 'worker_pool'
4
24
  class Limited
5
- # Create a Limited instance, that runs _maximum_ threads at most.
25
+ # Create a Limited instance that runs at most _maximum_ threads
26
+ # simultaneously.
27
+ #
28
+ # @param maximum [Integer] The maximum number of concurrent worker threads
29
+ # @param name [String, nil] Optional name for the thread group
30
+ # @raise [ArgumentError] if maximum is less than 1
31
+ # @raise [TypeError] if maximum cannot be converted to Integer
6
32
  def initialize(maximum, name: nil)
7
33
  @maximum = Integer(maximum)
8
34
  raise ArgumentError, "maximum < 1" if @maximum < 1
@@ -13,15 +39,28 @@ module Tins
13
39
  @tg = ThreadGroup.new
14
40
  end
15
41
 
16
- # The maximum number of worker threads.
42
+ # The maximum number of worker threads that can run concurrently.
43
+ #
44
+ # @return [Integer] The maximum concurrent thread limit
17
45
  attr_reader :maximum
18
46
 
19
- # Execute _maximum_ number of threads in parallel.
47
+ # Submit a task to be executed by the thread pool.
48
+ #
49
+ # @yield [Thread] The block to execute as a task
50
+ # @raise [ArgumentError] if called before process has been started
20
51
  def execute(&block)
21
52
  @tasks or raise ArgumentError, "start processing first"
22
53
  @tasks << block
23
54
  end
24
55
 
56
+ # Start processing tasks with the configured thread pool.
57
+ #
58
+ # This method blocks until all tasks are completed and the processing is
59
+ # stopped. The provided block is called repeatedly to submit tasks via
60
+ # execute().
61
+ #
62
+ # @yield [Limited] The limited instance for submitting tasks
63
+ # @return [void]
25
64
  def process
26
65
  @tasks = Queue.new
27
66
  @executor = create_executor
@@ -36,20 +75,32 @@ module Tins
36
75
  end
37
76
  end
38
77
 
78
+ # Stop processing new tasks and wait for existing tasks to complete.
79
+ #
80
+ # @return [void]
39
81
  def stop
40
82
  throw :stop
41
83
  end
42
84
 
43
85
  private
44
86
 
87
+ # Check if all tasks and threads have completed.
88
+ #
89
+ # @return [Boolean] true if no tasks remain and no threads are running
45
90
  def done?
46
91
  @tasks.empty? && @tg.list.empty?
47
92
  end
48
93
 
94
+ # Wait for all threads in the thread group to complete.
95
+ #
96
+ # @return [void]
49
97
  def wait
50
98
  @tg.list.each(&:join)
51
99
  end
52
100
 
101
+ # Create and start the executor thread that manages the worker pool.
102
+ #
103
+ # @return [Thread] The executor thread
53
104
  def create_executor
54
105
  Thread.new do
55
106
  @mutex.synchronize do
@@ -73,5 +124,3 @@ module Tins
73
124
  end
74
125
  end
75
126
  end
76
-
77
- require 'tins/alias'
@@ -1,29 +1,74 @@
1
1
  module Tins
2
+ # Tins::LinesFile provides enhanced file line processing capabilities.
3
+ #
4
+ # This class wraps file content in a way that allows for rich line-level
5
+ # operations, including tracking line numbers, filenames, and providing
6
+ # convenient navigation and matching methods. It's particularly useful for
7
+ # log processing, configuration files, or any scenario where you need to
8
+ # work with structured text data while maintaining context about line
9
+ # positions.
10
+ #
11
+ # @example Basic usage
12
+ # lines_file = Tins::LinesFile.for_filename('example.txt')
13
+ # lines_file.each do |line|
14
+ # puts line.file_linenumber # => "example.txt:1"
15
+ # puts line.line_number # => 1
16
+ # end
17
+ #
18
+ # @example Line navigation and matching
19
+ # lines_file = Tins::LinesFile.for_filename('example.txt')
20
+ # lines_file.next! # Move to next line
21
+ # lines_file.match_forward(/pattern/) # Match forward from current position
2
22
  class LinesFile
23
+ # Extension module that adds line metadata to individual lines.
24
+ #
25
+ # This module is automatically mixed into each line when a LinesFile is created,
26
+ # providing access to line number and filename information directly from the line objects.
3
27
  module LineExtension
28
+ # @return [Integer] The line number (1-based) of this line
4
29
  attr_reader :line_number
5
30
 
31
+ # @return [String] The filename associated with this line's source
6
32
  def filename
7
33
  lines_file.filename.dup
8
34
  end
9
35
  end
10
36
 
37
+ # Create a LinesFile instance from a filename.
38
+ #
39
+ # @param filename [String] Path to the file to read
40
+ # @param line_number [Integer] Starting line number (default: 1)
41
+ # @return [LinesFile] A new LinesFile instance
11
42
  def self.for_filename(filename, line_number = nil)
12
43
  obj = new(File.readlines(filename), line_number)
13
44
  obj.filename = filename
14
45
  obj
15
46
  end
16
47
 
48
+ # Create a LinesFile instance from an already opened file.
49
+ #
50
+ # @param file [File] An open File object to read from
51
+ # @param line_number [Integer] Starting line number (default: 1)
52
+ # @return [LinesFile] A new LinesFile instance
17
53
  def self.for_file(file, line_number = nil)
18
54
  obj = new(file.readlines, line_number)
19
55
  obj.filename = file.path
20
56
  obj
21
57
  end
22
58
 
59
+ # Create a LinesFile instance from an array of lines.
60
+ #
61
+ # @param lines [Array<String>] Array of line strings
62
+ # @param line_number [Integer] Starting line number (default: 1)
63
+ # @return [LinesFile] A new LinesFile instance
23
64
  def self.for_lines(lines, line_number = nil)
24
65
  new(lines, line_number)
25
66
  end
26
67
 
68
+ # Initialize a LinesFile with lines and optional starting line number.
69
+ #
70
+ # @param lines [Array<String>] Array of line strings to process
71
+ # @param line_number [Integer] Starting line number (default: 1)
27
72
  def initialize(lines, line_number = nil)
28
73
  @lines = lines
29
74
  @lines.each_with_index do |line, i|
@@ -34,27 +79,42 @@ module Tins
34
79
  instance_variable_set :@line_number, line_number || (@lines.empty? ? 0 : 1)
35
80
  end
36
81
 
82
+ # @return [String] The filename associated with this LinesFile
37
83
  attr_accessor :filename
38
84
 
85
+ # @return [Integer] The current line number (1-based)
39
86
  attr_reader :line_number
40
87
 
88
+ # Reset the current line number to the beginning.
89
+ #
90
+ # @return [LinesFile] Returns self for chaining
41
91
  def rewind
42
92
  self.line_number = 1
43
93
  self
44
94
  end
45
95
 
96
+ # Move to the next line.
97
+ #
98
+ # @return [LinesFile, nil] Returns self if successful, nil if at end of file
46
99
  def next!
47
100
  old = line_number
48
101
  self.line_number += 1
49
102
  line_number > old ? self : nil
50
103
  end
51
104
 
105
+ # Move to the previous line.
106
+ #
107
+ # @return [LinesFile, nil] Returns self if successful, nil if at beginning
52
108
  def previous!
53
109
  old = line_number
54
110
  self.line_number -= 1
55
111
  line_number < old ? self : nil
56
112
  end
57
113
 
114
+ # Set the current line number.
115
+ #
116
+ # @param number [Integer] The new line number to set
117
+ # @return [void]
58
118
  def line_number=(number)
59
119
  number = number.to_i
60
120
  if number > 0 && number <= last_line_number
@@ -62,14 +122,21 @@ module Tins
62
122
  end
63
123
  end
64
124
 
125
+ # @return [Integer] The total number of lines in this file
65
126
  def last_line_number
66
127
  @lines.size
67
128
  end
68
129
 
130
+ # @return [Boolean] True if the file has no lines
69
131
  def empty?
70
132
  @lines.empty?
71
133
  end
72
134
 
135
+ # Iterate through all lines, setting the current line number for each.
136
+ #
137
+ # @yield [line] Each line in the file
138
+ # @yieldparam line [String] The current line object with line metadata
139
+ # @return [LinesFile] Returns self for chaining
73
140
  def each(&block)
74
141
  empty? and return self
75
142
  old_line_number = line_number
@@ -83,15 +150,22 @@ module Tins
83
150
  end
84
151
  include Enumerable
85
152
 
153
+ # @return [String, nil] The current line content or nil if out of bounds
86
154
  def line
87
155
  index = line_number - 1
88
156
  @lines[index] if index >= 0
89
157
  end
90
158
 
159
+ # @return [String] Formatted filename and line number (e.g., "file.txt:5")
91
160
  def file_linenumber
92
161
  "#{filename}:#{line_number}"
93
162
  end
94
163
 
164
+ # Match a regular expression backward from current position.
165
+ #
166
+ # @param regexp [Regexp] The regular expression to match
167
+ # @param previous_after_match [Boolean] Whether to move back one line after match
168
+ # @return [Array<String>, nil] Captured groups or nil if no match
95
169
  def match_backward(regexp, previous_after_match = false)
96
170
  begin
97
171
  if line =~ regexp
@@ -101,6 +175,11 @@ module Tins
101
175
  end while previous!
102
176
  end
103
177
 
178
+ # Match a regular expression forward from current position.
179
+ #
180
+ # @param regexp [Regexp] The regular expression to match
181
+ # @param next_after_match [Boolean] Whether to move forward one line after match
182
+ # @return [Array<String>, nil] Captured groups or nil if no match
104
183
  def match_forward(regexp, next_after_match = false)
105
184
  begin
106
185
  if line =~ regexp
@@ -110,14 +189,14 @@ module Tins
110
189
  end while next!
111
190
  end
112
191
 
192
+ # @return [String] String representation including line number and content
113
193
  def to_s
114
194
  "#{line_number} #{line.chomp}"
115
195
  end
116
196
 
197
+ # @return [String] Detailed inspection string
117
198
  def inspect
118
199
  "#<#{self.class}: #{to_s.inspect}>"
119
200
  end
120
201
  end
121
202
  end
122
-
123
- require 'tins/alias'
@@ -1,33 +1,57 @@
1
1
  module Tins
2
+ # An LRU (Least Recently Used) cache implementation.
3
+ #
4
+ # This cache maintains a fixed-size collection of key-value pairs,
5
+ # automatically removing the least recently accessed item when the capacity
6
+ # is exceeded.
2
7
  class LRUCache
3
8
  include Enumerable
4
9
 
5
- class << self
6
- private
10
+ # Our "nil" value if it wasn' set by clients
11
+ NOT_EXIST = Object.new.freeze
7
12
 
8
- my_nil = Object.new.freeze
9
-
10
- define_method(:not_exist) do
11
- my_nil
12
- end
13
- end
13
+ private_constant :NOT_EXIST
14
14
 
15
+ # Initializes a new LRU cache with the specified capacity.
16
+ #
17
+ # @param capacity [Integer] maximum number of items the cache can hold
15
18
  def initialize(capacity)
16
- @capacity = capacity
19
+ @capacity = Integer(capacity)
20
+ @capacity >= 1 or
21
+ raise ArgumentError, "capacity should be >= 1, was #@capacity"
17
22
  @data = {}
18
23
  end
19
24
 
25
+ # Returns the maximum capacity of the cache.
26
+ #
27
+ # @return [Integer] the cache capacity
20
28
  attr_reader :capacity
21
29
 
30
+ # Retrieves the value associated with the given key.
31
+ #
32
+ # If the key exists, it is moved to the most recently used position.
33
+ # Returns nil if the key does not exist.
34
+ #
35
+ # @param key [Object] the key to look up
36
+ # @return [Object, nil] the value for the key or nil if not found
22
37
  def [](key)
23
- case value = @data.delete(key){ not_exist }
24
- when not_exist
38
+ case value = @data.delete(key) { NOT_EXIST }
39
+ when NOT_EXIST
25
40
  nil
26
41
  else
27
42
  @data[key] = value
28
43
  end
29
44
  end
30
45
 
46
+ # Associates a value with a key in the cache.
47
+ #
48
+ # If the key already exists, its position is updated to most recently used.
49
+ # If adding this item exceeds the capacity, the least recently used item is
50
+ # removed.
51
+ #
52
+ # @param key [Object] the key to set
53
+ # @param value [Object] the value to associate with the key
54
+ # @return [Object] the assigned value
31
55
  def []=(key, value)
32
56
  @data.delete(key)
33
57
  @data[key] = value
@@ -37,26 +61,39 @@ module Tins
37
61
  value
38
62
  end
39
63
 
64
+ # Iterates over all key-value pairs in the cache.
65
+ #
66
+ # Items are yielded in order from most recently used to least recently used.
67
+ #
68
+ # @yield [key, value] yields each key-value pair
69
+ # @yieldparam key [Object] the key
70
+ # @yieldparam value [Object] the value
71
+ # @return [Enumerator] if no block is given
40
72
  def each(&block)
41
73
  @data.reverse_each(&block)
42
74
  end
43
75
 
76
+ # Removes and returns the value associated with the given key.
77
+ #
78
+ # @param key [Object] the key to delete
79
+ # @return [Object, nil] the removed value or nil if not found
44
80
  def delete(key)
45
81
  @data.delete(key)
46
82
  end
47
83
 
84
+ # Removes all items from the cache.
85
+ #
86
+ # @return [Tins::LRUCache] self
48
87
  def clear
49
88
  @data.clear
89
+ self
50
90
  end
51
91
 
92
+ # Returns the number of items currently in the cache.
93
+ #
94
+ # @return [Integer] the current size of the cache
52
95
  def size
53
96
  @data.size
54
97
  end
55
-
56
- private
57
-
58
- def not_exist
59
- self.class.send(:not_exist)
60
- end
61
98
  end
62
99
  end
data/lib/tins/memoize.rb CHANGED
@@ -1,91 +1,119 @@
1
1
  require 'tins/extract_last_argument_options'
2
+ require 'mize'
2
3
 
3
4
  module Tins
5
+ # Provides memoization functionality for methods and functions with support
6
+ # for instance-level and class-level caching respectively.
7
+ #
8
+ # @example Basic method memoization
9
+ # class Calculator
10
+ # def expensive_calculation(x, y)
11
+ # # Some expensive computation
12
+ # x * y
13
+ # end
14
+ # memoize_method :expensive_calculation
15
+ # end
16
+ #
17
+ # @example Function memoization (shared across instances)
18
+ # class MathUtils
19
+ # def self.factorial(n)
20
+ # n <= 1 ? 1 : n * factorial(n - 1)
21
+ # end
22
+ # memoize_function :factorial
23
+ # end
24
+ #
25
+ # @example With freezing results
26
+ # class DataProcessor
27
+ # def process_data(input)
28
+ # # Process data and return result
29
+ # input.dup
30
+ # end
31
+ # memoize_method :process_data, freeze: true
32
+ # end
33
+ #
34
+ # @note This module is deprecated in favor of the {https://github.com/flori/mize mize} gem.
35
+ # Use `memoize method:` or `memoize function:` from the mize gem directly.
4
36
  module Memoize
37
+ # Provides cache management methods for memoized functions and methods.
38
+ # This module is included in classes that use memoization functionality.
39
+ #
40
+ # @example Using cache methods directly
41
+ # class Example
42
+ # include Tins::Memoize::CacheMethods
43
+ #
44
+ # def expensive_method
45
+ # # Some expensive computation
46
+ # end
47
+ # memoize_method :expensive_method
48
+ # end
49
+ #
50
+ # obj = Example.new
51
+ # obj.memoize_cache_clear # Clear all cached values
52
+ # obj.__memoize_cache__ # Access the internal cache object
5
53
  module CacheMethods
6
- # Return the cache object.
54
+ # Return the cache object used for memoization.
55
+ #
56
+ # @return [Object] The cache instance
7
57
  def __memoize_cache__
8
- @__memoize_cache__ ||= {}
58
+ if @__memoize_cache__
59
+ @__memoize_cache__
60
+ else
61
+ @__memoize_cache__ = __mize_cache__
62
+ def @__memoize_cache__.empty?
63
+ @data.empty?
64
+ end
65
+ @__memoize_cache__
66
+ end
9
67
  end
10
68
 
11
- # Clear cached values for all methods/functions.
69
+ # Clear cached values for all methods/functions of this object.
70
+ #
71
+ # @return [self] For chaining
12
72
  def memoize_cache_clear
13
73
  __memoize_cache__.clear
14
74
  self
15
75
  end
16
-
17
- def memoize_apply_visibility(id)
18
- visibility = instance_eval do
19
- case
20
- when private_method_defined?(id)
21
- :private
22
- when protected_method_defined?(id)
23
- :protected
24
- end
25
- end
26
- yield
27
- ensure
28
- visibility and __send__(visibility, id)
29
- end
30
76
  end
31
77
 
32
78
  class ::Module
33
- # Automatically memoize calls of the the methods +method_ids+. The
34
- # memoized results do NOT ONLY depend on the arguments, but ALSO on the
35
- # object the method is called on.
79
+ # Memoize a method so that its return value is cached based on the arguments
80
+ # and the object instance. Each instance maintains its own cache.
81
+ #
82
+ # @param method_ids [Array<Symbol>] One or more method names to memoize
83
+ # @option opts [Boolean] :freeze (false) Whether to freeze results
84
+ # @return [Symbol, Array<Symbol>] The memoized method name(s)
85
+ #
86
+ # @deprecated Use `memoize method:` from the mize gem instead.
36
87
  def memoize_method(*method_ids)
88
+ warn "[DEPRECATION] `memoize_method` is deprecated. Please use `memoize method:` from mize gem."
37
89
  method_ids.extend(ExtractLastArgumentOptions)
38
90
  method_ids, opts = method_ids.extract_last_argument_options
39
- include CacheMethods
40
- method_ids.each do |method_id|
41
- method_id = method_id.to_s.to_sym
42
- memoize_apply_visibility method_id do
43
- orig_method = instance_method(method_id)
44
- __send__(:define_method, method_id) do |*args|
45
- mc = __memoize_cache__
46
- if mc.key?(method_id) and result = mc[method_id][args]
47
- result
48
- else
49
- (mc[method_id] ||= {})[args] = result = orig_method.bind(self).call(*args)
50
- $DEBUG and warn "#{self.class} cached method #{method_id}(#{args.inspect unless args.empty?}) = #{result.inspect} [#{__id__}]"
51
- opts[:freeze] and result.freeze
52
- end
53
- result
54
- end
55
- end
91
+ method_ids.each do |method|
92
+ memoize method:, **opts.slice(:freeze)
56
93
  end
94
+ include CacheMethods
57
95
  method_ids.size == 1 ? method_ids.first : method_ids
58
96
  end
59
97
 
60
98
  include CacheMethods
61
99
 
62
- # Automatically memoize calls of the functions +function_ids+. The
63
- # memoized result does ONLY depend on the arguments given to the
64
- # function.
100
+ # Memoize a function (class method) so that its return value is cached
101
+ # based only on the arguments, shared across all instances of the class.
102
+ #
103
+ # @param function_ids [Array<Symbol>] One or more function names to memoize
104
+ # @option opts [Boolean] :freeze (false) Whether to freeze results
105
+ # @return [Symbol, Array<Symbol>] The memoized function name(s)
106
+ #
107
+ # @deprecated Use `memoize function:` from the mize gem instead.
65
108
  def memoize_function(*function_ids)
109
+ warn "[DEPRECATION] `memoize_function` is deprecated. Please use `memoize function:` from mize gem."
66
110
  function_ids.extend(ExtractLastArgumentOptions)
67
111
  function_ids, opts = function_ids.extract_last_argument_options
68
- mc = __memoize_cache__
69
- function_ids.each do |function_id|
70
- function_id = function_id.to_s.to_sym
71
- memoize_apply_visibility function_id do
72
- orig_function = instance_method(function_id)
73
- __send__(:define_method, function_id) do |*args|
74
- if mc.key?(function_id) and result = mc[function_id][args]
75
- result
76
- else
77
- (mc[function_id] ||= {})[args] = result = orig_function.bind(self).call(*args)
78
- opts[:freeze] and result.freeze
79
- $DEBUG and warn "#{self.class} cached function #{function_id}(#{args.inspect unless args.empty?}) = #{result.inspect}"
80
- end
81
- result
82
- end
83
- end
112
+ function_ids.each do |function|
113
+ memoize function:, **opts.slice(:freeze)
84
114
  end
85
115
  function_ids.size == 1 ? function_ids.first : function_ids
86
116
  end
87
117
  end
88
118
  end
89
119
  end
90
-
91
- require 'tins/alias'