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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e4127a34f013386209c71666f9d77e1b5c8fd439324443580e00c7e9018fdb4
4
- data.tar.gz: c61d6f1648c9c73cd89883a0c0e6ebd6ea813f51dcdb26f141a99a962e4db5fa
3
+ metadata.gz: e64e5ffb63619de67de53f6618db6f25dc61e6a69b99fb6ae6cdc96446bbc490
4
+ data.tar.gz: ccf55ee9ef5d9bd3beabba0f852910ab37294a23415df78ca800e5ae411905ab
5
5
  SHA512:
6
- metadata.gz: 74b643eb6d43c00aedede31195354412a0b7dcabc5f5da0d1c3f5dbfca4dc03abc1b13a68e10307813153b6e8fe0c502a075a9c4ef17c61f1163ec251e03b3f7
7
- data.tar.gz: '007384216191284048c0fcec62adedb04c8f41a549b92d7cdefcbaa3fa2f4536cce737d4a21a6c8d3648fe62a539fd9f201cd036566b9ff3251ac2929856a6a7'
6
+ metadata.gz: c37f77d7fd444f7b64ba489e6d170b28e49ca176f74311f9aa0f269976e1561e56ba8561dd2f4b2f47cc526dc677943a98f9cd4c356c073bdc6bcebfcff29580
7
+ data.tar.gz: ed8a76bd074ad26ac625b17aec759d36300d5f0ba4ebe6ed6c827ee38149d6b8303d5bca7e8c62575fad3f2c29513577c89de0c607d15d5e109a9e813de7e59c
data/README.md CHANGED
@@ -1,12 +1,14 @@
1
1
 
2
- [![Gem Version](http://img.shields.io/gem/v/lab42_data_class.svg)](https://rubygems.org/gems/lab42_data_class)
2
+ [![Issue Count](https://codeclimate.com/github/RobertDober/lab42_data_class/badges/issue_count.svg)](https://codeclimate.com/github/RobertDober/lab42_data_class)
3
3
  [![CI](https://github.com/robertdober/lab42_data_class/workflows/CI/badge.svg)](https://github.com/robertdober/lab42_data_class/actions)
4
4
  [![Coverage Status](https://coveralls.io/repos/github/RobertDober/lab42_data_class/badge.svg?branch=main)](https://coveralls.io/github/RobertDober/lab42_data_class?branch=main)
5
+ [![Gem Version](http://img.shields.io/gem/v/lab42_data_class.svg)](https://rubygems.org/gems/lab42_data_class)
6
+ [![Gem Downloads](https://img.shields.io/gem/dt/lab42_data_class.svg)](https://rubygems.org/gems/lab42_data_class)
5
7
 
6
8
 
7
9
  # Lab42::DataClass
8
10
 
9
- An immutable dataclass
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
- An `DataClass` object behaves like the result of it's `to_h` in pattern matching
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
- DataClass(*proxy.positionals, **proxy.defaults, &proxy.block)
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
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Lab42
4
4
  module DataClass
5
- VERSION = "0.3.1"
5
+ VERSION = "0.4.1"
6
6
  end
7
7
  end
8
8
  # SPDX-License-Identifier: Apache-2.0
@@ -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
@@ -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.3.1
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-01-23 00:00:00.000000000 Z
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