Fork me on GitHub
#clojure
<
2020-07-04
>
Crispin04:07:34

Whats the most elegant way to do a logical exclusive or?

andy.fingerhut04:07:18

Write a one-line function that does it?

Crispin04:07:27

with ands and ors?

Crispin04:07:41

truning them to integers and summing?

Crispin04:07:49

converting to bits and bit-xor?

craftybones04:07:53

Wouldn’t that depend on how you want to define your truthiness? What about nil etc?

andy.fingerhut04:07:51

OK, maybe not one-line function 🙂. Hacking one way of doing it now....

andy.fingerhut04:07:18

Takes me a bit longer to write one that works for 1 or more args

Crispin04:07:16

I have at least three args. I have done one with (if arg1 1 0) for each arg and summing and seeing if its = 1. But wondering if there is a more elegant way.

Crispin04:07:57

mine does also not short circuit. A macro could be written that short circuits.

andy.fingerhut04:07:34

There is no way to short circuit xor I don't think, unlike and and or. Every arg value can affect the result, regardless of the value of earlier args

Crispin04:07:26

Well if you get a second truth, you do not need to eval further

Crispin04:07:09

(xor true true true true) you know is false by the second true.

andy.fingerhut04:07:35

(xor true true false true) is ?

Crispin04:07:45

thats false

andy.fingerhut04:07:54

Not in any definition of xor I have ever seen..

Crispin04:07:52

:thinking_face: I need to read up on xor

hiredman04:07:15

I don't know, but wouldn't be surprised if EE and CS held slightly different interpretations of multi input xor

andy.fingerhut04:07:18

I have done some hardware design, and have a CS degree, and have yet to see any differences in ways that either field has defined xor.

andy.fingerhut04:07:09

Here is one possible Clojure implementation as a function. It could be written as a macro, but I do not see any benefits to doing so:

(defn xor
  "Returns the xor of its arguments.  Arguments are considered logical
  false for the same Clojure values that `if` treats them as logical
  false, i.e. nil or false.  All other values are considered logical
  true.  Returns `false` if the xor is logical false.  Returns the
  value of the last logical true argument if the xor is logical true."
  [& xs]
  (loop [acc false, xs xs]
    (if-let [xs (seq xs)]
      (let [x (first xs)
            acc (if x
                  (if acc false x)
                  acc)]
        (recur acc (next xs)))
      acc)))

phronmophobic04:07:02

is the seq call necessary in the if-let?

andy.fingerhut04:07:15

That might depend on whether it is important for it to work on 0 args.

andy.fingerhut04:07:20

but maybe not even then.

phronmophobic04:07:57

the seq seems prudent, but I was wondering just out of curiosity. 0 args seems to work on whatever version of clojure I'm currently running, but wasn't sure if that would be relying on something that might change or might be different from clj to cljs

andy.fingerhut04:07:15

I made some attempt at making it efficient for arbitrary length sequences, perhaps at the expense of a faster implementation for the 2-arg case.

Crispin04:07:24

@hiredman very interesting. I have always assumed interpretation 1. Never considered interpretation 2. Thanks for the link.

andy.fingerhut04:07:24

OK, I have read that article you linked, and interpretation 2 there (return true if an odd number of inputs are true) is the only definition I have come across before. Interpretation 1 there (return true if exactly one input is true) I have never come across yet.

Crispin04:07:50

I always thought of interpretation 1, because of the meaning of the word "exclusive". Exclusive or means to me one, and only one. That true input is exclusively true. Nothing else is true. Only that one. Thus exclusive.

andy.fingerhut04:07:00

The Wikipedia article for xor does not seem to mention interpretation 1, but I haven't read it in depth.

Crispin04:07:02

wolfram alpha implements interpretation 2.

Crispin04:07:01

(true, true, false, true) doesnt seems very exclusively true in the english definition of exclusive. But it seems the mathematicians disagree with me :man-shrugging:

andy.fingerhut04:07:42

I haven't taken a poll or anything, but if you implement something you call xor that uses interpretation 1, I would recommend documenting it very explicitly that is what it is doing, and not "odd number of arguments are true" interpretation, or you will trip many people up

andy.fingerhut04:07:22

The Wikipedia article mentions several nuances with interpreting English sentences. The xor interpretation 2 is what I have seen commonly in Boolean algebra, CS classes, and hardware logic design.

Crispin04:07:31

call the function odd-arguments-true? :D

Crispin04:07:56

yeah seems interpretation 2 is the preferred one. TIL.

andy.fingerhut04:07:32

Personally, I would call interpretation 1 exactly-one-true?

Crispin04:07:29

there's an english word that means "exactly one" we could use... now what is it? 😉

Crispin04:07:59

1b, 2a and 4

andy.fingerhut05:07:40

I'm not arguing with the dictionary. I'm simply pointing out a very common usage of the meaning of xor for 3 or more inputs in many years of experience in CS and hardware design.

andy.fingerhut05:07:08

Call the function whatever you think is clear, but if you call it xor, then document what interpretation of it that you mean, or some of your users will be confused.

Crispin04:07:55

yep. thats the function I want!

hiredman04:07:23

The Wikipedia page for the xor logic gate (there are a few pages related to xor) says: An XOR gate implements an exclusive or; that is, a true output results if one, and only one, of the inputs to the gate is true. I

hiredman04:07:35

Which I think would be interpretation 1

phronmophobic04:07:13

interpretation 1 is only in the case of 2 inputs . under the "More than two inputs" section: > Literal interpretation of the name "exclusive or", or observation of the IEC rectangular symbol, raises the question of correct behaviour with additional inputs. If a logic gate were to accept three or more inputs and produce a true output if exactly one of those inputs were true, then it would in effect be a https://en.m.wikipedia.org/wiki/One-hot detector (and indeed this is the case for only two inputs). However, it is rarely implemented this way in practice. [emphasis mine]. further: > It is most common to regard subsequent inputs as being applied through a cascade of binary exclusive-or operations: the first two signals are fed into an XOR gate, then the output of that gate is fed into a second XOR gate together with the third signal, and so on for any remaining signals. The result is a circuit that outputs a 1 when the number of 1s at its inputs is odd, and a 0 when the number of incoming 1s is even.

andy.fingerhut04:07:14

Given that the exactly-one-true? interpretation might be more common than I have seen in my experience, documenting explicitly the one that a function returns seems best, unlike what I have done in my example code earlier.

andy.fingerhut04:07:19

If a function called xor behaved like the 'exactly one input is true', and didn't document it, I would be in for a debugging session to figure that out somewhere down the line.

chepprey04:07:32

Could perhaps call it xtrue (exclusively-true) in keeping with the xor naming style. Then again, everybody knows what xor is, while nobody knows what xtrue is. So maybe Andy's longer name wins.

Crispin04:07:03

the multiple definitions seems like a good reason to not ever implement logical xor

Crispin04:07:19

I notice clojure doesn't have it. Python doesn't have it.

Crispin04:07:31

I bet this discussion has been seen many times before...

andy.fingerhut04:07:04

Clojure has bit-xor which uses the 'odd number of 1s' interpretation

Crispin04:07:41

with three inputs?

andy.fingerhut04:07:07

You've got a REPL, yes? 🙂

Crispin04:07:16

yes it does I see

andy.fingerhut05:07:02

The odd number of 1s interpretation means that the N-input version is a cascade of the 2-input version. The 'exactly 1 is true' interpretation cannot be implemented in that way.

andy.fingerhut05:07:31

At least, I am pretty sure it cannot be ....

Crispin05:07:41

yeah. I get it. xor(a,b,c) = xor(xor(a,b),c)

Crispin05:07:06

just surprising to me. Suprised its taken me twenty years to discover this. Better late than never I suppose

chepprey05:07:46

Ya I'm not sure there really are multiple definitions. If the above observation about interpretation 1 being limited to only 2 inputs is true, then interpretation 1 seems like just an algorithm that incidentally matches the mathematical definition of xor, when limited to 2 inputs.

andy.fingerhut05:07:58

And it is difficult to compare surprise between two people, but it is possible that I am more surprised it has taken me 35 years not to have come across 'exactly one input is true' interpretation

andy.fingerhut05:07:15

For 3 or more inputs, those are 2 different functions.

andy.fingerhut05:07:27

For 2 inputs, they are the same.

Crispin05:07:47

Maybe its my lack of comsci background.

Crispin05:07:40

I think I will pronounce it "ex-or" from now on not "exclusive-or"

andy.fingerhut05:07:14

Probably everyone who has had some kind of logic or philosophy class has come across the English ambiguity of 'or' sometimes meaning inclusive, sometimes meaning exclusive (for 2 args).

emccue06:07:13

My logic professor used to say that he has been telling his kids they can have A or B and is waiting for the day they claim both

emccue06:07:41

but i am fuzzy on the details on that story - probably was a joke

Timur Latypoff13:07:10

XOR is “sum modulo 2”, isn’t it?

andy.fingerhut15:07:38

It is for many people. According to a few sources linked in the discussion above, some people use the words "exclusive or" to mean "exactly one of the following set of alternatives is true, no matter how many alternatives are there"

👍 3
Frosku14:07:12

Anyone here familiar with any graphics processing libraries?

Frosku14:07:43

I have an image comprised entirely of white and alpha pixels, I want to select all the white and change them to another color by hex value.

Frosku14:07:02

Wondering which libraries would make this a simple task.

Frosku14:07:26

(I've drawn a thing, on multiple layers, I want to put those layers back together programmatically with random color palettes)

Frosku14:07:12

I've managed to programmatically put them back together in white using clojure2d, but I'm struggling to find a function to make a modification only to non-alpha pixels.

Alex Miller (Clojure team)17:07:01

you can do all that with the built in java2d but it's cumbersome

onetom22:07:34

i remember some clojure function or tool or some clojure-related context could use the @ character to denote files within jar files. something like (slurp "[email protected]") or (slurp "@x.jar/x.txt"), or have i just dreamt that? has anyone seen something like this? was it something in just intellij / cursive?

Alex Miller (Clojure team)22:07:50

there is a url syntax to reference things inside jar files, but you need the right url resolver thing installed for it, maybe uses "!" ?

👍 3
noisesmith22:07:14

(ins)user=> (io/resource "clojure/core.clj")
#object[java.net.URL 0x63798ca7 "jar:file:/home/justin/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar!/clojure/core.clj"]
(ins)user=> (count (slurp *1))
263653
this might offer a clue

👍 3
noisesmith22:07:24

yes, it uses "!"

noisesmith22:07:13

slurp "jar:file:/home/justin/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar!/clojure/core.clj" does the same thing

noisesmith22:07:35

shouldn't be too hard a string to construct, format would definitely help

noisesmith22:07:03

also I kind of wish vim fireplace would use the above technique for finding source for a namespace, instead of relying on a clojure program that runs when you start up first load a file in a project

quadron23:07:58

i remember reading something about contract-oriented programming, now I feel like I need this idea, does anybody have any pointers? 👀

quadron23:07:18

I can't find it

noisesmith23:07:36

seems at least semi-related to :pre / :post in functions http://blog.fogus.me/2009/12/21/clojures-pre-and-post/

noisesmith23:07:10

though those subjectively seem much less popular these days

lilactown23:07:08

we have banned :pre / :post at work

lilactown23:07:27

something to do with it throws a type of error that's hard to work with or something

p-himik05:07:17

Another issue is that there's no support for messages. With regular assert you can at least reuse the values again to construct something helpful.

noisesmith23:07:24

it throws AssertionError which is not a subtype of Exception

noisesmith23:07:53

and people 95% of the time write (catch Exception ...) in their try blocks and ignore all its subtypes and siblings

noisesmith23:07:26

the real fix IMHO is to turn assertions off at runtime (they are best used as a dev time tool), the fact that "catch Exception" doesn't catch AssertionError is a feature - AssertionError means "the programmer made a mistake if this condition is ever hit"

noisesmith23:07:07

as opposed to Exception which encompasses random things you couldn't predict that can come up at runtime and want to recover from gracefully

seancorfield23:07:38

If you're going to use assertions to catch "can't happen" programming bugs, then you should keep them on at runtime/production to avoid data corruption or other "weird" behavior. I could never understand why folks wanted assertions to just "go away" in production... that seems far more dangerous.

👍 9
seancorfield23:07:25

And that style of thinking at least encourages you to write proper conditional checks in your (production) code if you really think you want to handle a failure in a specific way -- and then you're dealing with Exceptions, not Errors.

seancorfield23:07:50

Instead of :pre/`:post` for dev-time checking, use instrument and check -- those at least are honest about being dev/test tools, not lazy "can't happen and maybe I'll fail randomly in production" assertions...