Fork me on GitHub
#clojure
<
2018-09-05
>
mihir05:09:54

Hey guys, needed some help.

mihir05:09:14

I haven't been able to make my function which determines whether a number is even or not performant.

mihir05:09:21

(defn is-even?
  [x]
  (let [i (atom 0)
        even-or-maybe-odd (atom true)
        return? (atom false)
        result (atom nil)]
    (while (not @return?)
      (if (= @i (max x (- x)))
        (cond (true? @even-or-maybe-odd) (do (swap! return? (fn [r] true)) (swap! result (fn [k] "Even")))
              (false? @even-or-maybe-odd) (do (swap! return? (fn [r] true)) (swap! result (fn [k] "Odd"))))
        (do (swap! i (fn [n] (+ n 1)))
            (swap! even-or-maybe-odd (fn [n] (not n))))))
    @result))

dadair05:09:59

Seems unnecessarily stateful. Here’s how even? is defined in the core library:

(defn even?
  "Returns true if n is even, throws an exception if n is not an integer"
  {:added "1.0"
   :static true}
   [n] (if (integer? n)
        (zero? (bit-and (clojure.lang.RT/uncheckedLongCast n) 1))
        (throw (IllegalArgumentException. (str "Argument must be an integer: " n)))))

mihir05:09:38

It works fine for small values. But bigger values it takes time

mihir05:09:07

Is that an accepted hit? Or am I doing something wrong?

emilaasa05:09:28

I have no idea what you are trying to do but a normally performant way to check for even or odd on integers is bitwise and

👍 4
mihir05:09:09

But that returns boolean. I need to return a string.

mihir05:09:36

Its also using a lot of java. Which would be difficult.

emilaasa05:09:40

(str (even? 1)) ?

mihir05:09:54

Yes but I need to return "Even" or "Odd" string.

dadair05:09:07

(if (even? x) "Even" "Odd")

👍 8
mihir05:09:58

(defn- even?
      [x]
      (let [i (atom 0)
            even-or-maybe-odd (atom true)
            return? (atom false)
            result (atom nil)]
           (while (not @return?)
                  (if (= @i (max x (- x)))
                    (cond (true? @even-or-maybe-odd) (do (swap! return? (fn [r] true)) (swap! result (fn [k] true)))
                          (false? @even-or-maybe-odd) (do (swap! return? (fn [r] true)) (swap! result (fn [k] false))))
                    (do (swap! i (fn [n] (+ n 1)))
                        (swap! even-or-maybe-odd (fn [n] (not n))))))
           @result))

(defn is-even?
      [x]
      (if (even? x) "Even" "Odd"))

👍 4
dadair05:09:45

Why can’t you use the built-in even??

mihir05:09:07

I have to implement my own even?.

the2bears05:09:27

But you didn't implement your own... you just wrapped the built in. edit: How did I look past the first fn? 😛

mihir05:09:36

I am sorry I don't understand. I overrode the even? with my own implementation in the snippet above right?

the2bears05:09:12

Oh... I'm so blind tonight. You're right... I glanced past the first, big function and just looked at 'is-even?' :shame:

ahungry05:09:37

well, 2 = 0

emilaasa05:09:49

@mihir

(defn even? [x]
  (= 0 (bit-and x 1))
)

seancorfield05:09:54

You can use zero? instead of (= 0 ...)

emilaasa05:09:20

I would use even? instead of writing my own tho 😄

emilaasa05:09:31

I'm still not sure what we are doing here

seancorfield05:09:41

(defn even? [x]
  (zero? (bit-and x 1)))
(none of those hanging ) 🙂 )

👍 4
emilaasa05:09:51

oh is that a style thing?

emilaasa05:09:55

Looks a bit better

emilaasa05:09:09

I'm a noob if you can't tell 🙂

emilaasa05:09:02

Is there a fmt thing that uses those rules?

emilaasa05:09:15

Been enjoying gofmt at my day job

seancorfield05:09:23

clj-fmt I think.

seancorfield05:09:04

There are plugins for Leiningen and Boot too I think.

emilaasa05:09:10

yeah looks like it

seancorfield05:09:52

BTW folks, for "noobs", you can usually find folks will be more attentive and go into more detail in #beginners (since folks opt-in there to help new Clojurians).

seancorfield05:09:35

@mihir Your algorithm is linear in the size of the number which is why it is slow for larger numbers.

seancorfield05:09:45

You also have a lot of unnecessary complexity in your code. (swap! my-atom (fn [_] value)) could just be (reset! my-atom value) -- but that's all very procedural since you're using a lot of mutable state. Very non-idiomatic for Clojure...

mihir05:09:29

Thank you.

Eccentric J05:09:48

Anyone familiar with https://github.com/dm3/clojure.java-time? I’m trying to set the seconds, and ms of a local-time to 0 but it’s not clear to me how to do that.

seancorfield05:09:20

@jayzawrotny Sounds like you want to truncate to minutes?

seancorfield06:09:50

(jt/truncate-to (jt/local-time) :minutes)
is that what you want?

Eccentric J06:09:10

I looked at that function

Truncates this entity to the specified time unit. Only works for units that
divide into the length of standard day without remainder (up to `:days`).
` made me think it can’t go more precise than days?

seancorfield06:09:51

@mihir I don't think threading helps readability there -- and a simple if is going to be clearer than using a lookup map

seancorfield06:09:25

(defn even? [n] (if (zero? (mod n 2)) "Even" "Odd"))
seems simpler to me

seancorfield06:09:47

"up to :days" means it can't be bigger than days -- but it can be smaller.

Eccentric J06:09:23

Oof it works 😩 I should have just tried it! Overthought it. So up to means from right to left in this case?

seancorfield06:09:45

It means (from the smallest unit) up to :days 🙂

Eccentric J06:09:37

Ah, right! So it’s because 1 day === 1000ms 60s 60m * 24h where as :weeks, :months, etc… would require some kind of calendar knowledge?

seancorfield06:09:49

Yup, that's right!

seancorfield06:09:41

We use java-time a lot at work -- we're using it to replace a combination of date-clj and clj-time (the latter wraps Joda Time which is essentially deprecated since Java 8 added Java Time).

seancorfield06:09:49

I really like java-time.

Eccentric J06:09:51

First time working with time in Clojure, found clj-time but it was deprecated from the README so working with java-time. The API definitely makes more sense to me than clj-time.

Eccentric J06:09:27

Especially the format function

seancorfield06:09:27

Yeah, I deprecated clj-time recently in favor of pushing people to java-time. Michael and I will continue to maintain clj-time for the foreseeable future... but I don't think it'll gain many new features at this point.

Eccentric J06:09:53

Ack! I had not recognized you were one of the authors, I didn’t mean to be so blunt. 😶

seancorfield06:09:07

Hahaha... I inherited clj-time so I'm not emotionally attached to it 🙂 I like that everything is UTC but sometimes the API can be very verbose... and Joda Time definitely have some quirks (but at least it's value-based).

seancorfield06:09:28

I've sunsetted a bunch of my own libraries over the years as I've realized there are better ways to do stuff...

seancorfield06:09:22

(and I've been doing OSS for nearly 30 years now so there's a long trail of abandoned stuff behind me!)

Eccentric J06:09:54

Hah that’s pretty impressive! I’m having trouble quantifying my experience. Been using github for about 8 years now but haven’t really been all that active in any particular OSS community or project. Quietly released a couple of libraries across a couple of languages but so far all my learning and experience has pulled me to Clojure so here I am.

Eccentric J06:09:31

If you don’t mind for the sake of conversation: Any libraries you are particularly proud of or would be upset to sunset?

seancorfield06:09:43

clojure.java.jdbc is probably the one I'm most invested in these days.

seancorfield06:09:03

I recently took over core.cache and core.memoize and a while back I took over tools.cli -- but I haven't really formed any attachment to those yet. Somewhere in the middle would be boot-new and clj-new (a port from Boot to clj / tools.deps).

seancorfield06:09:01

And HoneySQL is another recent adoption. It is in need of some consistency love I think. Still figuring out how best to move forward with that one.

seancorfield06:09:39

I've been maintaining java.jdbc for about seven years now and it's really grown as I've grown with Clojure... so I've made a lot of mistakes along the way but I'm really happy with most of the library now and I think it's a lot more consistent (and a lot more powerful) than it was when I took it on (as clojure.contrib.sql in the old, monolithic Clojure Contrib library back in the 1.2 days).

Eccentric J07:09:45

jdbc is a big deal. An insane amount of projects depend on that. Is that project stressful? I’ll have to check some of those out as I haven’t encountered them but what drew you to Clojure in 1.2?

Petrus Theron06:09:17

Been writing a lot of Swift code lately. holds head in hands Just a thank you to @richhickey for values-first so I don't have to craft boilerplate abominations like this in Clojure just to do copy-on-write structs:

public struct PIDParams {
   var kP: Double
   var kI: Double
   // ...etc.
}

protocol Cloneable { // uggghh
    func clone() -> Self
}

extension PIDParams: Cloneable {
    func clone() -> PIDParams {
        return PIDParams(
                kP: , kI: , kD: self.kD,
                deadzone: self.deadzone,
                minOutput: self.minOutput, maxOutput: self.minOutput,
                minWindup: self.minWindup, maxWindup: self.maxWindup)
    }
}

// in order to do convenient struct mutation:
let pid1 = PIDParams(kP: 0.5, kI: ...)
var pid2 = pid1.clone()
 = 0.7

👀 4
🤯 12
😶 8
😓 4
Saikyun06:09:41

haha, I love it when your langauge can't deal with minX: self.x, minY: self.y (* 1000) in any reasonable way

mping10:09:02

Hi all, somebody using clojure.jdbc? what method (eg: execute!) should one use for a query like “insert into .. returning id” (postgres)?

gon11:09:16

db-do-prepared-return-keys

mavbozo11:09:24

@mping i use jdbc/execute! like this

mping12:09:10

@mavbozo tks I figured it out, was using a bad postgres driver

souenzzo13:09:06

Hello. I'm testing the new alpha7 but I cant understand this error message: https://gist.github.com/souenzzo/17ec14b0ecbf676b7cb9af79aff5409b

😅 4
bronsa13:09:28

@souenzzo that's not alpha7

bronsa13:09:30

Syntax error macroexpanding clojure.core/ns at (1:1). Cause: Call to clojure.core/ns did not conform to spec.
((:import [org.agrona.concurrent UnsafeBuffer] [java.nio.ByteOrder])) - failed: Extra input spec: :clojure.core.specs.alpha/ns-form

bronsa13:09:32

this is alpha7

bronsa13:09:06

and the issue is that the ns decl should be

(ns ^{:no-doc true} onyx.state.serializers.windowing-key-encoder
   (:import [org.agrona.concurrent UnsafeBuffer]
            java.nio.ByteOrder))

leongrapenthin14:09:53

So (ns foo (:import [some.class])) is not working anymore

alexmiller15:09:23

that never did work - it just silently did nothing

leongrapenthin14:09:01

against the new core specs

leongrapenthin14:09:05

is this intentional?

bronsa14:09:57

the [foo bar] syntax is only intended for prefix usage

deliciousowl14:09:13

I'm using luminus and I did lein rollback and now lein migrate won't work... wth

leongrapenthin14:09:27

@bronsa So I don't have to import anymore if don't need an alias?

bronsa14:09:44

no you still have to import

bronsa14:09:21

sorry I totally glossed over the "if I don't need an alias" part 🙃

bronsa14:09:33

you never had to import classes if you don't need aliases

bronsa14:09:51

classes are automatically loaded on first use

leongrapenthin14:09:21

great thanks for clarification

deliciousowl14:09:47

why does it say "Migration reserved by another instance. Ignoring." and now the databse is empty, this is madenning

deliciousowl14:09:51

im just going to create a new project and copy all the files over..

theeternalpulse14:09:58

Is there a way with transducers to instead of using conj function to tell it to conj by 3, or partition within the tranducer expression, or would that just have to be done afterwards.

Cheese Cake Aficionado14:09:18

@theeternalpulse your profile picture is amazing.

theeternalpulse14:09:05

thanks lol, I made it myself

sundarj15:09:03

@theeternalpulse there's a partition-all transducer, if that's what you're looking for

dean21:09:11

bikeshedding question: When you have a boolean value in a config map, how do you name it?

(def option-a {:do-the-thing true})
(def option-b {:do-the-thing? true})
(def option-c {:should-do-the-thing? true})

ghadi21:09:24

If i'm going to be serializing to JSON I usually leave the question mark off. Otherwise I tend towards the middle option

hiredman21:09:29

{:the-thing? true}

seancorfield21:09:43

+1 for {:the-thing? true} (unless you're serializing to JSON -- leave the question mark off)

seancorfield21:09:19

(and, yes, deliberately without verb/sentence prefixes)

the2bears21:09:40

:would-do-the-thing? or :could-do-the-thing? depending on mood 😉

noisesmith21:09:02

:under-prevailing-conditions-would-the-task-in-question-be-carried-out?

20
dean21:09:15

Looks like option b (more or less) is the big winner, the guy doing my PR is going to be so pleased

noisesmith22:09:00

some fun trivia I learned today

ledger.tools.event-ids-test=> (.keySet {:a 0 :b 1})
#{:a :b}
ledger.tools.event-ids-test=> (get (.keySet {:a 0 :b 1}) :a)
nil

andy.fingerhut23:09:44

.keySet seems pretty rarely used even with in the Clojure implementation itself -- a couple of places in the compiler. Did you have a reason for using it vs. (set (keys my-map)) ?

hiredman23:09:47

it is interesting that get specifically checks java.util.Map, but not java.util.Set

noisesmith23:09:15

yeah - it was more of a "wouldn't it be clever to use this built in method instead of (comp set keys)" followed by WAT

noisesmith23:09:31

and easy to replace it with (comp set keys) given that result, of course :D

andy.fingerhut23:09:37

Oh, yeah. Another weirdness there, of course: (get (java.util.TreeSet. [1 2 3]) 1) => nil

andy.fingerhut23:09:36

There are other good reasons to avoid using mutable collections in Clojure, too.

noisesmith23:09:33

ledger.tools.event-ids-test=> (.contains (.keySet {:a 0 :b 1}) :a)
true
- of course

andy.fingerhut23:09:44

e.g. clojure.core/hash is not consistent with clojure.core/=, so you typically cannot find mutable Java collections if you try to use them as set elements or map keys.

noisesmith23:09:36

yeah, mutable items as keys only make sense with object identity

jetzajac23:09:28

Hi. Does anyone know what is the status of clojure-in-clojure implementation? is it any usable in production?

benzap23:09:09

I don't think there is a clojure-in-clojure implementation that has been maturing, but it is a dream

jetzajac23:09:54

just checked out clojure.tools.emitter.jvm and trying to make it something