https://kotlinlang.org logo
#language-evolution
Title
# language-evolution
h

Hullaballoonatic

01/01/2020, 7:24 PM
I often use inner classes in the following way (honestly don't know other uses for them):
Copy code
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
Copy code
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?
👍 1
r

raulraja

01/02/2020, 12:16 AM
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.
🤔 1
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

01/03/2020, 3:15 PM
I'm doing something near to this:
Copy code
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:
Copy code
typealias Point<T>  = Pai2< ()->T,    ()->T>
typealias Line<T>  = Pai2< Point<T>,   Point<T>>
Copy code
val Line.reversed get()=let{(a,b)->Line(b,a)}
2 Views