Question

My question is about structuring lisp code with side effects. The particular example I have in mind comes from Clojure, but I think it can apply to any lisp.

In this case, I am interacting with an existing library that requires some functions to be called in a particular order. The final function call creates the value I need for the rest of the procedure.

The code looks like this:

(defn foo [] 
    (let [_ procedure-with-side-effect
          __ another-procedure-with-side-effect
          value procedure-that-creates-the-value]
        (do-something value))) 

This works and everything is great, except I think the let block looks hideous. Is there a better way to do this?

Était-ce utile?

La solution 2

In Lisp every function body is a ordered set of forms. The value(s) of the last form will be returned. If the procedures don't use intermediate result values as arguments, a LET is not necessary. If the procedure-that-creates-the-value does not need to be documented by naming a variable, the LET binding for its value is also not necessary.

So in Lisp the code is just this:

(defun foo ()
  (procedure-with-side-effect)
  (another-procedure-with-side-effect)
  (do-something (procedure-that-creates-the-value)))

Autres conseils

If you don't need the intermediate values of the function calls, you can just put a bunch of function calls in the body of the defn:

(defn foo [] 
  (procedure-with-side-effect)
  (another-procedure-with-side-effect)
  (do-something (procedure-that-creates-the-value)))

While this is the best for this code, there are other options. You can also put any number of function calls in the body of a let:

(let [val 3]
     (fun-call-1)
     (fun-call-2)
     (fun-call-3 val))

And if you don't want to bind any values, you can use do:

(do (fun-call-1)
    (fun-call-2)
    (fun-call-3))

I'm not super experienced, but I'd do it this way:

(defn foo [] 
  (procedure-with-side-effect)
  (another-procedure-with-side-effect)
  (let [value (procedure-that-creates-the-value)]
    (do-something value)))

or

(defn foo [] 
  (procedure-with-side-effect)
  (another-procedure-with-side-effect)
  (-> (procedure-that-creates-the-value)
      do-something))

or

(defn foo [] 
  (procedure-with-side-effect)
  (another-procedure-with-side-effect)
  (do-something (procedure-that-creates-the-value)))

Edit: defn expressions are wrapped with an implicit do.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top