Allow multiple bindings for if-let, when-let, if-some, and when-some

Description

Description of issue:

Suppose I want to create multiple bindings with let and then execute a body. I can do that easily like so:

But, if I want to do the same type of thing with if-let, I can only do so by nesting them because if-let only accepts one binding at a time.

This is very inelegant because:
1) It is not as simple to read as it would be if all of the bindings were next to each other on the same indentation
2) The else clause it duplicated multiple times.
3) The else clause is evaluated in a different context depending which binding failed. What if a was already bound to something? If the if-let shadows a, and b does not get bound, the else clause would be executed with a different value bound to a than if a was not shadowed in the first if-let. (see code below for example)

I want to be able to write this instead:

I also want to be able to do a similar thing with when-let, if-some, and when-some.

Proposed:

I re-wrote those macros to be able to handle multiple bindings. If supplied with just one binding, their behavior remains identical. If supplied with multiple bindings, they should only execute the body if every binding passed. In the case of some bindings passing and some failing in if-let or if-some, none of the bindings should leak into the else clause.

Patches:

  • clojure-core v2 8-3-2017.patch - Clojure patch with macro updates. For if-let and if-some, I had to add a bit of extra logic in order to prevent them from leaking bindings to the else clause in the case of some bindings passing and some failing. It also includes a few extra tests around each macro.

  • core.specs.alpha.patch - core.specs.alpha patch with equivalent updates to core specs

Environment

None

Activity

Show:
Justin Spedding
August 4, 2017, 3:44 AM

An updated patch that simplifies the generated code when 0 bindings are given to if-let and if-some

Ghadi Shayban
August 3, 2017, 9:30 PM

It is worth looking at what the JVM is intending on doing with test-and-destructure intrinsics. Brian Goetz covers this in a recent talk on pattern matching [1]

[1] https://www.youtube.com/watch?v=n3_8YcYKScw

Justin Spedding
July 29, 2017, 10:52 PM

I posted my solutions to that ticket as code in a comment. Then, you posted about the correct format of tickets and linked to the ticket creation guidelines. I figured that meant that you wanted a ticket to be made that followed the conventions.

Also, this ticket is about modifying the existing macros. CLJ-2007 was about creating 2 new macros: if-let* and when-let*.

Alex Miller
July 29, 2017, 10:40 PM

What's the relationship of this to CLJ-2007?

Assignee

Unassigned

Reporter

Justin Spedding

Labels

None

Approval

Triaged

Patch

Code and Test

Affects versions

Priority

Major