Create a gist now

Instantly share code, notes, and snippets.

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
Owner

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

@ericnormand

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

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

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

@candera
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
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