Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documenting if-let and if-some #16

Open
DjebbZ opened this issue May 23, 2019 · 7 comments
Open

Documenting if-let and if-some #16

DjebbZ opened this issue May 23, 2019 · 7 comments

Comments

@DjebbZ
Copy link

DjebbZ commented May 23, 2019

Hello,

Could you document if-let and if-some? I don't understand how they works, and would love some an example in the README like other forms. Thanks in advance!

@Engelberg
Copy link
Owner

if-let and if-some are drop-in replacements for the ones built into Clojure:
Examples here:
https://clojuredocs.org/clojure.core/if-let
https://clojuredocs.org/clojure.core/if-some

The only difference is that the ones in better-cond support multiple bindings, in which case all the values must be truthy (for if-let) or non-nil (for if-some) to be considered true.

So now you can write things like:
(if-let [a 10, b 20] [a b] [b a])
which would return [10 20].

There is a paragraph about this in the README, but you are right that I don't give concrete examples. What examples do you think would be most clarifying?

@DjebbZ
Copy link
Author

DjebbZ commented May 23, 2019 via email

@Engelberg
Copy link
Owner

if-let and if-some are not clauses to be used within cond. They are standalone macros that can be used in place of the built-in if-let and if-some if you need multiple bindings (the built-ins only support one binding).

They are mainly used as implementation details to implement better-cond's :when-let and :when-some clauses inside of the cond. But since they are arguably better versions of clojure's built-in if-let and if-some, I thought I might as well expose them as public.

I personally never use them, as I find the cond is robust enough on its own.

Instead of (if-let [a 10, b 20] [a b] [b a], I would likely write

(cond
  :let [a 10, b 20]
  (and a b) [a b]
  :else [b a])

I suppose the if-let is more concise, but the cond makes each step clear, and then can stack together with other tests and bindings easily, without indenting.

@DjebbZ
Copy link
Author

DjebbZ commented May 23, 2019

Thanks for the explanations, very clear. I think this somehow deserve to be in the README :)

@isaksky
Copy link

isaksky commented Jun 14, 2019

if-let and if-some are not clauses to be used within cond. They are standalone macros that can be used in place of the built-in if-let and if-some if you need multiple bindings (the built-ins only support one binding).

Is there a reason to not support them within cond? Seems like it would be a good way to avoid the short circuiting behavior of when-let. E.g.,:

(def a 2)

(cond
  (odd? a)
  [:a a]

  :if-let [b (and false a)]
  [:b b]

  :if-let [c (or false a)]
  [:c c])
;=> [:c 2]

@Engelberg
Copy link
Owner

:if-let would be a three-part clause rather than two parts like everything else, complicating the macro and making it hard to understand what's going on in the event of user error. That's the main reason.

The original code from which better-cond was derived had a special syntax to pack the information into two parts (basically no keyword was used, a binding vector indicated the use of :if-let), but I never used it because I found it lacked the clarity of just doing (following your example):

:let [b (and false a)]
b [:b b]

:let [c (or false a)]
c [:c c]

In practice, even this rarely came up because usually what you want is to specify the value to bail out with when the name you just bound is false-y (i.e., you want a custom when-let that bails out with a value other than nil). So usually you want something that's the opposite of if-let, like this:

:let [b (and false a)]
(not b) [:b b]

and :if-let can't express this case. So you're better off just using better cond's abilities to express your condition for bailing out clearly, and the value you want to bail out with, like above.

@isaksky
Copy link

isaksky commented Jun 14, 2019

@Engelberg I understand - appreciate the the explanation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants