It depends what you're using it for. One use of ControlFlow is for early exits in try_for_each, and there it can be reasonable to ignore the result the same way that you don't have to look at something indicating whether a loop used break. But I agree that in the "I'm doing a bunch of recursing" case it would be better as must_use. It may yet get it; I don't know.
Yes.
I have a wrapper that takes a function and struct as arguments. The wrapper requires the function will return a Result. The types in the Result are generic with traits dependent on features. So then this wrapper can handle the running of different functions and loop / process the values in the Result<T, V> The Ok or Err. if needed. So if the a function wants to return valuable stuff in the result it can, and the wrapper can process the valuable stuff. *compare to strings if the T Or V is Display or Debug trait for example. If I write a simple function I am calling with the wrapper that just needs the logic of the wrapper (for example looping and user interaction.) and does not need to communicate an Ok or Err, I have those functions return OK(()) and the return signature is -> Result<(),()>
I tried using Result<!,!> thinking "no type" but that doesn't work. Using the plain Result<(),()> makes sense to me to mean "Just care if it is Ok, or Err", but not what kind of Ok or Err.
Well, ! can never be observed at the value level. It is impossible to instantiate, so nobody will pass it to your functions, either. A value of type Result<!, !> can't be observed, either, because neither the Ok nor the Err variant can be instantiated (since those both would contain a !).
There is no such thing as "no type" in Rust. Every value must have a type at all times. What you are actually thinking about is "no information". And that's exactly what zero-sized or "unit" types do: they have exactly one possible value, so they convey zero bits of information.
In contrast, empty/never/void types have exactly zero possible values, so they convey negative infinite bits of information (and thus would have negative infinite size in theory, but of course that can't be realized in a computer, and size_of is unsigned in Rust for practical reasons, so size_of::<!>() == 0, inconsistently with theory).
The number of bits is the (base-2) logarithm of the number of choices. (Every bit is two possibilities, so N independent bits can form 2^N different bit strings.)
Because, conceptually, ([u8; 100], !) should be size -∞, not size 99. Just subtracting off one byte isn't enough.
(Note that the "conceptually" is particularly important here. In rust that's still 100 bytes because of partial initialization logic.)
This is, in fact, the max-plus semiring, since (ignoring padding and discriminants and such) the size of an enum is the max of those of its fields and the size of a struct is the sum of those of its fields.
Size -1 would be 2⁻¹ = ½ a possible value, so no.
Size ½ would be 2½ ≈ 1.4 possible values, so also no.
Size +∞, though, totally makes sense: struct Foo(u8, Foo); is conceptually infinite-sized, since that's the "solution" to x ≥ sizeof(u8) ∧ x = x + sizeof(u8).
EDIT: Well, actually, it depends on the unit. In a theoretical discussion I'd expect to measure in bits, as the unit of information, at which point fractional sizes don't make sense.
But for Rust size is in bytes, then I guess size ½ would be u4, which you could certainly imagine existing. And if we had something like arithmetic coding or bitpacking as a language feature, then you could make a bit-packed type of size 1 that holds two u4s, at which point you could certainly think of that u4 as having "size ½", though certainly size_of would still say 1, just like size_of says the bool has size 1 even though conceptually you could think of it as having "size ⅛" in something like a bitset container.
It is possible to have a variable which contains half a bit of information, though it will require at least a bit of storage space. @H2CO3's statement that the number of bits is the log2 of the number of choices is a simplification that assumes each choice is equally likely. In particular, if the variable can take on two possibilities with 9∶1 odds, it conveys about half a bit of information.
Thank you for trying to clarify and making it more confusing. ?grin?
I think of the () unit type as a thing that is nothing. A "un" "it" type if you will.
I reason "I can never use never "!" for a type that is nothing, but using an "un it" makes logical sense.
For me, the empty type ! is called empty because it contains no information at all.
On the other hand, the unit type () contains no non-trivial information, but it contains information about its existance. If you have an instance, you know that you have it - which is different from the empty type. In that case, having an instance is a fatal logic bug.
So no information vs no non-trivial information.
But the unit type encodes information! (but trivial one)
My favourite one of those is actually 1 + 2 + 4 + 8 + … = -1, since in a sense that's exactly how we deal with signed binary numbers in computers: -1 == 0b111…111.
Et cetera; every rational is representable in this p-adic "repeats or terminates" form, similar to how they have a decimal representation -- except the repeating is on the left and there are always finite digits right of the decimal point. Additionally, there is no need for a negative sign. (The representation varies for each base p, as they also do for the fractional/"decimal" form.)
For -1 speciflcally, it's a sequence of Basek - Basek-1, i.e. 9 + 90 + 900 ... = repeating ...999. = -1 in 10-adic, similar to how .999... repeating = 1 in decimal. In the context of the rational examples above, 142857 * 7 = 999999; hence 142857 repeating from the decimal point is 1/7 in decimal (to the right) and -1/7 in 10-adic (to the left).
Note that the 1 + 2 + 4 ... example is for 2-adic and the corresponding sum in 10-adic does not converge. The 2-adic form using binary digits is repeating ...111. = -1. And the two's complement of n in binary is ...111. - n + 1 = -1 - n + 1 = -n.
(For some things, like extending from the rationals to a field with non-repeating infinite sequences, the base must be prime -- hence the p in p-adic. But a prime is not necessary to represent the rationals.)
Good point.
So let's continue this idea.
Idea: The size of a type is not a natural number, but a 2-adic integer.
Then the type
struct T(T, u8)
has size -1 (right?), but cannot be instanciated.
What is the size of the empty type?
Does the sum and product rule hold for size_of? (Where sum is to be taken with a grain of salt, of course)
In particular, is the size of (T,T) equal to -2?
Can we construct a type with size +/- 1/2?
As fun as it is to talk about type theory. std::mem::size_of doesn't actually measure the number of possible choices, if it does, size_of::<Vec<()>>() would have been infinite.