Fork me on GitHub
#other-languages
<
2016-10-21
>
borkdude12:10:24

@cfleming I read this discussion: https://groups.google.com/forum/#!topic/clojure/Dxk-rCVL5Ss and of course wondered if you’d looked at Frege and/or Scala. Both require writing wrappers of course.

cfleming12:10:53

@borkdude Frege is out because of laziness.

cfleming12:10:19

Scala is out because of a) complexity and b) it doesn’t handle nulls from interop well.

borkdude12:10:31

Scala is also lazy, but in a different way 😉

cfleming12:10:47

That would be c) then 🙂

borkdude12:10:05

The compiler is JTL

cfleming12:10:14

Basically, Kotlin works better for me than Scala

borkdude12:10:21

Just Too Late

borkdude12:10:40

I’m kidding. So, why not Kotlin then?

cfleming12:10:27

That’s pretty much what I’m doing. The problem is that the more Kotlin I write, the less Clojure I write, and I need to be dogfooding.

borkdude12:10:28

Btw, most of my null pointers come from misspelling Clojure keywords. But yeah, when you’re doing a lot of Java interop, I can see your problem. But wouldn’t you have those problems in Java as well?

cfleming12:10:54

This is a discussion I’ve had a couple of times - I don’t believe the NPEs are because I’m using interop. I think it’s more relevant that I’m programming against a large codebase that I don’t understand.

cfleming12:10:35

And I find that Clojure makes it harder to track down NPEs than Java - in Java the NPEs tend to be closer to the source of the problem.

borkdude12:10:48

I guess writing against code you don’t understand requires handling ‘Nothing’ cases in other languages as well after the fact?

borkdude12:10:53

Yes, definitely

cfleming12:10:53

nil punning in Clojure works against me here.

borkdude12:10:22

I guess libraries like seesaw would be in the same place

cfleming12:10:34

Well, in Kotlin that’s implicit. Types that come back from Java are known as “platform types”, and are written as String! (String is non-null and String? is nullable). You can’t write platform types yourself, but when looking at the type of something you’ll see them.

borkdude12:10:55

that’s convenient

cfleming12:10:23

You can assign a platform type to either a nullable or non-null Kotlin variable. If you assign it to a non-null one, Kotlin will implicitly add a nullability assertion at that point.

cfleming12:10:56

So you’ll get an NPE but right at the source (platform types cannot escape the function you made the interop call in).

cfleming12:10:25

The compiler enforces that you cannot dereference non-null variables, and also uses flow typing to make things easier.

cfleming12:10:26

String? x = <something>
if (x == null)
  // x is null here
else
  // x is String (not String?) here.

borkdude12:10:19

Writing some interop macros with assertions does not do the trick?

cfleming12:10:48

Scala doesn’t have this and it’s really convenient. You’d get something similar with pattern matching over Option, but there’s more ceremony involved.

cfleming12:10:26

Another nice thing about Kotlin’s null types is that they add no runtime overhead - Option requires more instances to be created every time you make an optional call.

cfleming12:10:46

Perhaps, but I make a lot of interop calls.

borkdude12:10:14

I guess rewriting some of the core interop macros would help, but not as fundamental

borkdude12:10:41

Anyway, I just wanted to hear you on Frege/Scala. Thanks!

cfleming12:10:10

To answer your earlier question - yes, Seesaw probably suffers from this as would any Clojure code written against a large Java codebase. But this is one of the key use cases for Clojure - not everyone is writing webapps.

cfleming12:10:24

Interop is supposed to be idiomatic.

borkdude12:10:24

I guess this is an area that could really be improved. Thanks and see you around at EuroClojure probably.

cfleming12:10:38

Yes, definitely - looking forward to it!

arrdem21:10:10

You can't just rewrite the interop macros tho, because you have to figure out the type of the method you're calling (if you can even do that, reflection) then emit each argument, check if it's nil, generate an appropriate empty T for any nil value and then invoke the method.

arrdem21:10:12

It'd be nuts.