lab42_data_class 0.3.1 → 0.4.1
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/README.md +129 -3
- data/lib/lab42/data_class/proxy.rb +11 -3
- data/lib/lab42/data_class/version.rb +1 -1
- data/lib/lab42/data_class.rb +10 -0
- data/lib/lab42/eq_and_patterns.rb +19 -0
- data/lib/lab42/pair.rb +21 -0
- data/lib/lab42/triple.rb +22 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e64e5ffb63619de67de53f6618db6f25dc61e6a69b99fb6ae6cdc96446bbc490
|
4
|
+
data.tar.gz: ccf55ee9ef5d9bd3beabba0f852910ab37294a23415df78ca800e5ae411905ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c37f77d7fd444f7b64ba489e6d170b28e49ca176f74311f9aa0f269976e1561e56ba8561dd2f4b2f47cc526dc677943a98f9cd4c356c073bdc6bcebfcff29580
|
7
|
+
data.tar.gz: ed8a76bd074ad26ac625b17aec759d36300d5f0ba4ebe6ed6c827ee38149d6b8303d5bca7e8c62575fad3f2c29513577c89de0c607d15d5e109a9e813de7e59c
|
data/README.md
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
|
2
|
-
[](https://codeclimate.com/github/RobertDober/lab42_data_class)
|
3
3
|
[](https://github.com/robertdober/lab42_data_class/actions)
|
4
4
|
[](https://coveralls.io/github/RobertDober/lab42_data_class?branch=main)
|
5
|
+
[](https://rubygems.org/gems/lab42_data_class)
|
6
|
+
[](https://rubygems.org/gems/lab42_data_class)
|
5
7
|
|
6
8
|
|
7
9
|
# Lab42::DataClass
|
8
10
|
|
9
|
-
An immutable
|
11
|
+
An immutable Dataclass, Tuples and Triples
|
10
12
|
|
11
13
|
## Usage
|
12
14
|
|
@@ -31,6 +33,8 @@ require 'lab42/data_class'
|
|
31
33
|
|
32
34
|
Well let us [speculate about](https://github.com/RobertDober/speculate_about) it to find out:
|
33
35
|
|
36
|
+
## Context `DataClass`
|
37
|
+
|
34
38
|
### Context: `DataClass` function
|
35
39
|
|
36
40
|
Given
|
@@ -181,7 +185,7 @@ Then we can access the included method
|
|
181
185
|
|
182
186
|
### Context: Pattern Matching
|
183
187
|
|
184
|
-
|
188
|
+
A `DataClass` object behaves like the result of it's `to_h` in pattern matching
|
185
189
|
|
186
190
|
Given
|
187
191
|
```ruby
|
@@ -211,6 +215,128 @@ And in `in` expressions
|
|
211
215
|
expect(second).to eq(4)
|
212
216
|
```
|
213
217
|
|
218
|
+
#### Context: In Case Statements
|
219
|
+
|
220
|
+
Given a nice little dataclass `Box`
|
221
|
+
```ruby
|
222
|
+
let(:box) { DataClass content: nil }
|
223
|
+
```
|
224
|
+
|
225
|
+
Then we can also use it in a case statement
|
226
|
+
```ruby
|
227
|
+
value = case box.new
|
228
|
+
when box
|
229
|
+
42
|
230
|
+
else
|
231
|
+
0
|
232
|
+
end
|
233
|
+
expect(value).to eq(42)
|
234
|
+
```
|
235
|
+
|
236
|
+
And all the associated methods
|
237
|
+
```ruby
|
238
|
+
expect(box.new).to be_a(box)
|
239
|
+
expect(box === box.new).to be_truthy
|
240
|
+
```
|
241
|
+
|
242
|
+
### Context: Behaving like a `Proc`
|
243
|
+
|
244
|
+
It is useful to be able to filter heterogeneous lists of `DataClass` instances by means of `&to_proc`, therefore
|
245
|
+
|
246
|
+
Given two different `DataClass` objects
|
247
|
+
```ruby
|
248
|
+
let(:class1) { DataClass :value }
|
249
|
+
let(:class2) { DataClass :value }
|
250
|
+
```
|
251
|
+
|
252
|
+
And a list of instances
|
253
|
+
```ruby
|
254
|
+
let(:list) {[class1.new(value: 1), class2.new(value: 2), class1.new(value: 3)]}
|
255
|
+
```
|
256
|
+
|
257
|
+
Then we can filter
|
258
|
+
```ruby
|
259
|
+
expect(list.filter(&class2)).to eq([class2.new(value: 2)])
|
260
|
+
```
|
261
|
+
|
262
|
+
### Context: Behaving like a `Hash`
|
263
|
+
|
264
|
+
We have already seen the `to_h` method, however if we want to pass an instance of `DataClass` as
|
265
|
+
keyword parameters we need an implementation of `to_hash`, which of course is just an alias
|
266
|
+
|
267
|
+
Given this keyword method
|
268
|
+
```ruby
|
269
|
+
def extract_value(value:, **others)
|
270
|
+
[value, others]
|
271
|
+
end
|
272
|
+
```
|
273
|
+
And this `DataClass`:
|
274
|
+
```ruby
|
275
|
+
let(:my_class) { DataClass(value: 1, base: 2) }
|
276
|
+
```
|
277
|
+
|
278
|
+
Then we can pass it as keyword arguments
|
279
|
+
```ruby
|
280
|
+
expect(extract_value(**my_class.new)).to eq([1, base: 2])
|
281
|
+
```
|
282
|
+
|
283
|
+
## Context: `Pair` and `Triple`
|
284
|
+
|
285
|
+
Two special cases of a `DataClass` which behave like `Tuple` of size 2 and 3 in _Elixir_
|
286
|
+
|
287
|
+
|
288
|
+
They distinguish themselves from `DataClass` classes by accepting only positional arguments, and
|
289
|
+
cannot be converted to hashes.
|
290
|
+
|
291
|
+
These are actually two classes and not class factories as they have a fixed interface , but let us speculate about them to learn what they can do for us.
|
292
|
+
|
293
|
+
### Context: Constructor functions
|
294
|
+
|
295
|
+
Given a pair
|
296
|
+
```ruby
|
297
|
+
let(:token) { Pair("12", 12) }
|
298
|
+
let(:node) { Triple("42", 4, 2) }
|
299
|
+
```
|
300
|
+
|
301
|
+
Then we can access their elements
|
302
|
+
```ruby
|
303
|
+
expect(token.first).to eq("12")
|
304
|
+
expect(token.second).to eq(12)
|
305
|
+
expect(node.first).to eq("42")
|
306
|
+
expect(node.second).to eq(4)
|
307
|
+
expect(node.third).to eq(2)
|
308
|
+
```
|
309
|
+
|
310
|
+
And we can treat them like _Indexable_
|
311
|
+
```ruby
|
312
|
+
expect(token[1]).to eq(12)
|
313
|
+
expect(token[-2]).to eq("12")
|
314
|
+
expect(node[2]).to eq(2)
|
315
|
+
```
|
316
|
+
|
317
|
+
And convert them to arrays of course
|
318
|
+
```ruby
|
319
|
+
expect(token.to_a).to eq(["12", 12])
|
320
|
+
expect(node.to_a).to eq(["42", 4, 2])
|
321
|
+
```
|
322
|
+
|
323
|
+
And they behave like arrays in pattern matching too
|
324
|
+
```ruby
|
325
|
+
token => [str, int]
|
326
|
+
node => [root, lft, rgt]
|
327
|
+
expect(str).to eq("12")
|
328
|
+
expect(int).to eq(12)
|
329
|
+
expect(root).to eq("42")
|
330
|
+
expect(lft).to eq(4)
|
331
|
+
expect(rgt).to eq(2)
|
332
|
+
```
|
333
|
+
|
334
|
+
And of course the factory functions are equivalent to the constructors
|
335
|
+
```ruby
|
336
|
+
expect(token).to eq(Lab42::Pair.new("12", 12))
|
337
|
+
expect(node).to eq(Lab42::Triple.new("42", 4, 2))
|
338
|
+
```
|
339
|
+
|
214
340
|
# LICENSE
|
215
341
|
|
216
342
|
Copyright 2022 Robert Dober robert.dober@gmail.com
|
@@ -69,18 +69,17 @@ module Lab42
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def _define_merge
|
72
|
-
proxy = self
|
73
72
|
->(*) do
|
74
73
|
define_method :merge do |**params|
|
75
74
|
values = to_h.merge(params)
|
76
|
-
|
77
|
-
.new(**values)
|
75
|
+
self.class.new(**values)
|
78
76
|
end
|
79
77
|
end
|
80
78
|
end
|
81
79
|
|
82
80
|
def _define_methods
|
83
81
|
(class << klass; self end).module_eval(&_define_freezing_constructor)
|
82
|
+
(class << klass; self end).module_eval(&_define_to_proc)
|
84
83
|
klass.module_eval(&_define_to_h)
|
85
84
|
klass.module_eval(&_define_merge)
|
86
85
|
end
|
@@ -91,6 +90,15 @@ module Lab42
|
|
91
90
|
define_method :to_h do
|
92
91
|
proxy.to_hash(self)
|
93
92
|
end
|
93
|
+
alias_method :to_hash, :to_h
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def _define_to_proc
|
98
|
+
->(*) do
|
99
|
+
define_method :to_proc do
|
100
|
+
->(other) { self === other }
|
101
|
+
end
|
94
102
|
end
|
95
103
|
end
|
96
104
|
|
data/lib/lab42/data_class.rb
CHANGED
@@ -1,12 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative './data_class/proxy'
|
4
|
+
require_relative './pair'
|
5
|
+
require_relative './triple'
|
4
6
|
|
5
7
|
module Kernel
|
6
8
|
def DataClass(*args, **kwds, &blk)
|
7
9
|
proxy = Lab42::DataClass::Proxy.new(*args, **kwds, &blk)
|
8
10
|
proxy.define_class!
|
9
11
|
end
|
12
|
+
|
13
|
+
def Pair(first, second)
|
14
|
+
Lab42::Pair.new(first, second)
|
15
|
+
end
|
16
|
+
|
17
|
+
def Triple(first, second, third)
|
18
|
+
Lab42::Triple.new(first, second, third)
|
19
|
+
end
|
10
20
|
end
|
11
21
|
|
12
22
|
# SPDX-License-Identifier: Apache-2.0
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lab42
|
4
|
+
module EqAndPatterns
|
5
|
+
def [](idx)
|
6
|
+
to_a[idx]
|
7
|
+
end
|
8
|
+
|
9
|
+
def ==(other)
|
10
|
+
other.is_a?(self.class) &&
|
11
|
+
to_a == other.to_a
|
12
|
+
end
|
13
|
+
|
14
|
+
def deconstruct(*)
|
15
|
+
to_a
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
# SPDX-License-Identifier: Apache-2.0
|
data/lib/lab42/pair.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'eq_and_patterns'
|
4
|
+
module Lab42
|
5
|
+
class Pair
|
6
|
+
attr_reader :first, :second
|
7
|
+
include EqAndPatterns
|
8
|
+
|
9
|
+
def to_a
|
10
|
+
[first, second]
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def initialize(first, second)
|
16
|
+
@first = first
|
17
|
+
@second = second
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
# SPDX-License-Identifier: Apache-2.0
|
data/lib/lab42/triple.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'eq_and_patterns'
|
4
|
+
module Lab42
|
5
|
+
class Triple
|
6
|
+
attr_reader :first, :second, :third
|
7
|
+
include EqAndPatterns
|
8
|
+
|
9
|
+
def to_a
|
10
|
+
[first, second, third]
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def initialize(first, second, third)
|
16
|
+
@first = first
|
17
|
+
@second = second
|
18
|
+
@third = third
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
# SPDX-License-Identifier: Apache-2.0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lab42_data_class
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Dober
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
An Immutable DataClass for Ruby
|
@@ -26,6 +26,9 @@ files:
|
|
26
26
|
- lib/lab42/data_class/proxy.rb
|
27
27
|
- lib/lab42/data_class/proxy/mixin.rb
|
28
28
|
- lib/lab42/data_class/version.rb
|
29
|
+
- lib/lab42/eq_and_patterns.rb
|
30
|
+
- lib/lab42/pair.rb
|
31
|
+
- lib/lab42/triple.rb
|
29
32
|
homepage: https://github.com/robertdober/lab42_data_class
|
30
33
|
licenses:
|
31
34
|
- Apache-2.0
|