Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding dynamic properties on top of the Mirror-values for context variables / Improved support for computed properties #339

Open
ralfebert opened this issue Apr 12, 2023 · 0 comments

Comments

@ralfebert
Copy link

ralfebert commented Apr 12, 2023

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:

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:

https://github.com/stencilproject/Stencil/blob/4f222ac85d673f35df29962fc4c36ccfdaf9da5b/Sources/Stencil/Variable.swift#L121:L124

Or maybe an extra protocol like DynamicMemberLookup that allows to add dynamic properties on top of the mirrored ones like that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant