Как построить карту из функции

#dictionary #kotlin #dsl

#словарь #котлин #dsl

Вопрос:

Я работаю над библиотекой, которая реализует несколько общих типов графов. В настоящее время я работаю над созданием чистого стиля создания экземпляра.

Моя цель — создать график, подобный такому:

 val graph = graphOf<Int>(true) {
            1 to setOf(2,3,4,)
            2 to setOf(1,3,4,)
            3 to emptySet<Int>()
            4 to emptySet<Int>()
        }
 

Что создало бы граф с 4 вершинами (1 … 4), где 1 и 2 связаны со всеми остальными вершинами, а 3 и 4 не связаны ни с одной. Я думал, что это будет самый чистый и эргономичный стиль. Однако он не заполняет базовую карту. Я знаю, что можно создать такую карту, потому что у меня где-то раньше был такой DSL, но я изо всех сил пытаюсь понять, как это сделать.

Код, который вызывается:

 fun <Vertex> graphOf(
    isDirected: Boolean,
    vertexEdgeMap: MutableMap<Vertex, Set<Vertex>>.() -> Unit // I think the problem lies here?
) = graphOf(isDirected, mutableMapOf<Vertex, Set<Vertex>>().also(vertexEdgeMap))

fun <Vertex> graphOf(
    isDirected: Boolean,
    vertexEdgeMap: Map<Vertex, Set<Vertex>> = emptyMap()
): Graph<Vertex> = mutableGraphOf(isDirected, vertexEdgeMap)

fun <Vertex> mutableGraphOf(
    isDirected: Boolean,
    vertexEdgeMap: Map<Vertex, Set<Vertex>> = emptyMap()
): MutableGraph<Vertex> = MutableAdjacencyMapGraphImpl<Vertex>(isDirected)
    .apply {
        vertexEdgeMap.forEach { addVertex(it.key) }
        vertexEdgeMap.forEach {
            from -> from.value.forEach {
            to -> addEdge(from.key, to) }
        }
    }
 

У кого-нибудь есть какие-нибудь советы?

Ответ №1:

Следующее позволит вам написать «graphOf» аналогичным образом, о котором вы упомянули.
Я переопределил функцию «to» infix fun T.to(that: Set<T>)
Посмотрите, поможет ли это.

 class GraphBuilder<T> {
    val graph: MutableMap<T, Set<T>> = mutableMapOf()

    infix fun T.to(that: Set<T>): GraphBuilder<T> {
        val graphBuilder = this@GraphBuilder
        graphBuilder.graph.put(this, that)
        return graphBuilder
    }
}

fun <T> graphOf(pair: GraphBuilder<T>.() -> Unit): GraphBuilder<T> {
    val builder = GraphBuilder<T>()
    pair(builder)
    return builder
}

fun main() {
    val graph =
        graphOf<Int>() {
            1 to setOf(2, 3, 4)
            2 to setOf(1, 3, 4)
            3 to emptySet()
            4 to emptySet()
        }
}