Simple tests suggest that in the absence of a CustomMirror, Mirrors will enumerate struct properties in the order of declaration. Unfortunately, I wasn't able to dig up any documentation or forum post that confirms this in general. Can I always rely on this behavior?
It would be extremely helpful, to me anyway, if struct properties, in the absence of a Custom Mirror, were guaranteed to be enumerated in the order of declaration.
I’m really curious what you would use this guarantee for. You can’t use it about someone else’s types unless they’re ABI-stable and @frozen, so you want it for your own types…but then you’re imposing an extra constraint on yourself that you have to remember not to screw up. So, what’s the use case?
ABI-Stability and @frozen kinda only matter in a dynamic library scenario.
I'm hobby-working on a Compiler-Compiler and I'm not happy with the way I represent the AST. I've come up with a new design that relies on property wrappers, e.g.
struct PlusExprRule : Node {
@NonTerm var lhs : Integer
@Term var plus = "+" // this one is just a glorified character
@NonTerm var rhs : Integer
func onRecognize() throws -> PlusExpr {
// use above properties
}
}
but during parsing, the properties I want to write will pop from the stack in a specific order. This is all assuming that I get type discovery to work at all without it becoming too cumbersome.
Conversely, I want to use the presumed fact that the properties are reflected in the order they were declared in order to reconstruct what the rule says, in this case <Integer>+<Integer>.
I (and likely many others) have come to assume that property declaration order doesn't matter, and that we can freely rearrange them in whatever order might make the most sense subjectively. I think code that relies on that would be a bit astonishing.
For your case, have you considered using a macro or result builder to generate a parse function?
The parse function is not really the problem once you have the ACTION and GOTO tables. Generating those tables isn't the problem either once you have some basic graph functions and you can distinguish between terminals and non-terminals.
The real problem is what to do when you recognized a production rule. I would like to consume data types associated to non-terminals and produce another data type associated specifically to the non-terminal I just discovered.
Just to be clear, I’m saying you cannot depend on declaration order in:
an ABI-stable type that is not @frozen
any non-ABI-stable type that you don’t own
because it is generally considered a non-breaking change to reorder declarations, as AlexanderM said. (For that matter, it is also considered a non-breaking change to rename declarations of stored properties as long as you leave a computer property behind to fill the gap, and adjust Codable accordingly. So basically “Mirror on types you don’t own” can’t be trusted.)
None of this applies to your use case; thank you for sharing.
If I statically link the library I'm writing and declare my Rule types, I own them, yes. But I still need to hear from someone that in this case, I don't need to declare a custom mirror in order to be confident the mirror "works in the expected order"
I am hobby-working on an argument parser. As is the current norm, I have a struct that conforms. to an enabling protocol, and the struct has properties that are annotated by property wrappers. The wrappers collect information when the struct is initialized. I get a Mirror reflecting the struct and gather info to send to a parser. The parser sends back parsed info that is sent to the wrappers to initialize the wrapped values. As far as this is concerned neither the the order of the properties in the struct, or the order of the mirror's children, makes any difference.
However, during this process I am building an ordered list of structs that describe each property for generating help messages. For that I require that the order of the mirror's children coincide with the order of the corresponding properties in the struct.