namo 0.32.4 → 0.32.5

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: fdd20fc3b0502a069ad6bf5781b183a00e1955b6b204e76a0c14551d54a7ea28
4
- data.tar.gz: 6963897982afa093c48cde988071fa7bbc0c756cbf46e05ebd776ca695ed1008
3
+ metadata.gz: fca34f0fc6464ae1bbb80a5df45f40b63c496369b7cfbc6b32090e26bf0938f3
4
+ data.tar.gz: f156784556a7fcd2a28cef6f44178e0c4b115617cd5e64f173cfb42ca768fb53
5
5
  SHA512:
6
- metadata.gz: f9eb25cbc7db9c7af7f9f12e88be7893c972cdd4f76a3d4bf5133a6423ea41cbf27378d9a4e9e890dc09a2c38e73b1b76e4cd7218dcd08bba6bed0d49a0f440c
7
- data.tar.gz: 1683cd38dfaf86011f61f2d527ba05c15c2c79eaec8cc65d4e40bd02287bca3ff80d0ebd8f8d5f91f3e5f2b4ffcb7077958a5c50af42b39db6aa05f853873f87
6
+ metadata.gz: e47d75b0e5a23a4f131de7d8d3865dc27ad74ef91a2e87cb7c8d36a2c127784a11cf1b767978ec54b6fabf48c99f25f9a09839e229d3abd36f3851d801549257
7
+ data.tar.gz: c1f4a2ae0e3946c4c02e1f4d643b18666214224b58602ffd9185410f7e66ea949d96a1521582f98b095b9cf7b703f665014e8e42f43ed7ef65a4647da3b8efc5
data/CHANGELOG CHANGED
@@ -1,5 +1,17 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 20261003
4
+
5
+ 0.32.5: Documentation clean up.
6
+
7
+ 1. ~ README.md: + what Symbol#-@ costs, and why `/` dedupes.
8
+ 2. ~ COMPARISON.md: decomposition is relational projection, dedup and all.
9
+ 3. ~ ROADMAP.md: + the 0.9.0 memoir's 2026-10 note and the "How the demonstration ships" section.
10
+ 4. ~ lib/namo.rb: the inspected_rows comment corrected.
11
+ 5. ~ namo.gemspec: the gem name heads the file list.
12
+ 6. ~ CHANGELOG: the 0.21.0, 0.22.0 and 0.23.0 entries aligned with the commit message for each.
13
+ 7. ~ Namo::VERSION: /0.32.4/0.32.5/
14
+
3
15
  ## 20260828
4
16
 
5
17
  0.32.4: ~ README.md: + Console, the command the gem has shipped since 0.32.0 going unmentioned until now.
@@ -10,7 +22,6 @@
10
22
  4. ~ CHANGELOG: the 20260828 releases gather under one heading, as 20260824 and 20260826 gather theirs. Four releases in a day had taken a heading each.
11
23
  5. ~ Namo::VERSION: /0.32.3/0.32.4/
12
24
 
13
-
14
25
  0.32.3: ~ install.sh: + ruby-install, for a machine with no package manager at all; the handover is to a clone's own bin/namo where the script was run from one.
15
26
 
16
27
  1. ~ install.sh: + install_ruby_install, + ruby_from_ruby_install. Where no package manager is found and Homebrew is declined, ruby-install is offered — fetched from its latest release rather than a pinned version, built with make as root, and used to build Ruby. It is the last thing tried and the only route here which builds Ruby rather than fetching it.
@@ -21,7 +32,6 @@
21
32
  6. ~ install.sh: + repository, and hand_over takes the clone it was given. install_namo is the bootstrap for the handover and nothing else — a way to have a namo command to run — so a script run from a checkout hands over to that checkout's bin/namo and leaves the gem to `namo setup`, which installs it as its own first act. A checkout with the gem not yet installed now works as it stands, and the gem is named once rather than by both scripts in turn. 0.32.1 had taken the path lookup out for being unconditional, which failed piped from curl where the working directory is not a checkout; it is guarded now on $0 being a readable file beside both bin/namo and the gemspec, none of which holds for the shell's own name, so the curl route finds nothing and installs the gem as it did.
22
33
  7. ~ Namo::VERSION: /0.32.2/0.32.3/
23
34
 
24
-
25
35
  0.32.2: ~ install.sh: the one command ends with namo runnable from anywhere.
26
36
 
27
37
  1. ~ install.sh: + add_to_path, + gem_bin_directory, + shell_configuration_file. gem puts the command in a directory which is on the PATH on some machines and not on others — Homebrew's ruby puts it somewhere which is not — so the run ended by naming the directory and stopping. It now offers to add it to the shell's configuration file, and adds it to the PATH of the run itself so that `namo setup` happens rather than being left as a further instruction.
@@ -30,7 +40,6 @@
30
40
  4. ~ install.sh: + apt-get, dnf, pacman and zypper alongside Homebrew and MacPorts, so the script reaches a Ruby on Linux rather than offering to install Homebrew on a machine which has apt. + install_with_sudo, every package manager but Homebrew installing as root, so the password is asked for by name rather than arriving unannounced.
31
41
  5. ~ Namo::VERSION: /0.32.1/0.32.2/
32
42
 
33
-
34
43
  0.32.1: ~ install.sh: it runs the same piped from curl as from a clone, and forces no package manager; ~ README.md: + the one-line install.
35
44
 
36
45
  1. ~ install.sh: the handover is to `namo setup` on the PATH rather than to bin/namo beside the script. It had found bin/namo by its own path, so piped from curl it looked in the working directory and failed there. It now finds nothing by its path and so runs from anywhere. The check is for the namo command rather than for the gem, that being what the next step needs: an older namo installs no executable.
data/README.md CHANGED
@@ -214,6 +214,8 @@ The `-:price` syntax uses unary minus on Symbol to produce a negated dimension.
214
214
  sales[:product, -:price] # => ArgumentError
215
215
  ```
216
216
 
217
+ `-:price` is not a local trick: unary minus is defined on Symbol itself (`lib/Symbol.rb`), so once `namo` is loaded, every Symbol in the process has a `-@` it did not have before. Nothing in Ruby or its standard library reads a negated Symbol as anything — the ground was empty — so a collision would take another library claiming the same operator for its own purpose, and contraction is the part of Namo which yields if one does.
218
+
217
219
  Selection and contraction can be chained:
218
220
 
219
221
  ```ruby
@@ -497,7 +499,7 @@ combined / fundamentals
497
499
 
498
500
  The intersection of dimensions — here `:symbol` and `:pe` — is removed. Everything else stays. The projected rows are deduplicated, so `/` answers "what's left when these dimensions are factored out?" rather than "what rows survive a column drop?". Formulae carry through from the left-hand side.
499
501
 
500
- `/` has no precondition. When the two Namos share no dimensions, the intersection is empty, nothing is removed, and `self / other` returns a Namo equal to self:
502
+ `/` has no precondition. When the two Namos share no dimensions, the intersection is empty, nothing is removed, and `self / other` returns a Namo equal to self (multiplicity aside — the deduplication above still applies, so "equal" here means equal on duplicate-free rows):
501
503
 
502
504
  ```ruby
503
505
  shipments = Namo.new([{order_id: 1, weight: 10}])
@@ -507,7 +509,7 @@ shipments / weather
507
509
  # => #<Namo [{order_id: 1, weight: 10}]> — equal to shipments
508
510
  ```
509
511
 
510
- The round-trip identity holds for the `**` case exactly:
512
+ The round-trip identity holds for the `**` case exactly — again on duplicate-free rows, for the reason given below:
511
513
 
512
514
  ```ruby
513
515
  a = Namo.new([{symbol: 'BHP'}, {symbol: 'RIO'}])
@@ -525,7 +527,7 @@ b = Namo.new([{symbol: 'BHP', pe: 14.5}, {symbol: 'RIO', pe: 9.2}])
525
527
 
526
528
  (a * b) / b
527
529
  # => #<Namo [{close: 42.5}, {close: 118.3}]>
528
- # Equal to a[-:symbol]. :symbol was shared and is lost.
530
+ # Equal to a[-:symbol] on duplicate-free rows. :symbol was shared and is lost.
529
531
  ```
530
532
 
531
533
  The asymmetry is inherent: `/` operates only on the two values it receives and can't distinguish "shared dimension that belonged to both" from "exclusive dimension that belonged only to the right". Removing the intersection is the only rule expressible from the operands alone, and it gives clean recovery from `**` and well-defined (if lossy) recovery from `*`.
@@ -534,14 +536,20 @@ The asymmetry is inherent: `/` operates only on the two values it receives and c
534
536
 
535
537
  `*` and `**` raise when their preconditions are violated — combining unrelated Namos has no natural answer, and silently producing arbitrary output would turn a logic error into a large pile of nonsense rows. `/` is different: it's a projecting operator, not a combining one, and projecting away nothing returns the original. The no-precondition rule isn't a fallback; it's the structurally correct result.
536
538
 
537
- This earns `/` three properties a strict version would lose:
539
+ This earns `/` three properties a strict version would lose, each stated for duplicate-free rows (the projection deduplicates; see below):
538
540
 
539
541
  - **Identity test.** `combined / other == combined` exactly when the two have no shared dimensions — answers "are these Namos dimensionally independent?" without explicit introspection. Same shape as `a & b == a` answering subset from 0.6.0.
540
542
  - **Idempotence.** `(c / b) / b == c / b`. Once `b`'s dimensions are removed, removing them again does nothing.
541
- - **Pipeline composition.** A processing step that applies `/ separator` can run over any Namo regardless of whether the separator's dimensions apply. Uninvolved Namos pass through unchanged; involved Namos get stripped. The pipeline doesn't need to special-case applicability.
543
+ - **Pipeline composition.** A processing step that applies `/ separator` can run over any Namo regardless of whether the separator's dimensions apply. Uninvolved Namos pass through stripped of nothing but duplicate rows; involved Namos get their shared dimensions stripped. The pipeline doesn't need to special-case applicability.
542
544
 
543
545
  This is the same pattern that makes `Array#-` useful with arrays that aren't subsets: `[1, 2, 3] - [9] == [1, 2, 3]`, not an error. The no-op-on-non-applicable behaviour lets the operator compose into pipelines that don't know in advance whether the operation applies.
544
546
 
547
+ #### Why `/` dedupes
548
+
549
+ `/` is the one operator outside the set family (`&`, `|`, `^`) and the explicitly collapsing verbs (`uniq`, `coordinates`) that drops multiplicities — everywhere else duplicate rows are data. The collapse is definitional, and is in fact what makes `/` the inverse of the composers at all: `**` with a multi-row right operand manufactures multiplicities on the left operand's rows, so any projection that kept them could never satisfy `(a ** b) / b == a`. Inversion is only a function once duplicates are collapsed.
550
+
551
+ Projection with multiplicities intact is one line of existing operators: `namo[*other.data_dimensions.map{|d| -d}]` — contraction over the other operand's dimensions. `[]`, contraction, and everything else in the row algebra are bag-faithful, so nothing essential goes unspellable; what `/` alone adds over the contraction spelling is operand-keying plus the collapse, which is to say, its role as the composition algebra's decomposer.
552
+
545
553
  ### Equality
546
554
 
547
555
  Comparison on Namos is **multiset-theoretic on rows**: the comparison operators — `==`, `eql?`, `===`, `<`, `<=`, `>`, `>=` — ignore row order, so two Namos holding the same rows in a different order compare equal, while row multiplicities count (they *are* data). That stance is shared across the equality, pattern-match, and subset/superset operators documented below. Row order is otherwise preserved: `to_h` and `values` depend on it for columnar alignment, and `each`, `first`, `last`, `take`, `drop`, and `+` all observe it. It is the comparison operators alone that treat the sequence of rows as a multiset.
data/lib/Namo/VERSION.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # Namo::VERSION
3
3
 
4
4
  class Namo
5
- VERSION = '0.32.4'
5
+ VERSION = '0.32.5'
6
6
  end
data/lib/namo.rb CHANGED
@@ -306,9 +306,10 @@ class Namo
306
306
  @name.nil? ? '' : " #{@name.inspect}"
307
307
  end
308
308
 
309
- # The rows as they are stored, never the derived values: inspect is called
310
- # for every result in a console, and evaluating a formula there would cost a
311
- # pass over the data per access and raise whatever the formula raises.
309
+ # inspect is called for every result in a console, so evaluating the derived
310
+ # dimensions is bounded to the rows shown — INSPECTED_ROWS of them, one
311
+ # evaluation each — and a formula which raises renders no value rather than
312
+ # raising out of inspect. The cost is constant however large the data.
312
313
  def inspected_rows(rendered)
313
314
  return ' []' if @data.empty?
314
315
  shown = rendered.map{|row, derived| " #{row.merge(derived).inspect}"}.join(",\n")
data/namo.gemspec CHANGED
@@ -27,13 +27,13 @@ Gem::Specification.new do |spec|
27
27
  spec.require_paths = ['lib']
28
28
 
29
29
  spec.files = [
30
+ 'namo.gemspec',
30
31
  Dir['bin/*'],
31
32
  Dir['lib/**/*.rb'],
32
33
  Dir['test/**/*.rb'],
33
34
  'CHANGELOG',
34
35
  'Gemfile',
35
36
  'LICENSE',
36
- 'namo.gemspec',
37
37
  'Rakefile',
38
38
  'README.md',
39
39
  ].flatten
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: namo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.32.4
4
+ version: 0.32.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoran
@@ -105,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
105
  - !ruby/object:Gem::Version
106
106
  version: '0'
107
107
  requirements: []
108
- rubygems_version: 4.0.19
108
+ rubygems_version: 4.0.21
109
109
  specification_version: 4
110
110
  summary: Named dimensional data for Ruby.
111
111
  test_files: []