1

I am attempting to write a recursive lambda function (accepting two arguments) that finds the intersection between two (potentially) unsorted sets. Here is the code, which I believe most will find straight forward:

(fn intersection [a b]
(fn inner [x y out]
  (if (empty? x) out
  (if (nil? (some ((set (first x)) y )))
    (inner (rest x) y out))))
    (inner (rest x) y (cons (first x) out))
    (inner a b '[])
)

I hope to use this lambda function intersection in place of the underscore _ that follows:

(= (__ #{0 1 2 3} #{2 3 4 5}) #{2 3})

However, this code fails to compile, insisting that Java is Unable to resolve symbol: inner in this context...

Any suggestions?

source: http://www.4clojure.com/problem/81

David Shaked
  • 3,171
  • 3
  • 20
  • 31
  • Sorry if the error description is a bit terse, but it feels as if we've been moving in circles looking to solve this problem for a good while :( – David Shaked Mar 22 '16 at 19:40
  • intersection takes two parameters and returns another set, correct ? Then why are you returning a function instead ? – nha Mar 22 '16 at 19:48

1 Answers1

3

You could try :

#(set (filter %1 %2))

Since sets are functions (see another useful example there). The syntax with %1 and %2 is the same as writing :

(fn [s1 s2] (set (filter s1 s2)))

Or even more succinctly :

(comp set filter)

Regarding the inner error, you simply misplaced the parens (but I don't really see the logic otherwise) :

(fn intersection [a b]
  (fn inner [x y out]
    (if (empty? x) out
        (if (nil? (some ((set (first x)) y )))
          (inner (rest x) y out)))
    (inner (rest x) y (cons (first x) out))
    (inner a b '[])))

If you insist on building the set manually (which I did not so long ago), you could end up with something like that :

(fn [s1 s2]
  (reduce #(if (contains? s2 %2) (conj %1 %2) %1) #{} s1))

But really the first solution is the most elegant.

Community
  • 1
  • 1
nha
  • 17,623
  • 13
  • 87
  • 133