Fork me on GitHub
#beginners
<
2020-12-05
>
Chinmay Dalal17:12:28

can bit-xor be used as logical xor?

Chinmay Dalal17:12:08

is there something elegant then?

seancorfield18:12:14

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

``````user=> (defn xor [p q] (and (or p q) (not (and p q))))
#'user/xor
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))
user=>``````
See https://en.wikipedia.org/wiki/Exclusive_or#Equivalences,_elimination,_and_introduction for the logic.

Chinmay Dalal19:12:16

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

seancorfield20:12:00

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.

seancorfield20:12:20

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?
([x y] (. clojure.lang.Numbers xor x y))
([x y & more]
(reduce1 bit-xor (bit-xor x y) more)))``````

shidima21:12:54

Could some one tell me why the `calculate-row` function returns `nil` and not a number? https://pastebin.com/TJzf7pXb (Advent of Code spoiler)

phronmophobic21:12:11

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) ())
r
(cond
(= (first d) \F) (recur (rest d) (bottom r))
(= (first d) \B) (recur (rest d) (top r))))))``````

phronmophobic21:12:06

I recommend the following idiom when looping using `loop` (which was originally recommend by someone in this slack): https://clojuredocs.org/clojure.core/loop#example-5a1de497e4b0a08026c48cc4

``````;; 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))))
result))

;; 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)))
result))``````

shidima21:12:44

Yes, it indeed returns the value now. thanks!

shidima21:12:48

I will keep that in mind

dpsutton21:12:16

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

dpsutton21:12:01

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