-1
struct MyStruct {
    @ArrayOfNonOptionalElements var arr: [SomeNonOptionalType]
}

where @ArrayOfNonOptionalElements is a propertyWrapper.
So, how to force non-optionality for the type inside? Is it even possible? πŸ™„
I mean, how to implement the property wrapper in such a way, that it forces the array element type to be non-optional.

Update:
Well, looks like nobody understood my question 😣
I want the compiler to prevent putting a question mark inside the square brackets πŸ˜ƒ

Update2:
Will copy/paste here one of my comments from under the post, so everyone could easily see it:

I'm writing "@Compact" propertyWrapper for safe array decoding. So the result will be guaranteed not to contain any nils. This property wrapper can operate with any array types. So it's rather just a kind of perfectionist challenge πŸ™‚

20
  • 2
    if your array is defined as [SomeNonOptionalType] it already guaranteed to not have nils. To have nils it would be [SomeNonOptionalType?]. So what exactly are you trying to prevent.
    – timbre timbre
    Commented Apr 25 at 14:13
  • 1
    @Roman Your updates do not answer my questions. What perceived benefit do you expect to get by trying to make a developer add @ArrayOfNonOptionalElements to a line of code just incase the same developer accidentally adds a ? to the rest of the array declaration? As I said, the compiler already helps you without needing any annotation.
    – HangarRash
    Commented Apr 25 at 15:35
  • 2
    @Roman your recent questions seem to be XY problems. Instead of overly simplifying a real-world problem you're trying to solve, it would be worth actually asking a question about a real world problem in the form of a minimal reproducible example. The question of "How do I decode a JSON array in a way that if a single element cannot be decoded, it doesn't fail the whole decoding, but simply skips that element" would be a completely different question than what you ended up asking, but seemingly the problem you're actually trying to solve.
    – David Pasztor
    Commented Apr 25 at 15:59
  • 2
    I can't think of a way to do this, and it kind of makes sense that you can't. By analogy, it would be similar to having some func i<T>(_ value: T) -> T { value }, but limiting it so T arbitrary can't be Int. What harm would come if the constraint didn't exist? Generics are about constraining values by protocols, which in tern gives those generic values more power (because you have access to the protocol's requirements). If there's something that a non-optional can do that an optional can't, you should capture that in a protocol constraint.
    – Alexander
    Commented Apr 25 at 17:15
  • 1
    @Cy-4AH I've finished my work and open-sourced it. So now everybody can use the result (or even contribute πŸ˜‰). I hope you'll find it useful πŸ™‚ gitlab.com/roman.kisliachenko/decodable-kit
    – Roman
    Commented Apr 27 at 10:15

1 Answer 1

1

So, how to force non-optionality for the type inside? Is it even possible? πŸ™„

No. Swift does not have a way to express "not" in the type system. (There is a new ~Copyable coming, but it does not mean "not Copyable." It means "removes the implicit assumption of Copyable.")

I'm writing "@Compact" propertyWrapper for safe array decoding. So the result will be guaranteed not to contain any nils. This property wrapper can operate with any array types.

This isn't really accurate. Optionals are Decodable if their Wrapped is Decodable. So the following is valid:

try JSONDecoder().decode([Int?].self, from: Data("[1]".utf8)) // [Optional(1)]

This suggests your @Compact could still return an array of Optionals. And if it can return Optionals, it can return nil. The type system has to be able to prove at compile time that this is impossible, and from what you've described, it is possible, you just "promise" it won't happen. And the type system isn't letting you get away with that, as is its job.

But even if you could really promise what you're promising, the Swift type system has no way to express it.

3
  • 1
    Yeah, I think I found a nice compromise solution already. Instead of fighting the system, I will use it to gain even more functionality for my wrapper. I will just change the semantics a little bit by renaming from "@Compact" to "@Exemptify". And will not filter out "nils" in a case if a developer explicitly put "?" inside the "[]". It will only filter out decoding errors in this case. If there is no "?" inside the "[]" then "nils" become decoding errors by itself and would be filtered out automatically. Feels like very consistent behavior πŸ™‚
    – Roman
    Commented Apr 26 at 3:00
  • I've finished my work and open-sourced it. I would be grateful if you could take a look. I hope you'll find it interesting πŸ™‚ gitlab.com/roman.kisliachenko/decodable-kit
    – Roman
    Commented Apr 27 at 10:21
  • 1
    I'm personally not a real fan of property wrappers for these kinds of things. If it works for you, that's great, but I find them too fragile for complex systems. It's easy to throw away the errors, but it's hard to actually deal with them this way. I talk a little bit about that, along with how I prefer to do this, here: youtube.com/watch?v=-k_vipGhugQ&t=340
    – Rob Napier
    Commented Apr 27 at 13:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.