l42_map
Immutable OpenStruct On Steroids, combining Hash and OpenStruct semantics
How does it work?
Let us speculate about that:
Context Polluting the global namespace, or not?
Given that we included l42/map
require 'l42/map'
Then the global namespace is not polluted
expect {
Map
}.to raise_error(NameError, "uninitialized constant Map")
But we can access it inside the namespace
expect {
L42::Map
}.not_to raise_error
In order to access Map
inside the global namespace one needs
to do
require 'l42/map/global'
Context Setup
Given instance of L42::Map
let(:empty) { L42::Map.new }
let(:single) { L42::Map.new(a: 1) }
let(:map) { L42::Map.new(a: 10, b: 20, c: 30) }
Context The OpenStruct API
Then they can be accessed by name
expect(single.a).to eq(1)
expect(map.a).to eq(10)
expect(map.c).to eq(30)
And we can use the []
syntax
expect(empty[:a]).to be_nil
expect(single[:a]).to eq(1)
expect(map[:b]).to eq(20)
Context Extensions to the OpenStruct API
And we can use fetch
expect {
empty.fetch(:a)
}.to raise_error(KeyError)
expect(empty.fetch(:a, 42)).to eq(42)
expect(empty.fetch(:a) { 43 }).to eq(43)
expect(single.fetch(:a)).to eq(1)
And we can merge into new instances
clone = empty.merge(x: "x")
expect(clone.x).to eq("x")
expect(empty).to be_empty
Context with_default
Given a Map
instance with with_default
let(:wd) { L42::Map.new.with_default(42) }
Then any access will yield 42
expect(wd.some_value).to eq(42)
And the default value is passed on to clones
also_wd = wd.merge(a: 43)
expect(wd.a).to eq(42)
expect(also_wd.a).to eq(43)
expect(also_wd.b).to eq(42)
Context Hash
methods
And our instance behaves much like a Hash
expect(map.slice(:a, :c)).to eq(L42::Map.new(a: 10, c: 30))
Additional methods
And we can remove keys
expect(map.without(:a, :b)).to eq(L42::Map.new(c: 30))
Context Enumerable
And we can iterate
result = map.inject(0) { |s, (_k, v)| s + v }
expect(result).to eq(60)
Context Pattern Matching
And of course it behaves like a Hash in pattern matching
map => c:
expect(c).to eq(30)
expect {
map => a:, b:, **nil
}.to raise_error(NoMatchingPatternError) # sic, it is indeed a PatternMatchingError
LICENSE
Copyright 2022] Robert Dober robert.dober@gmail.com,
Apache-2.0 c.f LICENSE