NonEmpty<NonEmpty<C>>
doesn't mean the collection has at least 2 values
#45
Replies: 4 comments 5 replies
-
Originally, struct NonEmpty<C: Collection>: Collection {
var head: C.Element
var tail: C
} This was changed in #26 for performance, bug-avoidance, and added functionality, to the following: struct NonEmpty<C: Collection>: Collection {
var rawValue: C
// ... validated non-empty via init
} But if I'm understanding correctly, your suggestion is something more like the following? struct NonEmpty<C: Collection>: Collection {
var head: C.Element
var tail: Slice<C>
} This is definitely interesting! In addition to the functionality you mention, it also avoids some of the issues we aimed to address in #26. The main gotchas I can think of is that the value of |
Beta Was this translation helpful? Give feedback.
-
I also thought about other features that could be added at the same time. Basically, What we could do is something like this (pseudo Swift code) extension NonEmpty<NonEmpty<C>> {
var second: C.Element { tail.first }
}
extension NonEmpty<NonEmpty<NonEmpty<C>>> {
var third: C.Element { tail.second }
}
extension NonEmpty<NonEmpty<NonEmpty<NonEmpty<C>>>> {
var fourth: C.Element { tail.third }
}
extension NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<C>>>>> {
var fifth: C.Element { tail.fourth }
}
extension NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<C>>>>>> {
var sixth: C.Element { tail.fifth }
}
extension NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<C>>>>>>> {
var seventh: C.Element { tail.sixth }
}
extension NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<C>>>>>>>> {
var eighth: C.Element { tail.seventh }
}
extension NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<C>>>>>>>>> {
var ninth: C.Element { tail.eighth }
}
extension NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<C>>>>>>>>>> {
var tenth: C.Element { tail.ninth }
} Now we can safely access indexes 1 to 10, but not above. I had an idea though (still pseudo Swift code): extension NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<C>>>>>>>>>>> {
var drop10: NonEmpty<C> { get }
} This way, we can do |
Beta Was this translation helpful? Give feedback.
-
Another problem I stumbled upon is the actual failing initializer ( let myOptionalCollectionWithAtLeast4Elements = NonEmpty(rawValue: elements)
.flatMap(NonEmpty.init(rawValue:))
.flatMap(NonEmpty.init(rawValue:))
.flatMap(NonEmpty.init(rawValue:)) I don't know why you chose The throwing initializer would allow avoiding optional chaining, like so: let myOptionalCollectionWithAtLeast4Elements = try? NonEmpty(NonEmpty(NonEmpty(NonEmpty(elements)))) |
Beta Was this translation helpful? Give feedback.
-
If you accept my previous two propositions (about typealias AtLeast2<C> = NonEmpty<NonEmpty<C>>
extension AtLeast2 {
var second: C.Element { get }
}
typealias AtLeast3<C> = NonEmpty<NonEmpty<NonEmpty<C>>>
extension AtLeast3 {
var third: C.Element { get }
}
// ...
typealias AtLeast10<C> = NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<NonEmpty<C>>>>>>>>>>
extension AtLeast10 {
var tenth: C.Element { get }
}
extension NonEmpty {
static func atLeast2<C>(_ c: C) -> AtLeast2<C>
static func atLeast3<C>(_ c: C) -> AtLeast3<C>
// ...
static func atLeast10<C>(_ c: C) -> AtLeast10<C>
}
This would remove the necessity to use It would also also replace Finally, like |
Beta Was this translation helpful? Give feedback.
-
I really like the safety of
NonEmpty
. I am writing a fully type-safe geographical library, also providing GeoJSON mapping, and I need to store arrays that have at least four values for example (see RFC 7946, section 3.1.6 for example).I thought I'd use
NonEmpty<NonEmpty<NonEmpty<NonEmpty<[MyType]>>>>
, but I was surprised to se it's not how the library works. NonEmpty.swift#L9-L10 shows that the collection is stored as-is, not cut into a head value and a tailSlice
.Is it a conscious choice? Wouldn't it be semantically better to make
NonEmpty
behave as I thought?Beta Was this translation helpful? Give feedback.
All reactions