To begin with, how does this proposal has already an SE number if it's still in its pitch state? Please remove the SE number from your proposal. I changed the title and moved this thread into #evolution:pitches, which is the right place for it.
My personal 2 cents about the idea:
I'm not a native English speaker and it's the first time I ever encountered the Presencable and Emptiable words, which read and sound very strange to me. In that sense I don't think they are intuitive for anyone to discover them quickly.
I also don't see any value in the Presencable protocol as its behavior is super strange on collections.
The motivation in the proposal is not clear, at least it's not clear to me.
// `[Array]` is not a well formed type
func retrieve() -> [Array] { ... }
The first example:
let array = retrieve()
guard !array.isEmpty else { return }
At this stage you know that the collection is not empty and it's already non-optional. I don't understand how the proposed solution is better then the above guard where you'd wrap, then again unwrap the collection into and from an optional just because it's empty or not.
guard let array = retrieve().presence else { return }
It's not clear what the second example means and why the presence wrapper is any better than the result expression.
func action() /* missing a return type */ {
...
return array.isEmpty : nil : array
}
Regarding to your questions,
names under negotiation, if you have some propositions – just propose :)
The idea to use Presencable protocoled types values only if they are not empty.
In this case, use-case where you process around a value with the strict understanding that it's not empty.
For example: array.presence?.first! is totally correct, and somehow we can rid of IUO operator, and just write array.presence?.first.
I like the property isEmpty on stuff, but what is the use case for Emptiable protocol? I can think of many functions that take parameters that must be non-emptiable (returning a first element of a Collection for example) but I cannot think of any function that uses Emptiable as a parameter. Could you give me some?
I don't like presence. It would be very confusing when you're dealing with Optionals ( I can already see the confusion when people will write let x: [Int]? = []; let y = x.presence and y isn't nil ).
let x: [Int]? = []; let z = x.map({ $0.presence }) will give you a double-optional which are hard to think about (people will be trying to remember was it .some(.none) for empty array, or .none?)
let x: [Int]? = []; let v = x?.presence will lose information.
Or maybe Optionals won't be Presencable even though they certainly can be empty or not?
I also don't see how guard let array = array.presence else { ... } is better than guard !array.isEmpty else { ... }. It certainly is less obvious what it does
unless I messed up the code in my head flatMap would be identical to x?.presence and would lose information about if the array is missing or just empty. If that information wasn't useful, then the array shouldn't be Optional in the first place.
If the array is just missing, there is no need to use presence.
But in the case, when you try to retrieve truly not empty, you can use it.
let a = Optional<[Int]>([1, 2])
let b = Optional<[Int]>([])
let c = Optional<[Int]>.none
if let value = a?.presence {
print(value) // [1, 2]
}
b?.presence // nil
c?.presence // nil
This isn't possible. You could update your implementation of presence to return a NonEmptyCollection or some other new type that has first, last, etc that return non-optionals. However, since presence returns an optional, optional chaining would propagate the optional and the result would be the same. At some point or other you would have to guard for nil, and I fail to see any provided use case where your suggestion offers simpler syntax or more readable code.
This isn't possible. You could update your implementation of presence to return a NonEmptyCollection or some other new type that has first , last , etc that return non-optionals. However, since presence returns an optional, optional chaining would propagate the optional and the result would be the same.
I wouldn't say impossible, it just doesn't fit in current flow.
You could update your implementation of presence to return a NonEmptyCollection or some other new type that has first , last , etc that return non-optionals.
Totally agree here, in languages without dependent types (and Swift is one of them) it's not possible to guarantee at compile time that an arbitrary collection is not empty in a certain expression.
In languages with dependent types (Idris is a good example) you could encode collection length in its type, here's how concatenation of a vector looks with dependent types:
(++) : Vect n a -> Vect m a -> Vect (n + m) a
(++) Nil ys = ys
(++) (x :: xs) ys = x :: xs ++ ys
Until Swift generics at least support values as their type parameters (like Int, e.g. Array<Int, 5> for an array of 5 elements), it won't be possible to provide any guarantees about collection's length at compile time. And even then you'd need to extend the type system to support type expressions like n + m from example above for list concatenation.