HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Powerset in Clojure

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
clojurepowersetstackoverflow

Problem

I think I have correctly implemented Powerset in Clojure.

(use '(clojure set))

(defn powerset [input result]
  (if (nil? (first input))
    (concat result #{})
    (set (reduce concat
           (for [x input]
             (let [set-of-x #{x}
                   input-no-x (set (remove set-of-x input))
                   next-result (union result (set (list input set-of-x input-no-x)))]
               (powerset input-no-x next-result)))))))


Of course I'm interested in how a library function could make the above a one-liner, but I'm also interested in how the above code could be made more idiomatic.

  • (if (nil? (first input)) feels wrong.



  • Using the let block to replicate imperative calculations. Acceptable?



  • Could I use ->> to make the following line more readable? (union result (set (list input set-of-x input-no-x)))



  • I'm not using recur as I got the "recur must be in the tail position" compiler error.



EDIT Removed (loop) from originally-posted version. - I had erroneously copy-pasted code after I had already commenced attempting to introduce loop/recur (tail recursion). How use loop/recur in this function?

Solution

A couple of random comments on your code:

-
it doesn't parse correctly, I guess the closed paren right after loop bindings is misplaced. I couldn't run it even after fixing that.

-
why do you need a second input parameter? I would expect the signature to only have the input set as parameter

-
(if (nil (first input)) then else) is more idiomatically written (note the inversion of the then-else branches) (if (seq input) else then)

-
input-no-x can be obtained in a simpler way: (let [input-no-x (disj input x)])

Context

StackExchange Code Review Q#12979, answer score: 3

Revisions (0)

No revisions yet.