Is there a better syntax for a fix for recursive type checking problems?


#1

I regularly need to wire cycles, and this is no problem using the DI container I wrote. Unfortunately the wiring is part of the property declaration, and this results in a recursive problem during type checking. Adding an explicit type will solve this:

class CyclesSgd(provided: Provided) : SubGraphDefinition(provided) {
    interface Provided : ProvidedBase

    // Explicit property type added here to prevent recursive problem
    val mainMenu: Definition<MainMenu> by Singleton { MainMenu() }
            .wire {
                it.eatStep = req(eatMenu)
                it.drinkStep = req(drinkMenu)
            }

    val eatMenu by Singleton { EatMenu() }
            .wire { it.quitStep = req(mainMenu) }

    val drinkMenu by Singleton { DrinkMenu() }
            .wire { it.quitStep = req(mainMenu) }
}

In this case the extra type declaration (Definition<MainMenu>) is relatively short, so it does not pollute the code too much. But in actual programs some type declarations are quite verbose, making the object definitions harder to read.

If I change the class to this, the extra type declaration is not needed. But now the object declaration has to be split in 2 properties: 1 for the delegate and 1 for the property itself. And the wiring (and other object life cycle functions) are separated from the object creation (because you cannot have multiple init blocks):

class CyclesSgd(provided: Provided) : SubGraphDefinition(provided) {
    interface Provided : ProvidedBase

    // 2 properties instead of 1, and the life cycle functions are down below
    val mainMenuDelegate = Singleton { MainMenu() }
    val mainMenu by mainMenuDelegate

    val eatMenuDelegate = Singleton { EatMenu() }
    val eatMenu by eatMenuDelegate
    
    val drinkMenuDelegate = Singleton { DrinkMenu() }
    val drinkMenu by drinkMenuDelegate
    
    init {
        mainMenuDelegate.wire {
            it.eatStep = req(eatMenu)
            it.drinkStep = req(drinkMenu)
        }
        eatMenuDelegate.wire { it.quitStep = req(mainMenu) }
        drinkMenuDelegate.wire { it.quitStep = req(mainMenu) }
    }
}

So I want the semantics of the second code snippet, but with a shorter syntax, and with all the behavior for an object definition close together. Is this possible?