<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body><div style="font-family: sans-serif;"><div class="markdown" style="white-space: normal;">
<p dir="auto">On 7 Sep 2022, at 19:19, Dan Smith wrote:</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">Summarizing my takeaways from talking over these use cases today:</p>
<p dir="auto">On Sep 7, 2022, at 12:56 AM, forax@univ-mlv.fr<<a href="mailto:forax@univ-mlv.fr" style="color: #777777;">mailto:forax@univ-mlv.fr</a>> wrote:</p>
<p dir="auto">Here is a list of such value types:
<br>
- unit types, value types like by example Nothing (which mean that a method
<br>
never returns) with no fields.
<br>
Because creating a ref on it creates something :)</p>
<p dir="auto">If you truly mean for such a class to have no instances, that's not something a
<br>
class with a value type can assert—the default instance always exists. I can
<br>
see how it would be nice, for example, to have a type like Void that is also
<br>
non-nullable, but value types are not the feature to accomplish that.</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">To pile on with Dan, value types are not at all like empty types (nothing, not-reached). Like all objects, they are records, products of fields, and so can be units (what Dan calls singletons), but not empties (nothings). Only types structured as sums can be empty.</p>
<p dir="auto">Background: A unit type is different from an empty type, just as the product identity element 1 (in various settings) differs from the sum identity element 0 (in various settings). A unit type has one instance and takes up no storage (O(1) storage globally for its metadata), but can be stored in many places. An empty type has zero instances, and takes up no storage because it cannot be stored anywhere, not even on stack.</p>
<p dir="auto">Void is a unit type, because you can return from a void method. NotReached is an empty type, because you cannot return from a method that declares its return as not reached.</p>
<p dir="auto">If you add a unit type to a union (sum type), you increase the information content of that union; a unit type is not an identity for sum-aggregation. By contrast, if you add an empty type to a union, you leave the union unchanged (since that union branch is never reached); an empty type is an identity for sum-aggregation in the same way that 0 is an identity for addition.</p>
<p dir="auto">Likewise, if you add a unit type to a product (tuple record), you leave the record unchanged in its information content, because a unit type is an identity for product-aggregation. But if you add an empty type to a record, you change it; the record can no longer be instantiated, so it collapses to an empty type (with a different label, maybe). This is one reason we associate 1 with units and 0 with “empties”: the product of an empty times any type is empty, just as 0*x = 0.</p>
<p dir="auto">Taking this all into account, a type <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Map<int,Nothing></code> is <em>not</em> a set of ints. It is a set that <em>you cannot take any ints out of</em>. It is an empty type, isomorphic to <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Nothing</code> itself (assuming <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Nothing</code> is empty not a unit).</p>
<p dir="auto">I think the closest Java gets to mapping the world of empty results is <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">throws</code> clauses, which talk about how a method’s (normal) return point can fail to be reached. (From another POV, both kinds of method returns, normal and exceptional, are coordinated terms in a sum-aggregation of the form <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Either<NormalType,ThrowType></code>.) But <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">throws</code> don’t get all the way there, since regardless of its <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">throws</code> clauses, a method can <em>always</em> return normally, so it’s return type is never actually empty.</p>
<p dir="auto">An empty type is what you get when you dereference <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">null</code>. Maybe the type of dereferencing <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">null</code> could be something like <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">NotReached<NullPointerException></code>? Maybe. But if we did such a thing, the generic type <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">NotReached</code> would have to be special-cased everywhere in the language. Probably you could never declare a field or variable of that type. (Except in dead code. But Java forbids you to write dead code.) Methods which return <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">NotReached</code> would be obligated to throw the indicated exception (or <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">RTE</code> or <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Error</code>) instead of returning.</p>
<p dir="auto">FWIW, I really like that value types can express labeled units, and embrace all the quirky corollaries, such as that an array of those guys is isomorphic to a non-negative <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">int</code>. I look forward to the day when <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Map.Entry<T,Void></code> specializes so that the second component takes up zero bits, and so sets can be built on maps with storage efficiency.</p>
<p dir="auto"><em>Note</em> that <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Void</code>! I really mean <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">java.lang.Void</code>, not a new value class. If I specialize to a type which is hardwired to have zero instances (and that means it is always <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">null</code>) I have a unit type that’s even better than a value-class with no fields, since the <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">null</code> is the only possible value, not <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">null</code> plus a default instance. Specialized generics should IMO specialize on <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Void</code>, when we get there!</p>
<p dir="auto">The conversation about a hypothetical specialized generic called <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Atomic</code> for Java is way premature, IMO. Is it mutable or immutable? Does it affect its container? …Who knows? I am sympathetic with the idea that wrapping a specialized generic around a random type can somehow create a new kind of container for that type; I envision such generics for <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Atomic</code>, <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Contended</code>, <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">WeakReference</code>, <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Lazy</code>, and many more, to replace various ad hoc mechanisms we have today. I want to try for it, but I don’t regard any of those as a necessary goal, just a “nice to have if we can get it”.</p>
<p dir="auto">(One example: We suffer from the lack, today, of arrays of weak references. But it’s not clear that value-types-plus-arrays can ever help with that. I’m OK if they don’t. We don’t need to replicate all of C++’s <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">atomic</code> template tricks, nor the tricks from any particular language.)</p>
<p dir="auto">Regarding unwanted nulls from ref-default types: Meh; the JVM has a quarter century invested in dealing with unwanted nulls, to the point where folks just don’t think about them very much as a performance problem. As a correctness problem, they are a pain, but again we have many ways to cope. I think forgetting to put <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">.val</code> on your fields or array creations is just fine; you can ship code that has too many nulls with a clear conscience, as long as you have a way to recognize when they are a measurable problem. At that point, fix your code by adding <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">.val</code> in a few places. But you can wait to measure a need in most cases. People writing high-performance code with complex numbers or vectors will readily learn where they must “salute the val”; it is no worse than the current question of when to use <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">float</code> or <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Float</code>. The rest of us can mostly ignore the issue.</p>
<p dir="auto">To conclude, I don’t feel much “loss” here, nor do I think we are “lost”. But some of the confusion between units and empties did leave me “at a loss”. Hence this message.</p>
<p dir="auto">— John</p>
</div></div></body>
</html>