I was reading the post A Modern Architecture for FP that included a code snippet that the author wanted to decompose further. I don't know Haskell but I recognize enough to know that I've written many functions like this one, combining related logging, metrics, and business logic in one function:

saveFile :: Path -> Bytes -> IO Unit
saveFile p f = do
  log ("Saving file" ++ show (name p) ++ " to " ++ show (parentDir p))
  r <- httpPost ("cloudfiles.fooservice.com/" ++ (show p)) f
  if (httpOK r) then log ("Successfully saved file " ++ show p)
  else let msg = "Failed to save file " ++ show p
  in log msg *> throwException (error msg)

I understand that Haskell, with only pure functions, requires special techniques to have side effects. (I am still studying up on monads and category theory to see why they matter.) While Clojure doesn't require pure functions, I still want to know how to decompose this method further.

What is the most Clojure-idiomatic way to split a function like the above? I don't understand enough about monads or Haskell to know how to apply that article to Clojure; I can see two other general possibilities:

  • Write multiple functions for each composite function, each new function representing a small unit of logging, metrics publication, business logic, etc. I have one call tree that composes those all into the actual component behavior I want, and another (?!) call tree composing only the pure-function version of the component (if desired). This seems unreasonable for any component of scale.
  • Write composite functions as shown above and dynamically bind no-op components when you want to get a pure function.

The second seems the most reasonable when writing enterprise software but that doesn't actually decompose anything.

  • 2
    What are you actually trying to accomplish with further decomposition. Do you want better simplicity, better purity, what? Nov 5, 2016 at 18:34
  • Simplicity, better composability. And, less important if it increases complexity, is the aesthetic of being able to compose small declarative statements like, "Give me this bit of functionality wrapped with this metrics and these logging statements." I do see the reasons that this decomposition might be unnecessary but I am really using this as an opportunity to learn if Clojure/FP has a new higher level that I haven't yet discovered. Nov 7, 2016 at 15:21


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.