Hullaballoonatic

    Hullaballoonatic

    2 years ago
    I often use inner classes in the following way (honestly don't know other uses for them):
    open class Line(open var from: Point, open var to: Point) {
        val reversed = Reversed
        inner class Reversed : Line(to, from) {
            override var from: Point
                get() = <mailto:this@Line.to|this@Line.to>
                set(v) {
                    <mailto:this@Line.to|this@Line.to> = v
                }
    
            override var to: Point ...
        }
    }
    Where every instance of Line has its own singular instance of Reversed, which only borrows its state from Line, and is otherwise stateless It is here that the idea of
    inner object
    comes to mind
    interface Line {
        var from: Point
        var to: Point
    
        inner object Reversed : Line {
            override var from: Point
                get() = <mailto:this@Line.to|this@Line.to>
                set(v) {
                    <mailto:this@Line.to|this@Line.to> = v
                }
    
            override var to: Point ...
        }
    }
    I'm not sure if this is the best nomenclature for this structure, though. Maybe
    satellite
    ? Could this be considered stateless in the same way that any getters/setters are? And thus usable in interfaces?
    raulraja

    raulraja

    2 years ago
    An object should be a singleton value but anything inner is a path dependent type which captures the member scope of the outer type declaration. That is you need the outer value to produce a new value of the type of the inner class.
    Is not clear to me how object can be supported as inner. The cooler feature is to have abstract types that serve as alternative or desugar into type parameters. Then you could override the type to say it's any object of your choosing. Not sure abstract path dependent types are possible in Kotlin but maybe I'm missing a possible encoding.
    j

    jimn

    2 years ago
    I'm doing something near to this:
    interface Pai2<F, S> {
        val first: F
        val second: S
        val pair get() = let { (a, b) -> a to b }
        operator fun component1(): F = first
        operator fun component2(): S = second
    
        companion object {
            operator fun <F, S> invoke(f: F, s: S) = object : Pai2<F, S> {
                override val first get() = f
                override val second get() = s
            }
    
            operator fun <F, S, P : kotlin.Pair<F, S>, R : Pai2<F, S>> invoke(p: P) = p.let { (f, s) -> Pai2(f, s) }
        }
    }
    typealias Vect0r<T> = Pai2<() -> Int, (Int) -> T>
    fun <  T> Vect0r<T>.toList() = object : AbstractList<T>() {
        override val size get() = size()
        override operator fun get(index: Int): T =second(index)
    } 
    fun <T, R, V : Vect0r<T>> V.map(fn: (T) -> R): Vect0r<R> = Vect0r(size, { ix: Int ->                      second(ix).let(fn) })
    inline operator fun <reified T> Vect0r<T>.get(index: Int): T = second(index)
    without all the stdlib classes in the way, this "Vect0r" thing composes functions that don't really store state. .map and other operators just compose deeper transofrms until .toList() is used to reify for effects. having an inherritable tuple seems every bit as important as an inheritable list, imho. Artist's rendition of Line class:
    typealias Point<T>  = Pai2< ()->T,    ()->T>
    typealias Line<T>  = Pai2< Point<T>,   Point<T>>
    val Line.reversed get()=let{(a,b)->Line(b,a)}