Fork me on GitHub
#clojure-uk
<
2016-06-14
>
martintrojer06:06:40

@agile_geek: I've lost count of all the NPE's in my Clojure code

agile_geek07:06:03

@martintrojer: interesting. In my, admittedly small pet, projects I have only encountered them with Java interop

agile_geek07:06:02

and even in my Java projects I didn't have to defend for them that often once I adopted TDD.

agile_geek07:06:28

Unless it's a system boundaries NPE's are usually a sign of poor internal design

agile_geek07:06:58

After all if it's your code you can ensure sensible default values.

dominicm07:06:42

I guess if a function returning a function, returns nil, you could get an NPE in Clojure. I did this once with boot.

((comp (returns-fn) (returns-nil)) :foo) ;; => NPE

agile_geek07:06:38

@dominicm: I'm not saying it can't happen but with good testing you should find it. Same in Java.

agile_geek07:06:51

but it does happen less in Clojure

dominicm07:06:32

Yeah, I agree.

agile_geek07:06:33

I currently work on a Java codebase with a vendor whose developers are indoctrinated with 'defensive' programming and little testing...about 60% of the code base is if (!null...

agile_geek07:06:49

last project I wrote in a small start up with a couple of dev's using a lot of TDD and unit tests only had null checks at boundaries and has been running for 2 years in prod without an NPE (and only 2 bugs)

agile_geek08:06:21

Maybe we should use the 'Maybe' monad more in Clojure?

mccraigmccraig08:06:35

i don't think there is much value for the maybe monad in clojure since you don't get the benefit of the type-checker telling you when you are failing to handle a branch

thomas08:06:41

nice discussion!

glenjamin09:06:38

mccraigmccraig: if you had to explicitly unwrap, you’d at least get a runtime error when you use it

mccraigmccraig10:06:22

@glenjamin: hmm. that's true - it can make a random error predictable, which seems valuable

minimal10:06:36

until you get Just nil

mccraigmccraig10:06:22

Just ThreadDeathError

minimal10:06:37

Just DieAlready

malcolmsparks10:06:07

95% of my NPEs are in java interop. In pure Clojure, nil punning takes care of that chunk, leaving a residual 5% where clojure.core fns throw NPE. There really aren't many of those.

malcolmsparks10:06:06

I often embrace nil in my code to have meaning/semantics. For example, returning nil from a yada response fn yields a 404. I think about nil more when writing Clojure code because I don't have a tool to alert me about missed cases. It would be nice, but I can happily cope without one. And ultimately, thinking about the code you write has all sorts of other positive advantages. Java programmers have so many tools to write and check code, they have to think about their code less. That shows in the systems that they deploy.

bronsa10:06:10

> Does that include the generated API docs? That'd be handy @glenjamin: no, those are generated by autodoc from the docstrings in code and changes to them need to go through jira

bronsa10:06:36

re: maybe monad in clojure -- making extensive use of if-let/`some->` I don't see the need for it TBH

martintrojer10:06:35

@malcolmsparks: I've come to the conclusion that assigning meaning to nil is a terrible idea

martintrojer10:06:52

Much better to have an explicit type for whatever than meaning might be

martintrojer10:06:35

IMHO, your milage might vary

minimal11:06:23

it is unfortunate that nil carries no information about “what it isn’t"

minimal11:06:55

Which Maybe solves in static langs as mentioned earlier

malcolmsparks11:06:46

Until we code everything in mathematical proofs, types are not a complete codification of meaning. For that we need code. So I don't see the world as types versus code, rather as code plus quality aids.

malcolmsparks11:06:38

@martintrojer: I think that is broadly your position too, the disagreement is in the detail

malcolmsparks11:06:57

Nice article. Half way through it. You'll laugh when I say that I have time to read articles because jvm restarts!

malcolmsparks11:06:37

Finished it. Very balanced article.

malcolmsparks11:06:13

Nice way of explaining via for-all, there-exists

malcolmsparks11:06:42

Ah, my JVM is back...

martintrojer11:06:54

one killer feature with contracts is that you can combine checking and input validation in one declaration (even coercion, kind of)

malcolmsparks11:06:30

Or more generally?

martintrojer11:06:12

In Haskell (and friends) you'd need to define your types and then write a parser-thing that validates/coerces the input and maps it on said types

minimal11:06:50

Well you can get haskell to write the parser for you with DeriveGeneric

dominicm11:06:17

I wonder if racket can do full input validation. I've only got spec to do it through hacks.

minimal11:06:18

If the library implemented it, which the json and yaml ones do

dominicm11:06:43

And even that probably breaks some other things.

thomas11:06:39

great article @martintrojer

thomas11:06:51

explains things nicely.

glenjamin12:06:20

martintrojer: I’d say that while “Types have AT WORST no performance impact” is true at runtime, the compilation cost can be a factor

glenjamin12:06:48

i’ll also be interested to see if more static analysis tools spring up using the spec information

bronsa13:06:11

I think @arohner might already be trying to do that IUC

glenjamin13:06:25

i think I saw a POC from Ambrose

korny16:06:16

For me the key performance indicator is “developer effectiveness” 🙂 Types can affect that in good and bad ways…