Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functional alternative to "let"

Tags:

clojure

I find myself writing a lot of clojure in this manner:

(defn my-fun [input]
  (let [result1 (some-complicated-procedure input) 
        result2 (some-other-procedure result1)]
    (do-something-with-results result1 result2)))

This let statement seems very... imperative. Which I don't like. In principal, I could be writing the same function like this:

(defn my-fun [input]
    (do-something-with-results (some-complicated-procedure input) 
                               (some-other-procedure (some-complicated-procedure input)))))

The problem with this is that it involves recomputation of some-complicated-procedure, which may be arbitrarily expensive. Also you can imagine that some-complicated-procedure is actually a series of nested function calls, and then I either have to write a whole new function, or risk that changes in the first invocation don't get applied to the second:

E.g. this works, but I have to have an extra shallow, top-level function that makes it hard to do a mental stack trace:

(defn some-complicated-procedure [input] (lots (of (nested (operations input))))) 
(defn my-fun [input]
    (do-something-with-results (some-complicated-procedure input) 
                               (some-other-procedure (some-complicated-procedure input)))))

E.g. this is dangerous because refactoring is hard:

(defn my-fun [input]
    (do-something-with-results (lots (of (nested (operations (mistake input))))) ; oops made a change here that wasn't applied to the other nested calls
                               (some-other-procedure (lots (of (nested (operations input))))))))

Given these tradeoffs, I feel like I don't have any alternatives to writing long, imperative let statements, but when I do, I cant shake the feeling that I'm not writing idiomatic clojure. Is there a way I can address the computation and code cleanliness problems raised above and write idiomatic clojure? Are imperitive-ish let statements idiomatic?

like image 371
Logister Avatar asked Jan 22 '26 06:01

Logister


1 Answers

The kind of let statements you describe might remind you of imperative code, but there is nothing imperative about them. Haskell has similar statements for binding names to values within bodies, too.

like image 69
andy_fingerhut Avatar answered Jan 27 '26 01:01

andy_fingerhut