Are there any common (Mutable)List implementations...
# getting-started
d
Are there any common (Mutable)List implementations that will wrap/unwrap the values from a delegate list? For example
Copy code
val myList: MutableList<String> = mutableListOf<String>()
val myWrappedList: MutableList<Wrapper> = wrap(myList, { Wrapper(it) }, { wrapper -> wrapper.value })
c
If you want the result to be read-only, that's
.map {}
. For two-way mapping, I'm not aware of anything in the stdlib, but we tend to avoid mutability anyway so I'm curious what your use-case is
d
I was thinking about it in the context of a iCalendar object model I’m building. It has a couple layers of abstraction. The higher level classes wrap lower level ones, and it made sense in my context to return a high level view of a low level list.
Example:
Copy code
val attachments get() = component.all(DescriptiveProperties.Attachment)
    val attendees get() = component.all(RelationshipProperties.Attendee)
    val categories get() = component.all(DescriptiveProperties.Categories)
    val comments get() = component.all(DescriptiveProperties.Comment)
    val contacts get() = component.all(RelationshipProperties.Contact)
    val exceptionDates get() = component.all(RecurrenceProperties.ExceptionDate)
    val requestStatuses get() = component.all(MiscellaneousProperties.RequestStatus)
    val relatedTo get() = component.all(RelationshipProperties.RelatedTo)
    val resources get() = component.all(DescriptiveProperties.Resources)
    val recurrenceDates get() = component.all(RecurrenceProperties.RecurrenceDate)

    fun add(attachment: DescriptiveProperties.Attachment) = component.add(attachment)
    fun add(attendee: RelationshipProperties.Attendee) = component.add(attendee)
    fun add(category: DescriptiveProperties.Categories) = component.add(category)
    fun add(comment: DescriptiveProperties.Comment) = component.add(comment)
    fun add(contact: RelationshipProperties.Contact) = component.add(contact)
    fun add(exceptionDate: RecurrenceProperties.ExceptionDate) = component.add(exceptionDate)
    fun add(requestStatus: MiscellaneousProperties.RequestStatus) = component.add(requestStatus)
    fun add(relatedTo: RelationshipProperties.RelatedTo) = component.add(relatedTo)
    fun add(resource: DescriptiveProperties.Resources) = component.add(resource)
    fun add(recurrenceDate: RecurrenceProperties.RecurrenceDate) = component.add(recurrenceDate)
c
Well, if you just need
MutableList
, it shouldn't be too hard to implement yourself. The most difficult part will be the mutating iterators
d
I’ve done it before, so I thought about it.
e
a basic implementation doesn't take much work
Copy code
fun <T, R> wrap(list: MutableList<T>, wrapper: (T) -> R, unwrap: (R) -> T): MutableList<R> = object : AbstractMutableList<R>() {
    override val size: Int
        get() = list.size
    override fun get(index: Int): R = wrapper(list[index])
    override fun set(index: Int, element: T): R = wrapper(list.set(index, unwrap(element)))
    override fun add(index: Int, element: R): Unit = list.add(index, unwrap(element))
    override fun removeAt(index: Int): R = wrap(list.removeAt(index))
}
but generally I'd consider mutable views to be questionable
d
That's basically what I ended up doing:
Copy code
class JsonArrayWrapper<V>(
    private val converter: Converter<JsonElement, V>,
    val jsonArray: JsonArray = JsonArray()
): AbstractMutableList<V>() {
    override fun add(index: Int, element: V) {
        jsonArray.add(index, converter.reverse(element))
    }

    override fun removeAt(index: Int): V {
        return converter.forward(jsonArray.removeAt(index))
    }

    override fun set(index: Int, element: V): V {
        return converter.forward(jsonArray.set(index, converter.reverse(element)))
    }

    override val size: Int get() = jsonArray.size

    override fun isEmpty(): Boolean {
        return jsonArray.isEmpty()
    }

    override fun get(index: Int): V {
        return converter.forward(jsonArray[index])
    }
}