Fork me on GitHub
Chinmay Dalal17:12:28

can bit-xor be used as logical xor?

Chinmay Dalal17:12:08

is there something elegant then?


@U01CLETCE1L It's easy enough to write your own:

user=> (defn xor [p q] (and (or p q) (not (and p q))))
user=> (for [a [true false] b [true false]] (list a b (xor a b)))
((true true false) (true false true) (false true true) (false false false))
See,_elimination,_and_introduction for the logic.

Chinmay Dalal19:12:16

(defn xor [& args]
  (odd? (count (filter true? args))))


That's not quite the same semantics as the version I provided. Mine works with truthy/falsey which is more like the built-in and and or. Yours will only work with true for truthy.


If you update yours to (filter identity args) it'll have truthy/falsey semantics. (mine was strictly a 2-arity version so I can see why that's not generally useful!)

Chinmay Dalal09:12:27

oh yeah i expect only true or false as input


i would use bit-xor as a guide to write your own multi-arity one

(defn bit-xor
  "Bitwise exclusive or"
  {:inline (nary-inline 'xor)
   :inline-arities >1?
   :added "1.0"}
  ([x y] (. clojure.lang.Numbers xor x y))
  ([x y & more]
    (reduce1 bit-xor (bit-xor x y) more)))


Could some one tell me why the calculate-row function returns nil and not a number? (Advent of Code spoiler)


it looks like a misplaced paren. moving the cond statement to the else branch of the if statement fixes "returning nil" (I didn't check logical correctness otherwise):

(defn calculate-row
  [data rows]
  (loop [d data
         r rows]
    (if (= (rest d) ())
        (= (first d) \F) (recur (rest d) (bottom r))
        (= (first d) \B) (recur (rest d) (top r))))))


I recommend the following idiom when looping using loop (which was originally recommend by someone in this slack):

;; Iterating over a collection using loop

;; 1. First call (seq xs) on the given argument and then check for nil 
;; 2. Then call next/first and use these.

(loop [xs (seq [1 2 3 4 5])
       result []]
  (if xs
    (let [x (first xs)]
      (recur (next xs) (conj result (* x x))))

;; the same loop can be written using destructing,
;; but the compiler will generate two consecutive
;; seq calls and is slightly less efficient.

(loop [[x & r :as xs] (seq [])
       result []]
  (if xs
    (recur r (conj result (* x x)))


Yes, it indeed returns the value now. thanks!


I will keep that in mind


the first if is ignored. it is executed but nothing uses its return value so it might as well never happen. you then have a cond which will return a value if the predicate is hit, but if none of those predicates match it returns nil. also, you have a loop expression but there are no recur expressions so it will never loop


oh sorry. you do have recurs. but if neither condition of the cond is satisfied it returns nil