|
Perhaps you should be programming in Q#[^]?
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
|
So if you asked your sergeant if your platoon was all present and correct when in fact they'd all been blown to smithereens and the platoon was now devoid of soldiers, you would still expect the answer "Yes"?
|
|
|
|
|
In your example, the sergeant is probably asking about the set of soldiers assigned to the platoon (regardless of status). In which case, the set isn't empty, and the answer is "no".
However, if the sergeant was asking if all soldiers in your platoon who were capable of showing up were there, then the answer is "yes". Note: technically, the set still isn't empty, as you are presumably in your own platoon. However, the logic would still apply if the question was asked about another platoon where no one was left alive - everyone who was capable of showing up would be there...
|
|
|
|
|
The officer doing the asking is enquiring about the present state of his platoon, not what it might have been. He wants to know how many men he has left in that platoon, if any (he's a practical chap). The Sergeant isn't necessarily a member of the platoon in question.
It's a valid question before possibly sending the platoon out on another patrol, one which requires a practical answer. A platoon now devoid of soldiers wouldn't perform well on patrol.
|
|
|
|
|
Exactly! The officer needs to know how many men are available (a platoon of one wouldn't perform well either). He could have asked, "How many are available?" But he didn't (in this example). Presumably he can see there's no one there, so he effectively asked, "Is this everyone in the platoon?" The correct answer at that point is "Yes", at which point he knows what he has to work with (even if it's zero).
To answer No at this point would imply that there are others who are not present, which isn't the case.
If we were to write that in code, it would be Platoon.AreAllPresent(), and the result would be True as long as no members of the Platoon are absent (even if there are no members of the Platoon).
|
|
|
|
|
Here's a more obscure one.
HashAlgorithm.TransformBlock is for computing things like MD5 and SHA hashes on streamable data. TransformFinalBlock needs to be called at the end, even if there's no data left to include in the hash. Notably you have to give it both an array AND the length.
You can give it an empty byte[] and specify it has 0 length, and it's perfectly happy.
But give it a null buffer - even if you specify 0 length! - and it throws on you. I'm explicitly telling it I have no data to give it, but I still have to give it the empty array, for reasons.
|
|
|
|
|
In logic, ALL(P(x)) would be equivalent to NOT ANY(NOT P(x)) . So if you agree on that [Empty].Any(...) would always be false, then it logically follows that [Empty].All(...) would be true.
|
|
|
|
|
Yes, we have no bananas....
how about malloc( 0 ) not returning NULL.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
That was interesting.
Apparently that is undefined so implementation dependent.
I wonder why. I suspect some memory allocators would have trouble with allocating an empty block so perhaps that is the reason to allow null.
What is additionally interesting was that I was thinking it would return just a pointer to the heap block tracker. That is so free still works.
But of course it could actually return real space. So for example if the allocator just always sizes up to a block (say 16 bytes) it might be valid space.
|
|
|
|
|
I brought it up a while back and there was some back and forth on it.
Apparently, malloc( 0 ) not returning NULL is deliberate.
Here is what GCC does with some short bit of code
printf("Hello world!\n");
printf( "call malloc(0)\n" );
sz = (char*)malloc(ZERO);
printf( "Errno %d\n", errno );
if( sz == NULL ) printf( "returned NULL allocated zero bytes\n");
else printf( "NULL not returned from malloc, allocated 8 bytes\n" );
Hello world!
call malloc(0)
Errno 0
NULL not returned from malloc, allocated 8 bytes
Apparently this is allowed by GCC.
The argument is that it was successful
Haven't tried it in VS.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
jmaida wrote: Apparently, malloc( 0 ) not returning NULL is deliberate.
Standard says either is allowed.
jmaida wrote: allocated 8 bytes
Without the actual standard, which costs money, I suspect the following is authoratative enough.
MEM04-C. Beware of zero-length allocations - SEI CERT C Coding Standard - Confluence[^]
Keep in mind that without that reference I thought it might have been undefined. Which means it could throw a system exception too. So probably better the way it is.
modified 1-Mar-24 18:14pm.
|
|
|
|
|
I agree. I have seen this cert referenced before.
I wrap malloc with a check for <1 memory request argument and return NULL and an error message.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
To add to this, what universality (All) is really saying is that "nothing exists that violates this constraint", whereas existentiality (Any) is really saying "at least one thing exists that obeys this constraint."
With [].All(constraint), nothing exists to violate the constraint, so All() returns true.
With [].Any(constraint), nothing exists to obey the constraint, so Any() returns false.
|
|
|
|
|
I agree. I find the behavior of All() on an empty collection strange.
If I'm told "all the members of a list of integers are greater than zero" I would expect Any(p => p > 0) on that list to return true . But if the list is empty, Any(p => p > 0) returns false . That seems wrong.
/ravi
|
|
|
|
|
Good point. So, you're saying that if list.All(>0) then we should be able to assume that list.Any(>0) is also true? Makes sense.
However, it also makes sense that if list.All(>0) then list.Any(<=0) should be false, which it is, and we should be able to expect that if not list.Any(<=0) then list.All(>0) would be true, which it is (but wouldn't be if we changed it to work in your example).
The problem is that either way, when working with null sets, we end up with some relationship which isn't fully transitive.
For example, in SQL x = null and x <> null are both false (regardless of whether x is null or not, the only way to test for null is explicitly: x is null or x is not null ).
|
|
|
|
|
I feel what you feel but!
If you walk in a room and ask if anyone is there and there is no reply you have to note that down as false.
If you walk in a room and ask if all of them are aliens, but no one denies (cause nobody there) you note that down as true.
If there is no room you can walk into you can't ask questions in there, hence you trip and fall into the backrooms (nullException)
So MS is right, although it seems a bit off.
Rules for the FOSW ![ ^]
MessageBox.Show(!string.IsNullOrWhiteSpace(_signature)
? $"This is my signature:{Environment.NewLine}{_signature}": "404-Signature not found");
|
|
|
|
|
.NET's behavior is similar to the Principle of explosion
It is not a fallacy, it is a matter of "careful what you wish, you just might get it".
If you ask for multiple elements to satisfy a condition, you should be aware that you are, in fact, asking 2 questions:
1. I want at least 1 element
2. Each one of them satisfies the criterion.
Do not count on the tooth fairy to satisfy your hidden criterion #1, make it explicit instead.
|
|
|
|
|
I agree - code defensively. Check that the collection has something to interrogate, and if it has, proceed to do so. Otherwise define the behaviour you want if it is empty.
Don't be lazy!
|
|
|
|
|
Oh after this episode I no longer use All ; instead:
public static bool AnyAndAll<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
if (source == null)
return false;
bool any = false;
foreach (var item in source)
{
if (!predicate(item))
return false;
any = true;
}
return any;
}
|
|
|
|
|
Wikipedias page on Empty set[^] shows the properties of an empty set - which defined this behavior.
Personally I would have been very surprised if All() on an empty set would ever return false - as I one or another time managed to get "everything applies to all elements in the empty set" stuck in my head.
|
|
|
|
|
I figured I might be in the minority here, but suprised how overwhelmingly folks agree with Microsoft on [Empty].All() == true .
Mathematically I totally get it. None of the items is false. Fine.
But consider a real-world application and what I, as someone giving orders, would expect:
Darth Vader is commanding the Imperial fleet and approaching a suspected Rebel base but is uncharacteristically concerned about civilian casualties for once. "Are there any civilian inhabitants of this planet, commander?"
"No, Lord Vader," the commander replies.
"Good, so they're all rebels?"
"Yes, milord."
"Sterilize the planet," Vader commands.
The fleet spends the next four hours bombarding the planet, burning the entire surface and boiling the oceans, while Vader waits impatiently as he is eager to proceed to the next suspected target. Finally when the carnage is over, Vader asks, "Well done, Commander. How many Rebels did we kill?"
"Well, um, none, milord," the commander meekly replies.
"What do you mean?"
"The planet was uninhabited."
Vader initiates a force choke. "You said there were Rebels here!"
The commander struggles to spit out his last words.
"I said the inhabitants were all Rebels, not that there were any inhabitants."
|
|
|
|
|
This may be considered a "dumb" response, but why not check for null and if not null, get a count, on your collection before attempting an action that presumes items in the collection?
|
|
|
|
|
|
That was an interesting read, as was this:
Vacuous truth - Wikipedia
I don't pretend to be a mathematician, but if all conditions can be satisfied by all members of an empty set, then all members of the empty set would satisfy the condition that their parent set is non-empty.
If we took the other approach and said that no condition can be satisfied by all members of an empty set, then all members of the empty set would fail to satisfy the condition that their parent set is empty.
Both approaches lead to contradictions, which is why the answer seems like it should be undefined.
|
|
|
|