I'm curious about the :keys! stuff and the comment that this is built on assert. Does that mean it would be disabled in production code (if you choose to disable assert)? Was there any consideration of throwing an Exception here rather than an Error? (more in π§΅ )
It will not be based on assert but a checking variant of get and IllegalArgumentException is already in the plan.
Note also that this is not just available in fn arg destructuring but all destructuring
Thanks, @richhickey! I was a bit concerned when I heard assert in the Dev Call π It's kind of a hot button for me, and I've spent time recently removing all the :pre, :post, and assert calls (and catch Throwable) from our code at work... I've never liked assert.
I look forward to the first 1.13 alpha that implements this so I can start using it at work!
pretty sure I didn't say anything about assert in the call. it's listed in an idea column on the sheet I showed, but that was just one of many ideas, lots of further work has happened
Ah, maybe "heard" = "seen" then. It just jumped out at me, either way.
I just rewatched that segment really carefully and you did not say "assert". I got hung up on what I saw on screen: "build on assert", "the binding of keys with an added assert", and the potential :assert syntax -- and I was like "OMG! Red Flag! Red Flag!" π€£ As you can tell, I suffer from "Assert PTSD" π
Yeah that was right under βIdeasβ :)
This was just the start, which is why I didn't talk about all that stuff
Really excited about this! I think it addresses an important pain point in a very easy-to-use way. @seancorfield Out of curiosity, what did you replace asserts with?
Explicit checks that throw IllegalArgumentException where it made sense, and restructuring logic to handle success/failure where that made sense.
This was really all intended to replace catch Throwable with catch Exception or something even more specific -- and catch Throwable was there specifically because we had used assert in the first place.
I'm a strong believer that if you think you need assert to catch programming errors at runtime, to prevent your code from operating on bad data, then those checks should be part of your production code and so assert is the wrong machinery. After all, if you call a function with the wrong number of arguments, you get an ArityException not an ArityError -- the Java docs draw a very clear distinction that Error exceptions should not be caught but Exception exceptions are an indication of something that it is reasonable to catch and handle.
I may be in a minority with this opinion, but this is one of those very few hills in programming that I am willing to at least get severely wounded on, if not actually die π
(FWIW, nearly all of our asserts were that certain hash maps contained certain required keys -- so when this new feature drops in a 1.13 alpha, I can go back through those changes and remove most of the explicit checks I added and use :keys! instead)
My two big issues with assert (and I've talked about this before) are:
β’ that you can indeed turn this off in production and so your program would blunder on with "bad data" and potentially fail a long way from the failure anyway (what :keys! is supposed to be helping to prevent),
β’ assert usually produces pretty horrible messages, especially when there's no way to add your own message (`:pre` and :post are examples of this, which is why a lot of folks avoid them).
In addition, assert throws an Error, which the JVM docs are pretty clear should be used for "uncatchable" program failures -- Exceptions are "expected" failures and can/should be caught and handled, Errors are supposed to be for "can't happen" failures and should not be caught.
I feel like key-checking in fn arg destructuring should be more along the lines of IllegalArgumentException...?
not ready to talk about it yet, unlikely to end up being based on assert
Good to know. Thanks!
(timestamp 10:50 for the curious, again 34:20)