10 ms·
That pluggable type system looks amazing. One thing that's weird to me is how java included a new Optional type (seems similar to Haskell's Maybe), but the com
by tieTYT 12y ago
That pluggable type system looks amazing. One thing that's weird to me is how java included a new Optional type (seems similar to Haskell's Maybe), but the compiler (afaik) doesn't prevent you from setting an Optional field to null. Something about that doesn't feel right. (Side Note: Optional isn't serializeable. Also... what's the best practice for using Optional when I'm using JPA? Can it be used in my Entities?)
I believe Jetbrains/Intellij-IDEA has created annotations for @NotNull/@Nullable, but afaik these just create warnings in the IDE. Maybe you can configure IDEA to mark these as compiler errors, but I don't know if my peers using netbeans/sublime/whatever would be able to notice when they write code that IDEA will refuse to compile.
I want compilation to FAIL in these cases.
- steveklabnik 12y agoIt's certainly a bit strange, but it's how Scala works as well. I wonder if it's for backwards compatibility reasons, given that everything is nullable already. Have to give it more thought though.
- the_af 12y agoIndeed, Option in Scala has the same problem. I understand null is needed for backwards compatibility, but it makes Option the poor man's Maybe...
- virtualwhys 12y ago> Indeed, Option in Scala has the same problem eh? scala> val safe = Option(null) safe: Option[Null] = None
- adamwbarr 12y agoscala> val x = Some(null) x: Some[Null] = Some(null)
- virtualwhys 12y agoThat's pretty contrived, when would you _ever_ wrap a thing that could be null in a Some? Even so, to continue with your example: scala> x foreach println null x.get res2: Null = null Hey, what do you know, no NPE. Try harder ;-)
- adamwbarr 12y agoOk fair point re it being contrived! Although (having just re-read it), the original post's complaint was actually that: > the compiler (afaik) doesn't prevent you from setting an Optional field to null ie scala> val option: Option[Any] = null option: Option[Any] = null
- the_af 12y agoExactly, that was my complaint. It makes elegant pattern matching against Option types (the whole point of using them, in fact) less than useful. Now, in Scala-land, you have to check that they aren't null, which sucks.
- frowaway001 12y agoThis complaint shows pretty well that some people have never actually used Scala.
- the_af 12y agoCan you elaborate? The whole point of Option types is that I can map (for example) over them without explicitly checking what their value is, and it will work without a runtime error. Same with pattern matching. With the introduction of null, this is no longer possible. I've just shown an example of getting an NPE while mapping over an Option[String]. Now we're back in Java-land, where I must explicitly check for nulls, read the source code of every method or trust some comment that tells me that it will never return null. (Ok, not exactly like Java-land: a Scala programmer who returns a null for a function with type Option is very inexperienced or is doing something naughty. But why does the language even allow it?) Aside from telling me I'm wrong, can you explain why?
- the_af 12y agoI don't understand your objection: // The type of 'unsafe' is Option[String] var unsafe = Option("some string") unsafe = null unsafe map println gives Exception in thread "main" scala.MatchError: null effectively a NullPointerException. This would be impossible for a true Option (aka Maybe) type. The problem is introduced because Scala, for backwards compatibility reasons, still allows the assignment of null; this lowers the usefulness of pattern matching against Option types. -- edit: you could object to my use of var (and you should). Ok, let's re-write it to be a val: def unsafeFunction(x: Option[String]): Option[String] = { x orElse null } ... val unsafe = unsafeFunction(None) unsafe map println ...and I still get the NPE. Note that in this case you can easily see how I introduced the problem, but the point is that the signature for unsafeFunction should guarantee null is not a possible return value.
- virtualwhys 12y ago// The type of 'unsafe' is Option[String] var unsafe = Option("some string") unsafe = null unsafe map println Is complete contrived nonsense, var? Seriously, quit trolling, in Scala (immutable) val is king. Next: def unsafeFunction(x: Option[String]): Option[String] = { x orElse null } Oh yeah, that's brilliant, let's just try our hardest to come up with scenarios that never occur in the "real" world (unless we try really hard to create nullthing out of nonething).
- the_af 12y agoI'm not trolling. I genuinely want to like Scala, which is why I'm disappointed by some of its design choices. Yes, in Scala val should be king (unfortunately, it's not -- if you've taken the two Coursera courses by Odersky you'll see some use of var in the exercises, refuting your claim). But it's true val is more common, and the use of var was accidental to my point anyway (mutation wasn't the issue), hence my clarification and second example. Yes, it's pretty obvious where I introduced the mistake, I said as much. In the real world, the mistake might be harder to spot, which is why the type system shouldn't allow it. If I understand your position correctly, it seems to boil down to "programmers will code correctly, therefore this static check (that Option must not be null) isn't needed". Which is pretty much what dynamic typing proponents have been saying all along. A pretty untenable position if you want to stay on the side of Scala... I'd much prefer if Option were more like Haskell's Mabye, but then again, I side with static typing. I understand why, given Scala's requirements, this wasn't possible. It's just disappointing.
- peeters 12y agoThere are a number of implementations of JSR 305 (https://jcp.org/en/jsr/detail?id=305 https://jcp.org/en/jsr/detail?id=305). Findbugs is one that provides the annotations. You can include the annotations JAR file on your compile path and then use findbugs in your build to enforce them. IntelliJ will still recognize them and flag the warnings/errors.
- kazagistar 12y agoThe main issue with non-nullable types in OOP, in my mind, seems to be defaults. Quite simply, when you don't initialize an primitive, you get a 0, and when you don't initialize an object, you get a null. Not all fields must be initialized by the time the constructor ends, so some kind of valid default exists. Enforcing non-nullability would involve somehow enforcing that the variable is always valid before use some other way, like how "final" is enforced in the constructor, but it should be possible. Unless you make it default, though, it won't be as "elegant" as the haskell Maybe, and doing so would net you a very very different language.
- pjmlp 12y agoOutside the JVM world, Eiffel does it. In the JVM world, Kotlin and Ceylon do it as well.
- strictfp 12y agoYou can at least add runtime assertions automatically with jwtbrains annotation processor (maven plugin). I don't know about compiler errors,