#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()
}
}