Adding dynamic properties on top of the Mirror-values for context variables / Improved support for computed properties
ralfebert opened this issue · 0 comments
I just digged into the topic of how to use computed properties with Stencil because I had this issue in a project of mine.
This was already discussed here:
This bug report was closed because this feature was added:
- Dynamic member lookup
7247d0a
I was looking for something better compared to the workaround "don't use computed properties, always set regular properties instead". For example, if you want to pass a struct to Stencil like this and use the sum
property:
struct Prices {
let prices: [Decimal]
var sum: Decimal {
prices.reduce(0, +)
}
}
you could use something like this:
struct Prices {
let prices: [Decimal]
var sum: Decimal = 0
mutating func updateSum() {
self.sum = prices.reduce(0, +)
}
}
I didn't like this solution too much, thus this bug report. The only clean alternative would be manually mapping the data types to Dictionary, which would mean a lot of manual busywork for complex types.
I tinkered with DynamicMemberLookup, you could add the sum
property yourself, but then you loose the support for accessing other properties via the Mirror approach. One could copy the Mirror#getValue
method from Stencil and use that as fallback, but looking at that method and the nil-handling I thought: no, better not.
I wondered:
Would it make sense to fall back to the Mirror-resolving if DynamicMemberLookup doesn't resolve a value? That way one could add code to add computed properties by manually resolving them.
So you could add something like this:
extension Prices: DynamicMemberLookup {
subscript(dynamicMember member: String) -> Any? {
if member == "sum" {
return self.sum
}
return nil
}
}
and could still access the prices
property without manually resolving it.
This currently is not possible, if it implements DynamicMemberLookup, it will not resolve via Mirror anymore:
Or maybe an extra protocol like DynamicMemberLookup that allows to add dynamic properties on top of the mirrored ones like that?