The right way to program in Lisp?

I am new to Common Lisp, and found that I use functions functions that return values. The following are two trivial examples:

(defun safe-avg (ab) (and (numberp a) (numberp b) (/ (+ ab) 2))) (defun safe-div (ab) (and (numberp a) (numberp b) (> b 0) (/ ab))) 

But I could write it like this (perhaps clearer):

 (defun safe-avg (ab) (if (and (numberp a) (numberp b)) (/ (+ ab) 2))) (defun safe-div (ab) (if (and (numberp a) (numberp b) (> b 0)) (/ ab))) 

I wanted to know which preferred method to do something like this and reason behind it before I start abusing this habit.

+4
source share
2 answers

Since you are not using the else branch, you can use when :

 (defun safe-div (ab) (when (and (numberp a) (numberp b) (> b 0)) (/ ab))) 

which matches with:

 (defun safe-div (ab) (if (and (numberp a) (numberp b) (> b 0)) (/ ab) nil)) 

which matches your version, but more explicit.

In any case, they are all functionally equivalent. I would rather think about how these features will be used. If you do it this way, you will have to do null checks every time you call these functions, which is tedious.

It is better to use conditions either through type declarations, through statements, or through explicit when & hellip; signal . You can then define handlers and restart these conditions for entire parts of your program. Further reading: Practical General Lisp, chap. 19 .

In this case, I would not cope with this at all:

 (defun safe-div (ab) (/ ab)) 

(or rather, just use / ).

If / receives the wrong arguments, it will signal an error that you can handle externally, where you know what that might mean.

+7
source

The first form is idiomatically acceptable. This is not a good example of effectively using the AND return value, as the second form is a little clearer without being longer. But you should not be afraid to use LISP for its intended purpose!

For example, going in the (inappropriate) direction ... someone might argue that the implicit expression "nil return" from if can be confusing, and the attempt and parallel structure of if/else are clearer:

 (defun safe-avg (ab) (cond ((and (numberp a) (numberp b)) (/ (+ ab) 2)) (t nil))) 

This is bad. And you do not want to follow this road. So, continue to use expressions and trim the amount of code with good grades and use comments to pick up slack, to remind others (and ourselves) of how this works if something is implicit.

+3
source

All Articles