2025-01-07 12:30:57 +03:00
2025-01-07 12:30:57 +03:00
2025-01-07 13:02:05 +03:00
2025-01-07 12:30:57 +03:00
2025-01-07 12:30:57 +03:00
2025-01-07 12:30:57 +03:00
2025-01-07 12:30:57 +03:00
2025-01-07 12:30:57 +03:00
2025-01-07 12:30:57 +03:00
2025-01-06 11:18:33 +03:00
2025-01-07 13:03:12 +03:00
2025-01-07 12:30:57 +03:00

Maven Central Version

Attributes-kt

This is a small multiplatform library dedicated to typed attribute containers inspired by kotlinx-coroutines contexts.

Attribute is a marker interface for an attribute key.

Attributes is a generic immutable container for key-value pairs.

SafeType is a compile-type checked wrapper for KType.

Access attributes

The attribute access is done in the following way:

object MyAttribute: Attribute<Int>

val value: Int? = attributes[MyAttribute]

One could also add shortcuts to attribute container for convenience:

class MyContainer: AttributeContainer

val MyContainer.myAttribute: Int? get() = attributes[MyAttribute]

While Attributes class itself is a container that could hold any kind of attributes, its parent container (usually AttributeContainer)could expose only specific attributes via extensions.

Create attributes

Attributes is created with a function with the following signature:

fun <O> Attributes(builder: AttributesBuilder<O>.() -> Unit): Attributes

AttributeBuilder is a mutable container that exists only during attribute configuration. One could do the following operations with it:

  • put values into it via key (new values override existing values with the same key) via put operation (prefix or infix notation)
  • add or remove an element from SetAttribute
val attributes = Attributes{
    put(MyAttribute, 3)
    MyAttribute put null
    
    MyAttribute(4)
}

The last notation (invoke-based) is added for convenience.

The type-parameter of the builder is used only in compile time to provide more extension points. ForExample one could provide extensions for builder like this:

fun AttributesBuilder<MyContainer>.defaultMyAttribute() = put(MyAttribute, 0)

Modify attributes

Attributes are immutable, so to modify attributes one needs to copy them. There are several methods to do that like:

  • withAttribute - create a copy with additional (or overriding) attribute;
  • withFlag - the same for flag (value-less) attribute;
  • withAttributeElement/withoutAttributeElement - add or remove an element from set-valued attribute;
  • plus - compose (overlay) two attributes sets.

Other modifications could be added as extensions.

Generic modifications could be done via

fun <O> Attributes.modified(block: AttributesBuilder<O>.() -> Unit): Attributes

Polymorphic attributes

Polymorphic attributes (attributes, where value has a type parameter) are more complicated. They could not be used as singleton keys since each key has a different parameter. Users may want to provide a key factory instead of keys themselves so they could organize key caching and avoid creating keys on each access:

class Determinant<T>(type: SafeType<T>) :
    PolymorphicAttribute<T>(type),
    MatrixAttribute<T>

val <T> MatrixScope<T>.Determinant: Determinant<T> get() = Determinant(type)

with(matrixScope) {
    val determinant = matrix[Determinant]
}

It is possible to simplify the work with polymorphic attributes by implementing type erasure for type arguments, but it will violate structural equality guarantees. Polymorphic attributes are work in progress and could change in the future.

Artifact:

The Maven coordinates of this project are space.kscience:attributes-kt:0.3.0.

Gradle Kotlin DSL:

repositories {
    maven("https://repo.kotlin.link")
    mavenCentral()
}

dependencies {
    implementation("space.kscience:attributes-kt:0.3.0")
}
Description
Type-safe attributes container
Readme 92 KiB
Languages
Kotlin 100%