简体   繁体   中英

How to build a map from a function

I'm working on a library that implement a couple of generic graph types. I'm currently working on creating a clean style of instantiation.

My goal is to create a graph like such:

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

Which would create a graph with 4 vertices (1 ... 4) where 1 and 2 are connected to all the other vertices, and 3 and 4 are not connected to any. I thought this would be the cleanest and most ergonomic style. It doesn't fill the underlying map though. I know it is possible to build a map like this, because I've this kind of DSL somewhere before, but I'm struggling to figure out how.

The code that is called:

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

Anyone got any tips?

The following will allow you to write "graphOf" in a similar way you mentioned.
I overrided "to" function infix fun T.to(that: Set<T>)
Look if it helps.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM