Layers KT
An experiment in style and technique in Kotlin.
Layers
is a list of maps that appears as a single map. It uses rules
to provide a single value for each key, based on all values for that key in
the list of maps. For example, if the key "BOB" has values 1, 2, and 3 in
different layers, and the rule were "sum", then the value of "BOB" in the map
would be 6. Changing the rule to "latest of" for "BOB" would result in the map
having 3 for the value of that key.
(See Layers Java for an older approach in Java.)
Build and try
To build, use ./mvnw verify
or ./batect build
(for a CI-like experience).
There are no run-time dependencies.
Platform
This code relies on JDK 11 or newer.
Build
- DependencyCheck scans for dependency security issues
- detekt runs static code analysis for Kotlin
- JUnit runs tests
- JaCoCo measures code coverage
- ktlint keeps code tidy
Use ./mvnw
(Maven) or ./batect build
(Batect) to build, run tests, and
create a demo program. Use ./run.sh
or ./batect run
to run the demo.
Batect works "out of the box", however, an important optimization is to avoid redownloading plugins and dependencies from within a Docker container.
This shares Maven plugin and dependency downloads with the Docker container run by Batect.
API
General patterns
It is difficult to express in Kotlin the structure of functions without providing their names (think interfaces; meta-programming may be required), but for all functions which express map state (construction or mutation), functions come in three styles:
foo(vararg state: Pair<String, Entry<*>>): T
x = x.foo("a" to 3.toValue()) // Merge into existing mutable map
foo(state: EntryMap): T
x = x.foo(mapOf("a" to 3.toValue())) // Merge into existing mutable map
foo(state: MutableMap<String, Entry<*>>.() -> Unit): T
x = x.foo {
this["a"] = 3.toValue() // Mutate existing mutable map
}
Example functions following these patterns include new
and edit
.
Actual declarations take advantage of these type aliases:
EntryMap = Map<String, Entry<*>>
EditMap = MutableMap<String, Entry<*>>
EditBlock = EditMap.() -> Unit
Layers
Properties
layers
— an immutable list of layers, ordered from most recent to oldest. The top-most in the list is the current layercurrent
— the current, editable layer. Make updates against the _ current_ layer
Layer
Editable layer
EditableLayer
is a subtype of
Layer
.
Methods
edit
— edits with a block. AllMap
methods apply. A sample:editableLayer.edit { this["BOB"] = 3.toEntry() }
Standard rule: Constant
A layers rule which returns a constant value.
See
ConstantRule
.
Standard rule: Latest
A layers rule which returns the latest value (the value in the most recently
layer to a Layers
).
See
LatestOfRule
.
Standard rule: Sum
A layers rule which sums all values added to a Layers
.
See
SumOfRule
.
TODO
- Rationalize uses of
Map
as input vsMutableMap
reused as a property or delegated argument - Incorporate the spike having generic key and value types