You can't enforce one of the two with no way to go for either. That's just not feasible. Think about it; it would be impossible to write even the simplest utility methods.
Just like in generics, where you can specify: Don't care what it is ('T extends Object', it should be possible to say: Don't care which type of nullable we have). Unlike generics, where the amount of things you can do with a random 'T' is fairly limited, for nullity there's loads you can do. The number of methods that never write null but do null checks when reading / don't actually read are virtually limitless. And yet all of those would have to pick a side and allow null or not, eventhough IT DOESNT MATTER to them. When the type system gets in the way of you not repeating yourself, the type system completely failed. On Oct 17, 9:09 am, "Viktor Klang" <[EMAIL PROTECTED]> wrote: > On Thu, Oct 16, 2008 at 9:21 PM, Reinier Zwitserloot <[EMAIL PROTECTED]>wrote: > > > > > On Oct 15, 3:04 pm, "Viktor Klang" <[EMAIL PROTECTED]> wrote: > > > This expands to: > > > > List?<X?> list = someMethodThatReturnsAStringList(); > > > list.add("foo"); > > > No; it doesn't. The above means that 'list.add(null);' should be > > legal. This is a meaningful property of a type, but it does come with > > caveats. Specifically, if the 'someMethodThatReturnsAStringList' > > method returns a list that does not allow nulls, this should be a > > compile-time error. > > Of course it should. > > > There's really no way that I can see to get around > > the notion that you need 3 different properties in generics > > parameters: > > > A. Definitely allows null, (benefit: Can write nulls in) > > B. Definitely does not allow null (benefit: No need to null-check when > > reading) > > > C. Don't know / Don't care if its allowed (benefit: Accept anything) > > I don't think that's an option, that kind of thinking was what got us into > this mess in the first place. > A type is a type is a type. > > String? is another type than String! > > Not caring about types should place you in the dynamic languages section. > Either you design the code to handle nulls, or you don't. It's binary. > > > > > Because the whole point, in a sense, is to eliminate null checks as > > much as possible, it seems fundamentally bad to ADD situations where > > you need to perform null checks (which is what you'd do if you tried > > to e.g. combine B and C, for example). that's what I meant. > > > Now, 3 types might be acceptable, but syntax is definitely an issue. > > ESPECIALLY if non-null becomes the default; there are two different > > more nully options, so you need 'nully' and 'even more nully'; using > > '?' and '??' seems kinda wrong, and the ? is used a lot more in java > > than the !, which makes it hard to use ? or even ??. I'd say it's > > pretty bad to let parser architecture dictate syntax, but its > > undeniable that suffix-! for non-null, suffix-? for most definitely > > allows null, and -nothing- to indicate 'don't know/care' is easiest on > > the parser and thus easiest for tools out in the wild to adapt this > > change, and easiest for the tutorials. It's not easiest on the eyes > > once everyone's used to it, which is a pretty big problem, but for now > > it's the front-runner for me. > > > > Whis is exactly (I don't care wether list is null or String, and if it > > > contains Xs or null) what you said. > > > > > in such a way that the method can return either a list of strings-or- > > > > nulls, or a list of definitely-not-null-strings. > > > > > Eventhough, given the only thing it does is add a non-null string, it > > > > doesn't matter. > > > > > I'm pretty much positive not being able to do that makes this feature > > > > very stupid. > > > > Reinier, that's an opinion, and not an argument. > > > > I'd like to continue this discussion, so it'd be nice if more people join > > in > > > with ideas, questions, etc. > > > > > On Oct 14, 4:49 pm, "Viktor Klang" <[EMAIL PROTECTED]> wrote: > > > > > I don't like the possibility to not specify nullness. > > > > > > Let's say that ? is implicit > > > > > > List<String> = List?<String?> = (a list with Strings or null) or null > > > > > > List!<String!> = a list with strings > > > > > > List<String!> = (a list with Strings) or null > > > > > > List!<? extends String> = a list with (subtypes of string or null) > > > > > List!<?! extends String> = a list with subtypes of string > > > > > List!<? super String> = a list with (supertypes of String or null) > > > > > List!<?! super String> = a list with supertypes of String > > > > > > List?<? extends String> a = ... > > > > > List!<? extends String> b = ... > > > > > > a = b is legal (since they have the same generics signature) > > > > > b = a is not legal since a can be null > > > > > > I haven't really thought this through, I'm just exploring the > > > > possibilities. > > > > > > /Viktor > > > > > > On Tue, Oct 14, 2008 at 2:54 PM, Reinier Zwitserloot < > > [EMAIL PROTECTED] > > > > >wrote: > > > > > > > Introducing ! as definitely never null, and ? as might be null, in > > an > > > > > > Either/Maybe kind of construct, doesn't really help, unless you are > > > > > > willing to throw out the ability to make a list/map/anything else > > with > > > > > > generics in it which will take arbitrary type input; it doesn't > > matter > > > > > > if the type you're passing in is of the 'never null' or of the > > 'maybe > > > > > > null' or of the 'I don't know' variety. Throwing that out seems > > like a > > > > > > death sentence for the entire feature; the point is ease of use, > > and > > > > > > getting rid of pointless null checks, not conflagrating the issue > > by > > > > > > adding a bunch of neccessary null checks just to satisfy the > > compiler. > > > > > > > In other words, you need to be able to say: > > > > > > > List< AAAAA > list; > > > > > > > where AAAA is something that says: "Strings, but the nullable or > > non- > > > > > > nullable nature of them is irrelevant; I'll only be reading from > > them, > > > > > > and I'll do explicit null checks when I do, so I just don't care, > > and/ > > > > > > or when I write to it, I'll definitely write non-null." > > > > > > > You also need: I do care; only one particular variant of > > null-allowed > > > > > > is okay here. > > > > > > > This is actually one less scenario than generics (which splits up > > the > > > > > > first scenario into: I'll only be writing into it, so I'll give an > > > > > > type range going from Object to the thing I'll be putting in, say, > > > > > > Integer, and you can then feed it a List of Object, Number, or > > > > > > Integer, it'll all be good, and into a second scenario: I'll only > > be > > > > > > reading from it, so I'll give a type range going from, say, Number, > > up > > > > > > to whatever, and I'll only be reading Numbers out, so if you give > > me a > > > > > > Number, or Integer, or Double, it'll be all good. In our case we > > can > > > > > > combine these two situations into stating that: When reading, you > > get > > > > > > possibly-null out, and when writing, you must never write nulls in. > > > > > > > I think your suggestion to use ? to indicate 'definitely allowed to > > be > > > > > > null' and use the lack of a marker as 'we don't know if null is > > > > > > allowed here or not' might make the concept a lot simpler to grok > > > > > > (though it would force you to add a marker to every type you state > > in > > > > > > your entire codebase to do it 'right', which I envision would get > > > > > > annoying fast). You'd then have: > > > > > > > ! = Definiitely not null. > > > > > > ? = Definitely allowed to be null. > > > > > > (nothing) = We don't know, so to be safe, when reading, you get ?, > > but > > > > > > when writing, you must write in ! - that can't go wrong. > > > > > > > So, you'd get: > > > > > > > List!<String> listA; // must only add non-nulls, but when reading > > > > > > elements out, must check for null. > > > > > > List!<String?> listB; //when reading, you must still check for > > null, > > > > > > but you're allowed to write null into it as well. > > > > > > List!<String!> listC; //must only add non-nulls, and when reading, > > you > > > > > > get String!s out, so no need for null checks. > > > > > > > listA = listB; //okay > > > > > > listA = listC; //also okay. Hey! That's nice! > > > > > > listB = listA; //not okay > > > > > > listC = listA; //also not okay > > > > > > listB = listC; //duh - not okay > > > > > > > Of course, if your generics type has an unnamed type with a bound, > > you > > > > > > still get the funky ?! and ?? syntax, and you also still get the > > extra > > > > > > leniency: > > > > > > > List!<? extends Number> listA; //can't add, but when reading, must > > > > > > check for null. > > > > > > List!<?? extends Number> listB; //can't add, but when reading, must > > > > > > check for null. Same as listA. > > > > > > List!<?! extends Number> listC; //can't add but when reading, no > > need > > > > > > for null-check. > > > > > > > listA = listB; //okay > > > > > > listB = listA; //okay - contrast to above, where it wasn't. > > > > > > listA = listC; //okay > > > > > > listB = listC; //okay - contrast to above, where it wasn't. > > > > > > listC = either; //not okay. > > > > > > > And the most complicated case, super: > > > > > > > List!<? super Integer> listA; //write Integer!, read Object? > > > > > > List!<?? super Integer> listB; //write Integer!/Integer/Integer?, > > read > > > > > > Object? > > > > > > List!<?! super Integer> listC; //write Integer!, read Object! > > > > > > > note that listA and listC aren't quite the same, due to the fact > > that > > > > > > you can read from ? super X bounds, whereas you can't write to ? > > > > > > extends Y bounds. > > > > > > > assignment compatibility: same as in the String! vs. String? vs. > > > > > > String case. > > > > > > > Grokking this might be easier, and being compatible with existing > > java > > > > > > code is way easier (no marker = dunno), but there is the issue of ! > > > > > > and ? showing up *EVERYWHERE*: > > > > > > > public Integer? combineHashes(List?<?!> list) { > > > > > > if ( list == null ) return null; > > > > > > Integer! hash = 0; > > > > > > for ( Object! x : list ) hash ^= x; > > > > > > return hash; > > > > > > } > > > > > > > Does that look okay to you? If it does, this might be worth the > > > > > > trouble. > > > > > > > On Oct 14, 9:52 am, "Viktor Klang" <[EMAIL PROTECTED]> wrote: > > > > > > > Actually, I think non-nullness could be simplified if you change > > the > > > > way > > > > > > you > > > > > > > view it. > > > > > > > > if ! indicates the type <a string value> > > > > > > > and ? indicates the type <Either<String!,null>> > > > > > > > > Clearly, > > > > > > > > 1) casting a ! to a ? is not possible, a type > > ... > > read more » --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "The Java Posse" group. To post to this group, send email to javaposse@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/javaposse?hl=en -~----------~----~----~----~------~----~------~--~---