Just because they have "a little" hair doesn't mean they don't have any. A mammal, by definition, must possess hair:
Mammals are the vertebrates within the class Mammalia (/məˈmeɪliə/ from Latin mamma "breast"), a clade of endothermic amniotes distinguished from reptiles (including birds) by the possession of a neocortex (a region of the brain), hair, three middle ear bones, and mammary glands. Females of all mammal species nurse their young with milk, secreted from the mammary glands.
If you had as much hair as a naked mole-rat, you wouldn't be saying, "I have hair" :)
The definition of a mammal does not rest on any particular physical attribute; taxonomy hasn't worked that way for a long while. Take it from someone who created a genetically modified mouse strain.
(As a sidenote, one other thing that Discourse doesn't seem to do is allow for private discussions "off-list" instead of polluting threads with tangents. Is there a better way to do this?)
We should at least try to avoid tangents over definitions of words, which are inherently flexible. Your previous classification of mammal would suggest hair removal surgery is all it takes to switch branch in the family tree. We could nitpick things like this all day, but it's a wasted effort as long as we all recognise what's being discussed.
As a general rule, if a tangent is worth discussing, I'd say it's worth making a new thread for.
forEach is a nice method to be used to terminate the call chains like xs.filter { ... }.map { ... }. The alternative being to then break the flow, return all the way of the beginning of the chain and wrap it into a for ... in ... loop this way or the other.
Also let's not forget that map is not free, as it always allocates an array to hold the result.
I said it in the past somewhere, and I still believe that porting some Collection methods to Optional would be nice. However I disagree with the ifSome(then:) name. We already have a name for such operation and it's forEach(_:).
We need to stop the forced parallels between Optional and Collection, just because Optional has map and flatMap, doesn't mean we need to crowbar in every API that seems to do something similar. I'll defer to my previous statement:
Following this logic, any type that is a functor (implements map) and that is also a monad (is a functor that also implements flatMap) should follow suite. Promise is one such type. Let's have a Promise.forEach. Compare the syntax:
let p: Promise<File> = downloadFile("www.something.com/file")
p.then { print($0 } // makes sense!
p.forEach { print($0) } // wut
We could make some forced connection between promises and collections, saying that a Promise is a collection of 0 or 1 values: but it just doesn't serve us any good. We chose then(_:) because it makes more sense than forEach(_:), even if under some contrived conformance to collection, they would do the same thing.
Naming ifNone(then:) opens up the opportunity for also having ifNil(then:). What would the counterpart to forEach(_:) be, in that case?
I look at it as a matter of familiarity and recognizability, if you will, of the API. It is not about the Collection-ness of Optionals, but about this specific method, that unwraps the abstraction and applies a closure to every single value that happens to be inside. Promise fits...
I might be brain-damaged beyond repair, but it's only Result.forEach that seems a little unnatural to me.
Haha fret not, I don't think you're brain damaged.
Yes, I did concede that promise "fits" technically speaking:
But I think our APIs should center around what's intuitively true, over that's technically true. This is a valid way of looking at it, and I don't contest that. The issue is that it's not an obvious observation to make, and would certainly not be obvious to someone learning how to work with optional or promises in the first place. Even for those who do know about this similarity, like you and I, I'm sure that we can agree that getPromise().then(doSomething) is more intuitive.
I'd further like to note, that sometimes you have to work with a collection of promises. Some poorly-designed APIs only work with single cases per request, requiring multiple requests. It's not a good thing, but it's a fact of life we need to put up with sometimes. The distinction between the forEach of the collection, and the then of the promise is a useful distinction to make: promises.forEach { $0.then(doSomething) }.
If Promise.forEach isn't unnatural, why do you find Result.forEach unnatural? Where's the distinction?
I do not understand the ifNil(then:) part, I'm afraid. What's its signature?
Result contains some payload even in its Left or Error case, which is completely ignored by map and forEach, depending on the implementation of course. That is the unnatural part that I meant.
This is a contrived example of the usage, but it follows from your earlier point:
The same wrapping a long chain in a for loop is a bit mesy, the same could be said for if. The variable declaration is at the very start of the whole expression, before the chain, yet its usage is in the block at the very end, after the chain:
if let result = Something() // result defined all the way up here
.doSomething()
.map { $0.something }
.filter({ $0.isValid }) { // can't use trailing closure syntax on last line
use(result) //result used all the way down here
}
else {
handleNil()
}
compared to:
Something()
.doSomething()
.map { $0.something }
.filter{ $0.isValid } // can use trailing closure here
.ifSome(then: { result in use(result) }) // result declared close to where its used
// could even just be: .ifSome(then: use)
.ifNone(then: handleNil)
What would the forEach equivalent be?
Something()
.doSomething()
.map { $0.something }
.filter{ $0.isValid }
.forEach(use)
.ifEmpty(the: handleNil) // Empty? I thought it was called Optional.none or nil!
Oh I see what you're saying. I personally don't like this approach where you chain both the "then" and the "else" branches. I'd much rather linearize the chain using something like Optional.orElse(() -> Optional) and then terminate it with a forEach (or whatever the name ends up being).
I had considered that, but it doesn't well if you only care about the nil case. Sure, you could default the then closure to { _ in }, but then it reads as ifSome(else: { ... }), which is not ideal. Even worse, with a trailing closure, it would be ifSome { ... }
Better, but inarguably more cluttered (why waste a full line for then: { and else: {?) and incompatible with trailing closures, which is the nail in the coffin, imo.