memo_wise 1.6.0 → 1.8.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.
- checksums.yaml +4 -4
- data/.github/workflows/dependency-review.yml +23 -0
- data/.github/workflows/main.yml +16 -7
- data/.gitignore +3 -0
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +231 -129
- data/Gemfile +10 -5
- data/Gemfile.lock +63 -76
- data/README.md +36 -30
- data/benchmarks/Gemfile +8 -6
- data/benchmarks/benchmarks.rb +68 -38
- data/lib/memo_wise/internal_api.rb +40 -17
- data/lib/memo_wise/version.rb +1 -1
- data/lib/memo_wise.rb +76 -22
- data/memo_wise.gemspec +1 -1
- metadata +4 -3
data/Gemfile.lock
CHANGED
@@ -1,122 +1,109 @@
|
|
1
1
|
GIT
|
2
|
-
remote: https://github.com/panorama-ed/panolint.git
|
3
|
-
revision:
|
2
|
+
remote: https://github.com/panorama-ed/panolint-ruby.git
|
3
|
+
revision: a93988ea554177cf0ec9ef636c442f9d3af49a10
|
4
4
|
branch: main
|
5
5
|
specs:
|
6
|
-
panolint (0
|
7
|
-
|
8
|
-
rubocop (
|
9
|
-
rubocop-
|
10
|
-
rubocop-rails (~> 2.5)
|
11
|
-
rubocop-rake (~> 0.5)
|
12
|
-
rubocop-rspec (~> 2.0)
|
6
|
+
panolint-ruby (0)
|
7
|
+
rubocop (= 1.51.0)
|
8
|
+
rubocop-performance (= 1.18.0)
|
9
|
+
rubocop-rspec (= 2.22.0)
|
13
10
|
|
14
11
|
PATH
|
15
12
|
remote: .
|
16
13
|
specs:
|
17
|
-
memo_wise (1.
|
14
|
+
memo_wise (1.8.0)
|
18
15
|
|
19
16
|
GEM
|
20
17
|
remote: https://rubygems.org/
|
21
18
|
specs:
|
22
|
-
activesupport (6.1.4.1)
|
23
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
24
|
-
i18n (>= 1.6, < 2)
|
25
|
-
minitest (>= 5.1)
|
26
|
-
tzinfo (~> 2.0)
|
27
|
-
zeitwerk (~> 2.3)
|
28
19
|
ansi (1.5.0)
|
29
20
|
ast (2.4.2)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
concurrent-ruby (1.1.9)
|
34
|
-
diff-lcs (1.4.4)
|
35
|
-
docile (1.3.5)
|
36
|
-
dokaz (0.0.4)
|
21
|
+
diff-lcs (1.5.0)
|
22
|
+
docile (1.4.0)
|
23
|
+
dokaz (0.0.5)
|
37
24
|
ansi
|
38
|
-
rouge
|
25
|
+
rouge (~> 4)
|
39
26
|
slop (~> 3)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
parser (3.1.0.0)
|
27
|
+
json (2.6.3)
|
28
|
+
minitest (5.18.0)
|
29
|
+
parallel (1.23.0)
|
30
|
+
parser (3.2.2.1)
|
45
31
|
ast (~> 2.4.1)
|
46
|
-
|
47
|
-
rainbow (3.0.0)
|
32
|
+
rainbow (3.1.1)
|
48
33
|
rake (13.0.6)
|
49
|
-
redcarpet (3.
|
50
|
-
regexp_parser (2.
|
34
|
+
redcarpet (3.6.0)
|
35
|
+
regexp_parser (2.8.0)
|
51
36
|
rexml (3.2.5)
|
52
|
-
rouge (
|
53
|
-
rspec (3.
|
54
|
-
rspec-core (~> 3.
|
55
|
-
rspec-expectations (~> 3.
|
56
|
-
rspec-mocks (~> 3.
|
57
|
-
rspec-core (3.
|
58
|
-
rspec-support (~> 3.
|
59
|
-
rspec-expectations (3.
|
37
|
+
rouge (4.1.0)
|
38
|
+
rspec (3.12.0)
|
39
|
+
rspec-core (~> 3.12.0)
|
40
|
+
rspec-expectations (~> 3.12.0)
|
41
|
+
rspec-mocks (~> 3.12.0)
|
42
|
+
rspec-core (3.12.1)
|
43
|
+
rspec-support (~> 3.12.0)
|
44
|
+
rspec-expectations (3.12.2)
|
60
45
|
diff-lcs (>= 1.2.0, < 2.0)
|
61
|
-
rspec-support (~> 3.
|
62
|
-
rspec-mocks (3.
|
46
|
+
rspec-support (~> 3.12.0)
|
47
|
+
rspec-mocks (3.12.3)
|
63
48
|
diff-lcs (>= 1.2.0, < 2.0)
|
64
|
-
rspec-support (~> 3.
|
65
|
-
rspec-support (3.
|
66
|
-
rubocop (1.
|
49
|
+
rspec-support (~> 3.12.0)
|
50
|
+
rspec-support (3.12.0)
|
51
|
+
rubocop (1.51.0)
|
52
|
+
json (~> 2.3)
|
67
53
|
parallel (~> 1.10)
|
68
|
-
parser (>= 3.
|
54
|
+
parser (>= 3.2.0.0)
|
69
55
|
rainbow (>= 2.2.2, < 4.0)
|
70
56
|
regexp_parser (>= 1.8, < 3.0)
|
71
|
-
rexml
|
72
|
-
rubocop-ast (>= 1.
|
57
|
+
rexml (>= 3.2.5, < 4.0)
|
58
|
+
rubocop-ast (>= 1.28.0, < 2.0)
|
73
59
|
ruby-progressbar (~> 1.7)
|
74
|
-
unicode-display_width (>=
|
75
|
-
rubocop-ast (1.
|
76
|
-
parser (>= 3.
|
77
|
-
rubocop-
|
60
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
61
|
+
rubocop-ast (1.28.1)
|
62
|
+
parser (>= 3.2.1.0)
|
63
|
+
rubocop-capybara (2.18.0)
|
64
|
+
rubocop (~> 1.41)
|
65
|
+
rubocop-factory_bot (2.23.1)
|
66
|
+
rubocop (~> 1.33)
|
67
|
+
rubocop-performance (1.18.0)
|
78
68
|
rubocop (>= 1.7.0, < 2.0)
|
79
69
|
rubocop-ast (>= 0.4.0)
|
80
|
-
rubocop-
|
81
|
-
|
82
|
-
|
83
|
-
rubocop (
|
84
|
-
|
85
|
-
|
86
|
-
rubocop-rspec (2.6.0)
|
87
|
-
rubocop (~> 1.19)
|
88
|
-
ruby-progressbar (1.11.0)
|
89
|
-
simplecov (0.18.5)
|
70
|
+
rubocop-rspec (2.22.0)
|
71
|
+
rubocop (~> 1.33)
|
72
|
+
rubocop-capybara (~> 2.17)
|
73
|
+
rubocop-factory_bot (~> 2.22)
|
74
|
+
ruby-progressbar (1.13.0)
|
75
|
+
simplecov (0.22.0)
|
90
76
|
docile (~> 1.1)
|
91
77
|
simplecov-html (~> 0.11)
|
78
|
+
simplecov_json_formatter (~> 0.1)
|
79
|
+
simplecov-cobertura (2.1.0)
|
80
|
+
rexml
|
81
|
+
simplecov (~> 0.19)
|
92
82
|
simplecov-html (0.12.3)
|
83
|
+
simplecov_json_formatter (0.1.4)
|
93
84
|
slop (3.6.0)
|
94
|
-
|
95
|
-
concurrent-ruby (~> 1.0)
|
96
|
-
unicode-display_width (2.1.0)
|
85
|
+
unicode-display_width (2.4.2)
|
97
86
|
values (1.8.0)
|
98
|
-
|
99
|
-
yard (0.9.27)
|
100
|
-
webrick (~> 1.7.0)
|
87
|
+
yard (0.9.34)
|
101
88
|
yard-doctest (0.1.17)
|
102
89
|
minitest
|
103
90
|
yard
|
104
|
-
zeitwerk (2.5.1)
|
105
91
|
|
106
92
|
PLATFORMS
|
107
93
|
ruby
|
108
94
|
|
109
95
|
DEPENDENCIES
|
110
|
-
|
111
|
-
dokaz
|
96
|
+
dokaz (~> 0.0.5)
|
112
97
|
memo_wise!
|
113
|
-
panolint!
|
98
|
+
panolint-ruby!
|
114
99
|
rake
|
115
|
-
redcarpet (~> 3.
|
116
|
-
rspec (~> 3.
|
100
|
+
redcarpet (~> 3.6)
|
101
|
+
rspec (~> 3.12)
|
102
|
+
simplecov
|
103
|
+
simplecov-cobertura
|
117
104
|
values (~> 1)
|
118
105
|
yard (~> 0.9)
|
119
106
|
yard-doctest (~> 0.1)
|
120
107
|
|
121
108
|
BUNDLED WITH
|
122
|
-
2.
|
109
|
+
2.3.8
|
data/README.md
CHANGED
@@ -6,9 +6,8 @@
|
|
6
6
|
# `MemoWise`
|
7
7
|
|
8
8
|
[](https://github.com/panorama-ed/memo_wise/actions?query=workflow%3AMain)
|
9
|
-
[](https://codecov.io/gh/panorama-ed/memo_wise
|
10
|
-
[](http://rubydoc.info/
|
11
|
-
[](http://inch-ci.org/github/panorama-ed/memo_wise)
|
9
|
+
[](https://codecov.io/gh/panorama-ed/memo_wise)
|
10
|
+
[](http://rubydoc.info/gems/memo_wise)
|
12
11
|
[](https://rubygems.org/gems/memo_wise)
|
13
12
|
[](https://rubygems.org/gems/memo_wise)
|
14
13
|
|
@@ -113,38 +112,38 @@ For more usage details, see our detailed [documentation](#documentation).
|
|
113
112
|
|
114
113
|
## Benchmarks
|
115
114
|
|
116
|
-
Benchmarks are run in GitHub Actions, and the tables below are updated with every code change. **Values >1.00x represent how much _slower_ each gem’s memoized value retrieval is than the latest commit of `MemoWise`**, according to [`benchmark-ips`](https://github.com/evanphx/benchmark-ips) (2.
|
115
|
+
Benchmarks are run in GitHub Actions, and the tables below are updated with every code change. **Values >1.00x represent how much _slower_ each gem’s memoized value retrieval is than the latest commit of `MemoWise`**, according to [`benchmark-ips`](https://github.com/evanphx/benchmark-ips) (2.11.0).
|
117
116
|
|
118
|
-
Results using Ruby 3.
|
117
|
+
Results using Ruby 3.2.2:
|
119
118
|
|
120
|
-
|Method arguments|`Dry::Core
|
119
|
+
|Method arguments|`Dry::Core`\* (1.0.1)|`Memery` (1.5.0)|
|
121
120
|
|--|--|--|
|
122
|
-
|`()` (none)|
|
123
|
-
|`(a)`|1.
|
124
|
-
|`(a, b)`|
|
125
|
-
|`(a:)`|1.
|
126
|
-
|`(a:, b:)`|
|
127
|
-
|`(a, b:)`|
|
128
|
-
|`(a, *args)`|0.
|
129
|
-
|`(a:, **kwargs)`|0.
|
130
|
-
|`(a, *args, b:, **kwargs)`|0.
|
121
|
+
|`()` (none)|0.54x|3.62x|
|
122
|
+
|`(a)`|1.54x|7.74x|
|
123
|
+
|`(a, b)`|1.29x|5.58x|
|
124
|
+
|`(a:)`|1.55x|12.37x|
|
125
|
+
|`(a:, b:)`|1.15x|8.76x|
|
126
|
+
|`(a, b:)`|1.15x|8.75x|
|
127
|
+
|`(a, *args)`|0.84x|1.54x|
|
128
|
+
|`(a:, **kwargs)`|0.79x|2.13x|
|
129
|
+
|`(a, *args, b:, **kwargs)`|0.69x|1.38x|
|
131
130
|
|
132
131
|
\* `Dry::Core`
|
133
132
|
[may cause incorrect behavior caused by hash collisions](https://github.com/dry-rb/dry-core/issues/63).
|
134
133
|
|
135
|
-
Results using Ruby 2.7.
|
134
|
+
Results using Ruby 2.7.8 (because these gems raise errors in Ruby 3.x):
|
136
135
|
|
137
|
-
|Method arguments|`DDMemoize` (1.0.0)|`Memoist` (0.16.2)|`Memoized` (1.
|
136
|
+
|Method arguments|`DDMemoize` (1.0.0)|`Memoist` (0.16.2)|`Memoized` (1.1.1)|`Memoizer` (1.0.3)|
|
138
137
|
|--|--|--|--|--|
|
139
|
-
|`()` (none)|24.
|
140
|
-
|`(a)`|
|
141
|
-
|`(a, b)`|
|
142
|
-
|`(a:)`|30.
|
143
|
-
|`(a:, b:)`|
|
144
|
-
|`(a, b:)`|
|
145
|
-
|`(a, *args)`|3.
|
146
|
-
|`(a:, **kwargs)`|2.
|
147
|
-
|`(a, *args, b:, **kwargs)`|2.
|
138
|
+
|`()` (none)|24.22x|2.42x|26.43x|2.70x|
|
139
|
+
|`(a)`|22.08x|15.19x|22.03x|13.67x|
|
140
|
+
|`(a, b)`|19.12x|14.01x|18.60x|12.80x|
|
141
|
+
|`(a:)`|30.21x|24.29x|26.43x|23.11x|
|
142
|
+
|`(a:, b:)`|27.73x|22.97x|25.11x|21.89x|
|
143
|
+
|`(a, b:)`|26.87x|22.76x|23.71x|21.26x|
|
144
|
+
|`(a, *args)`|3.15x|2.30x|3.18x|2.11x|
|
145
|
+
|`(a:, **kwargs)`|2.89x|2.40x|2.69x|2.28x|
|
146
|
+
|`(a, *args, b:, **kwargs)`|2.12x|1.82x|1.96x|1.74x|
|
148
147
|
|
149
148
|
You can run benchmarks yourself with:
|
150
149
|
|
@@ -181,7 +180,7 @@ versions:
|
|
181
180
|
|
182
181
|
We maintain API documentation using [YARD](https://yardoc.org/), which is
|
183
182
|
published automatically at
|
184
|
-
[RubyDoc.info](https://rubydoc.info/
|
183
|
+
[RubyDoc.info](https://rubydoc.info/gems/memo_wise). To
|
185
184
|
edit documentation locally and see it rendered in your browser, run:
|
186
185
|
|
187
186
|
```bash
|
@@ -236,7 +235,7 @@ And we've written more about `MemoWise` in a series of blog posts:
|
|
236
235
|
|
237
236
|
- [Introducing: MemoWise](https://medium.com/building-panorama-education/introducing-memowise-51a5f0523489)
|
238
237
|
- [Optimizing MemoWise Performance](https://ja.cob.land/optimizing-memowise-performance)
|
239
|
-
- [
|
238
|
+
- [Esoteric Ruby in MemoWise](https://jemma.dev/blog/esoteric-ruby-in-memowise)
|
240
239
|
|
241
240
|
## Logo
|
242
241
|
|
@@ -267,9 +266,16 @@ Then carry out these steps:
|
|
267
266
|
|
268
267
|
1. Update `CHANGELOG.md`:
|
269
268
|
- Add an entry for the upcoming version _x.y.z_
|
270
|
-
- Add a link for this version's comparison to the bottom of `CHANGELOG.md`
|
271
269
|
- Move content from _Unreleased_ to the upcoming version _x.y.z_
|
272
|
-
-
|
270
|
+
- Update the diff links for this version and _Unreleased_ in `CHANGELOG.md`
|
271
|
+
- Change _Unreleased_ section to say:
|
272
|
+
```
|
273
|
+
**Gem enhancements:** none
|
274
|
+
|
275
|
+
_No breaking changes!_
|
276
|
+
|
277
|
+
**Project enhancements:** none
|
278
|
+
```
|
273
279
|
- Commit with title `Update CHANGELOG.md for x.y.z`
|
274
280
|
|
275
281
|
2. Update `lib/memo_wise/version.rb`
|
data/benchmarks/Gemfile
CHANGED
@@ -2,18 +2,20 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
-
|
5
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
6
6
|
|
7
|
-
|
7
|
+
ruby ">= 2.7.7"
|
8
|
+
|
9
|
+
gem "benchmark-ips", "2.12.0"
|
8
10
|
|
9
11
|
if RUBY_VERSION > "3"
|
10
|
-
gem "dry-core", "0.
|
11
|
-
gem "memery", "1.
|
12
|
+
gem "dry-core", "1.0.1"
|
13
|
+
gem "memery", "1.5.0"
|
12
14
|
else
|
13
15
|
gem "ddmemoize", "1.0.0"
|
14
16
|
gem "memoist", "0.16.2"
|
15
|
-
gem "memoized", "1.
|
17
|
+
gem "memoized", "1.1.1"
|
16
18
|
gem "memoizer", "1.0.3"
|
17
19
|
end
|
18
20
|
|
19
|
-
gem "memo_wise",
|
21
|
+
gem "memo_wise", github: "panorama-ed/memo_wise", branch: "main"
|
data/benchmarks/benchmarks.rb
CHANGED
@@ -3,7 +3,26 @@
|
|
3
3
|
require "benchmark/ips"
|
4
4
|
|
5
5
|
require "tempfile"
|
6
|
-
|
6
|
+
|
7
|
+
github_memo_wise_path = Gem.loaded_specs["memo_wise"].full_gem_path
|
8
|
+
|
9
|
+
# This string is both used for temp filepaths necessary to separate the GitHub
|
10
|
+
# version of MemoWise and the local version, and used for the reported results
|
11
|
+
GITHUB_MAIN = "MemoWise_GitHubMain"
|
12
|
+
|
13
|
+
# We download a the main branch of MemoWise on GitHub into a tmp directory to
|
14
|
+
# compare against the local version when we run benchmarks
|
15
|
+
Dir.mktmpdir do |directory|
|
16
|
+
Dir["#{github_memo_wise_path}/lib/**/*.rb"].each do |file|
|
17
|
+
Tempfile.open([File.basename(file)[0..-4], ".rb"], directory) do |tempfile|
|
18
|
+
tempfile.write(File.read(file).gsub("MemoWise", GITHUB_MAIN))
|
19
|
+
tempfile.rewind
|
20
|
+
require tempfile.path
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require_relative "../lib/memo_wise"
|
7
26
|
|
8
27
|
# Some gems do not yet work in Ruby 3 so we only require them if they're loaded
|
9
28
|
# in the Gemfile.
|
@@ -51,6 +70,7 @@ end
|
|
51
70
|
# NOTE: Some gems do not yet work in Ruby 3 so we only test with them if they've
|
52
71
|
# been `require`d.
|
53
72
|
BENCHMARK_GEMS = [
|
73
|
+
BenchmarkGem.new(MemoWise_GitHubMain, "prepend #{GITHUB_MAIN}", :memo_wise),
|
54
74
|
BenchmarkGem.new(MemoWise, "prepend MemoWise", :memo_wise),
|
55
75
|
(BenchmarkGem.new(DDMemoize, "DDMemoize.activate(self)", :memoize) if defined?(DDMemoize)),
|
56
76
|
(BenchmarkGem.new(Dry::Core, "include Dry::Core::Memoizable", :memoize) if defined?(Dry::Core)),
|
@@ -187,11 +207,11 @@ benchmark_lambdas = [
|
|
187
207
|
|
188
208
|
# We benchmark different cases separately, to ensure that slow performance in
|
189
209
|
# one method or code path isn't hidden by fast performance in another.
|
190
|
-
benchmark_lambdas.map do |benchmark|
|
210
|
+
benchmark_jsons = benchmark_lambdas.map do |benchmark|
|
191
211
|
json_file = Tempfile.new
|
192
212
|
|
193
213
|
Benchmark.ips do |x|
|
194
|
-
x.config(suite: suite)
|
214
|
+
x.config(suite: suite)
|
195
215
|
BENCHMARK_GEMS.each do |benchmark_gem|
|
196
216
|
instance = Object.const_get("#{benchmark_gem.klass}Example").new
|
197
217
|
|
@@ -203,42 +223,52 @@ benchmark_lambdas.map do |benchmark|
|
|
203
223
|
end
|
204
224
|
|
205
225
|
JSON.parse(json_file.read)
|
206
|
-
end
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
226
|
+
end
|
227
|
+
|
228
|
+
[true, false].each do |github_comparison|
|
229
|
+
benchmark_jsons.each_with_index do |benchmark_json, i|
|
230
|
+
# We print a comparison table after we run each benchmark to copy into our
|
231
|
+
# README.md
|
232
|
+
|
233
|
+
# MemoWise will not appear in the comparison table, but we will use it to
|
234
|
+
# compare against other gems' benchmarks
|
235
|
+
memo_wise = benchmark_json.find { |json| json["name"].split.first == "MemoWise" }
|
236
|
+
benchmark_json -= [memo_wise]
|
237
|
+
|
238
|
+
github_main = benchmark_json.find { |json| json["name"].split.first == GITHUB_MAIN }
|
239
|
+
benchmark_json = github_comparison ? [github_main] : benchmark_json - [github_main]
|
240
|
+
|
241
|
+
# Sort benchmarks by gem name to alphabetize our final output table.
|
242
|
+
benchmark_json.sort_by! { |json| json["name"] }
|
243
|
+
|
244
|
+
# Print headers based on the first benchmark_json
|
245
|
+
if i.zero?
|
246
|
+
benchmark_headers = benchmark_json.map do |benchmark_gem|
|
247
|
+
# Gem name is of the form:
|
248
|
+
# "MemoWise (1.1.0): ()"
|
249
|
+
# We use this mapping to get a header of the form
|
250
|
+
# "`MemoWise` (1.1.0)
|
251
|
+
gem_name_parts = benchmark_gem["name"].split
|
252
|
+
"`#{gem_name_parts[0]}` #{gem_name_parts[1][...-1]}"
|
253
|
+
end.join("|")
|
254
|
+
puts "|Method arguments|#{benchmark_headers}|"
|
255
|
+
puts "#{'|--' * (benchmark_json.size + 1)}|"
|
256
|
+
end
|
257
|
+
|
258
|
+
output_str = benchmark_json.map do |bgem|
|
259
|
+
# "%.2f" % 12.345 => "12.34" (instead of "12.35")
|
260
|
+
# See: https://bugs.ruby-lang.org/issues/12548
|
261
|
+
# 1.00.round(2).to_s => "1.0" (instead of "1.00")
|
262
|
+
#
|
263
|
+
# So to round and format correctly, we first use Float#round and then %
|
264
|
+
"%.#{N_RESULT_DECIMAL_DIGITS}fx" %
|
265
|
+
(memo_wise["central_tendency"] / bgem["central_tendency"]).round(N_RESULT_DECIMAL_DIGITS)
|
227
266
|
end.join("|")
|
228
|
-
|
229
|
-
|
267
|
+
|
268
|
+
name = memo_wise["name"].partition(": ").last
|
269
|
+
puts "|`#{name}`#{' (none)' if name == '()'}|#{output_str}|"
|
230
270
|
end
|
231
271
|
|
232
|
-
|
233
|
-
|
234
|
-
# See: https://bugs.ruby-lang.org/issues/12548
|
235
|
-
# 1.00.round(2).to_s => "1.0" (instead of "1.00")
|
236
|
-
#
|
237
|
-
# So to round and format correctly, we first use Float#round and then %
|
238
|
-
"%.#{N_RESULT_DECIMAL_DIGITS}fx" %
|
239
|
-
(memo_wise["central_tendency"] / bgem["central_tendency"]).round(N_RESULT_DECIMAL_DIGITS)
|
240
|
-
end.join("|")
|
241
|
-
|
242
|
-
name = memo_wise["name"].partition(": ").last
|
243
|
-
puts "|`#{name}`#{' (none)' if name == '()'}|#{output_str}|"
|
272
|
+
# Output a blank line between sections
|
273
|
+
puts ""
|
244
274
|
end
|
@@ -17,8 +17,8 @@ module MemoWise
|
|
17
17
|
# zero_arg_method_name: :memoized_result,
|
18
18
|
# single_arg_method_name: { arg1 => :memoized_result, ... },
|
19
19
|
#
|
20
|
-
# #
|
21
|
-
# multi_arg_method_name: {
|
20
|
+
# # This is faster than a single top-level hash key of: [:multi_arg_method_name, arg1, arg2]
|
21
|
+
# multi_arg_method_name: { arg1 => { arg2 => :memoized_result, ... }, ... }
|
22
22
|
# }
|
23
23
|
obj.instance_variable_set(:@_memo_wise, {}) unless obj.instance_variable_defined?(:@_memo_wise)
|
24
24
|
|
@@ -70,7 +70,6 @@ module MemoWise
|
|
70
70
|
case method_arguments(method)
|
71
71
|
when SPLAT then "*args"
|
72
72
|
when DOUBLE_SPLAT then "**kwargs"
|
73
|
-
when SPLAT_AND_DOUBLE_SPLAT then "*args, **kwargs"
|
74
73
|
when ONE_REQUIRED_POSITIONAL, ONE_REQUIRED_KEYWORD, MULTIPLE_REQUIRED
|
75
74
|
method.parameters.map do |type, name|
|
76
75
|
"#{name}#{':' if type == :keyreq}"
|
@@ -105,8 +104,6 @@ module MemoWise
|
|
105
104
|
case method_arguments(method)
|
106
105
|
when SPLAT then "args"
|
107
106
|
when DOUBLE_SPLAT then "kwargs"
|
108
|
-
when SPLAT_AND_DOUBLE_SPLAT then "[args, kwargs]"
|
109
|
-
when MULTIPLE_REQUIRED then "[#{method.parameters.map(&:last).join(', ')}]"
|
110
107
|
else
|
111
108
|
raise ArgumentError, "Unexpected arguments for #{method.name}"
|
112
109
|
end
|
@@ -129,18 +126,7 @@ module MemoWise
|
|
129
126
|
def self.original_class_from_singleton(klass)
|
130
127
|
raise ArgumentError, "Must be a singleton class: #{klass.inspect}" unless klass.singleton_class?
|
131
128
|
|
132
|
-
|
133
|
-
# huge impact; for example, in our test suite this drops our test times
|
134
|
-
# from over five minutes to just a few seconds.
|
135
|
-
@original_class_from_singleton ||= {}
|
136
|
-
|
137
|
-
# Search ObjectSpace
|
138
|
-
# * 1:1 relationship of singleton class to original class is documented
|
139
|
-
# * Performance concern: searches all Class objects
|
140
|
-
# But, only runs at load time and results are memoized
|
141
|
-
@original_class_from_singleton[klass] ||= ObjectSpace.each_object(Module).find do |cls|
|
142
|
-
cls.singleton_class == klass
|
143
|
-
end
|
129
|
+
find_attached_object(klass)
|
144
130
|
end
|
145
131
|
|
146
132
|
# Convention we use for renaming the original method when we replace with
|
@@ -211,5 +197,42 @@ module MemoWise
|
|
211
197
|
end
|
212
198
|
end
|
213
199
|
private_class_method :target_class
|
200
|
+
|
201
|
+
if Module.singleton_class.respond_to?(:attached_object)
|
202
|
+
# In Ruby3.2+, for singleton classes, `#attached_object` returns the object this class is for
|
203
|
+
# https://bugs.ruby-lang.org/issues/12084
|
204
|
+
#
|
205
|
+
# @param klass [Class]
|
206
|
+
# Singleton class to find the original class of
|
207
|
+
#
|
208
|
+
# @return Class
|
209
|
+
# Original class for which `klass` is the singleton class.
|
210
|
+
def self.find_attached_object(klass)
|
211
|
+
klass.attached_object
|
212
|
+
end
|
213
|
+
else
|
214
|
+
# :nocov:
|
215
|
+
# @param klass [Class]
|
216
|
+
# Singleton class to find the original class of
|
217
|
+
#
|
218
|
+
# @return Class
|
219
|
+
# Original class for which `klass` is the singleton class.
|
220
|
+
def self.find_attached_object(klass)
|
221
|
+
# Since we call this method a lot, we memoize the results. This can have a
|
222
|
+
# huge impact; for example, in our test suite this drops our test times
|
223
|
+
# from over five minutes to just a few seconds.
|
224
|
+
@original_class_from_singleton ||= {}
|
225
|
+
|
226
|
+
# Search ObjectSpace
|
227
|
+
# * 1:1 relationship of singleton class to original class is documented
|
228
|
+
# * Performance concern: searches all Class objects
|
229
|
+
# But, only runs at load time and results are memoized
|
230
|
+
@original_class_from_singleton[klass] ||= ObjectSpace.each_object(Module).find do |cls|
|
231
|
+
cls.singleton_class == klass
|
232
|
+
end
|
233
|
+
end
|
234
|
+
# :nocov:
|
235
|
+
end
|
236
|
+
private_class_method :find_attached_object
|
214
237
|
end
|
215
238
|
end
|
data/lib/memo_wise/version.rb
CHANGED