Search code examples
swiftswift-stencilsourcery

Access random array element using Sourcery and Stencil


I'm doing some code generation stuff using Sourcery and Stencil.

I'm trying to add an extension to all my enums that has a method that returns a random case of the enum. So, in my case, I need a way to access a random array element.

I know that we can do array lookup using one of the following ways: (first, last or by index), but I can't find a way to access a random element.

Here is an example of what I'm trying to achieve:

{% for type in types.enums %}
extension {{ type.name }} {
    static func random() -> {{ type.name }} {
         let index = Int.random(in: 0..<{{ type.cases.count }})
         return .{{ type.cases.index.name }}
    }
}
{% endfor %}

The previous code snippet doesn't work, obviously. I just added it as a way to make my intention clear.

Does anyone have an idea about this?


Solution

  • So, after the ideas posted by others here (thanks to them). I implemented it like the following as I also need to randomize the associated values of the cases that have associated values:

    {% for type in types.enums %}
    extension {{ type.name }} {
        static func random() -> {{ type.name }} {
            let cases: [{{ type.name }}] = [
            {% for case in type.cases %}
            {% if case.associatedValues.count > 0 %}
            {% map case.associatedValues into values using value %}.random(){% endmap %}
                .{{ case.name }}({{ values|join:", " }}),
            {% else %}
                .{{ case.name }},
            {% endif %}
            {% endfor %}
            ]
            return cases.randomElement()!
        }
    }
    {% endfor %}
    

    The above code snippet iterates over the cases of the enum and creates an array that contains all the cases. If a case has associated values, it will create a random element for each associated value using the random() method.