Skip to content

Instantly share code, notes, and snippets.

@gilesbowkett
Created June 30, 2013 04:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gilesbowkett/5893860 to your computer and use it in GitHub Desktop.
Save gilesbowkett/5893860 to your computer and use it in GitHub Desktop.
comparing every element in a list to every other element
; common lisp version, totally works
; (defun build (list1 list2)
; (if (null list1)
; ()
; (append (mapcar #'(lambda (bubble)
; (list (first list1) bubble))
; list2)
; (build (rest list1) list2))))
; if you tell lisp: (build '(1 2) '(1 2))
; lisp will happily reply: ((1 1) (1 2) (2 1) (2 2))
; literal clojure translation
(defn build [list-1 list-2]
(if (nil? list-1)
()
(concat (map (fn [bubble]
(list (first list-1) bubble))
list-2)
(build (rest list-1) list-2))))
; if you tell clojure: (build '(1 2) '(1 2))
; lisp will stack overflow error all up in your business
; if you're curious there's a Ruby version here:
; https://github.com/gilesbowkett/tweenr/blob/master/bit101_style.rb#L2
@gilesbowkett
Copy link
Author

recur also fails because it's not in the tail position

@ericnormand
Copy link

The problem is that the empty list returns false to nil? in Clojure. () and nil are distinct. So it's going into an infinite loop.

@ericnormand
Copy link

Should do (nil? (seq list-1)) instead.

Or do (when (seq list-1) (concat ....))

@candera
Copy link

candera commented Jun 30, 2013

This looks like you're trying to take the Cartesian cross-product of two sequences. I know you got help on the failure already, but in case you're interested, a more Clojurey approach would look like this:

(defn build [seq1 seq2]
  (for [elem1 seq1 elem2 seq2] [elem1 elem2]))

And that's short enough that I probably wouldn't even bother making a function out of it.

If you want something that's the Cartesian product of n sequences, that's slightly more involved:

(defn cross-prod [& colls]
  (->> colls
       (reduce #(for [x %1 y %2] [x y]))
       (map flatten)))

@lispm
Copy link

lispm commented Jan 8, 2015

The Common Lisp code reimplements MAPCAN. Use it:

(defun cp (l1 l2)
  (mapcan (lambda (e2)
            (mapcar (lambda (e1) (list e1 e2)) l1))
          l2))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment