dash.el icon indicating copy to clipboard operation
dash.el copied to clipboard

`-if-let` treats list with one nil element as nil

Open phst opened this issue 10 years ago • 4 comments

Consider:

(-if-let ((a b) '(1 2)) (list a b) 'else)
(1 2)

(-if-let ((a b) '(1 nil)) (list a b) 'else)
else

I think the behavior in the second case is a bug; the VAL is not nil, yet the else branch is taken.

phst avatar Oct 03 '15 15:10 phst

It's not a but, this is expected behaviour. Maybe it's just not documented properly.

I can see that sometimes it might be useful (probably) to only check if the entire expression is non-nil. You can use the &as binding for that, and maybe we can then make it check only on the entire expression. But I'm not sure if that won't be overly complex and confusing too.

-if-let as it is requires all bindings to be non-nil.

Fuco1 avatar Oct 03 '15 15:10 Fuco1

All bindings non-nil is how I would interpret if-let as well.

magnars avatar Oct 03 '15 15:10 magnars

The docstring of -if-let is:

(-if-let VAR-VAL THEN &rest ELSE)

If VAL evaluates to non-nil, bind it to VAR and do THEN,
otherwise do ELSE. VAR-VAL should be a (VAR VAL) pair.

Note: binding is done according to `-let'.

Here VAL evaluates to (1 nil), which is non-nil, so the then branch should be taken if the docstring is correct.

The current behavior is unpleasant in a few ways:

  • The behavior of -if-let depends on whether destructuring is happening or not.
  • -if-let can no longer be mentally expanded into if and -let.

phst avatar Oct 03 '15 15:10 phst

The first point is easily fixed by saying "all bindings are non-nil" which makes it consistent whether or not destructuring happens.

About the second point -if-let should rather be expanded to let and if, because testing on if and then assigning would evaluate the expression twice.

Fuco1 avatar Oct 03 '15 15:10 Fuco1