valhalla-dev Digest, Vol 6, Issue 3
Thomas W
twhitmore.nz at gmail.com
Sun Dec 21 06:11:01 UTC 2014
Hi everybody, Hi Brian,
Appreciate the draft. I'm going to largely agree with Simon Ochsenreither
on the merits of simplicity -- I'm dubious about layering/peeling -- and
add a few suggestions of my own.
1) List<int>.remove() disambiguation
-----------------------------------------------------
We can easily disambiguate the remove() methods by annotation; adding a
longer "specific" name.
Thus:
@Disambiguate("removeAt")
public T remove (int index);
@Disambiguate("removeItem")
public boolean remove (T item); // traditionally, item is
Object; could specify this as 'compatible<T>'
Compiler & specializer would thus be able to generate bridge methods, from
the "ambiguous" signature to the unambiguous method. Syntax could work
either way around -- renaming the methods now & annotating the old
"ambigous" name would be better engineering, but less source-compatible.
Type specification of 'item' could be a solved problem, or a specific type
syntax could be introduced to handle this. "compatible" could possibly be a
reasonable keyword to express the intent; Object was originally considered
"compatible with" T, but for a value-type T only T would be compatible.
Not sure that we'd want to turn "compatible" into a keyword generally,
though, as it could be quite widely used as a variable name.
2) List.remove() cleaner syntax
---------------------------------------------
- everybody hates java.util.Enumeration and it's gratuitously over-long
syntax,
- so let's use List.removeAt(int index), List.removeItem(T item) etc.
3) "Empty" values
--------------------------
- as somebody pointed out, we need a syntax that references 'empty' values
by type; null or zero.
- I propose 'T.empty' for this purpose; eg, int.empty references 0,
Object.empty references null.
4) Map<int>.get() and "sentinel values"
--------------------------------------------------------
- null is a moderately good "sentinel value" for objects, but zero is not
so good for numbers;
- similar to the 'T.empty' syntax proposed above, I propose a 'T.sentinel'
syntax for "no element".
eg, int.sentinel references -1, Object.sentinel references null.
5) Statics; synchronizing to access these?
----------------------------------------------------------------
- good point about SomeType<int> and SomeType<T extends Object> sharing the
same statics;
- but since they do not have class in common, what syntax/ or common object
can they synchronize on?
- possible proposal: T.classLock, which should be the base Class (but
perhaps just typed as Object).
6) Equals, esp. null-safe!
--------------------------------------
- comparing objects (especially in a null-safe way) is a fundamental
operation of Collections etc.
- if we prohibit null-checks, we cannot write such code!
- if we allow null-checks & specialize them for value-types to NOP, we
allow other possibly wrong uses of 'null' to remain.
As a side rant:
- null-safety has required stupid & ugly code in Java for so long. Every
library has had to write this, whereas the base library should have done it
once, and done it right, back a version 1.1. Nor is "null as a monad"
(Optional in Java 8) the good basic solution we need.
- and where are Optional.equals( nullableX, nullableY) and
Optional.hashCode( nullableX) methods???
- I called my null-handling class "Optional" back at Java 5. Now some
dropkick comes along and pollutes my namespace with these
poorly-thought-out & incomplete FP ideas. We're not Scala, let's not
pretend to be.
Coming back to the problem at hand: we're not going to use Monads for
null-safe equality, we don't have rocks in our heads, but we do want a
type-portable null-safe equals().
- do we want to consider T.equals(x, y) ??
- any better ideas??
7) Peeling and Layers
--------------------------------
- these ideas seem major & complex, but solve only relatively moderate
corner cases.
- introducing a major new structural level into the Java language, breaking
long-standing single Java types into separate parts is an enormous change;
seemingly suitable for "mixins" or some really major language enhancement.
- yet the parts/layers are not named/ or addressible, and the use of this
structure will really be quite minor.
Summary: introducing a banner-level language feature to solve two
problematic methods, with no other possible use, does not really seem the
right design choice.
8) Conclusions
----------------------
Introduction of a simple "field-style" syntax on types extends the existing
usage of ".class", to allow important new type-related expressions to be
expressed in an easy & obvious way. It also gives minimal potential for
conflict with existing syntax.
I am much happier to avoid cast-based formulations, such as casting 'null'
to int, to get zeros/nulls in a type-specific way. Introducing a
well-defined syntax for "empty" and "sentinel" values could resolve most
no-item & empty-value problems -- which is where null & null problems
typically crop up -- in an effective manner.
I absolutely think we need a type-specific method/ or syntax for null-safe
equals; this is a basic to writing most collections code. However, I'm
less clear on what "the right" syntax should be here. Any takers?
Look forward to your thoughts,
Regards
Thomas Whitmore
More information about the valhalla-dev
mailing list