Fork me on GitHub
#beginners
<
2019-04-24
>
hiredman00:04:04

it doesn't prevent the seq from being gc'ed while it walks it

solf00:04:37

Ah thanks, that explains the difference between doseq and for

seancorfield01:04:06

@dromar56 Also for is lazy, so it will only iterate through the items if the result is consumed -- doseq is eager and always iterates through the items.

seancorfield01:04:05

for example:

(first (for [n (range 100)] (do (println n) n)))
only realizes the first chunk (32 items) since nothing beyond that is asked for

seancorfield01:04:34

(quite a few lazy things in Clojure work in chunks of 32 items for efficiency rather than being completely lazy)

didibus05:04:08

I was actually wondering. Does the chunking also help reduce the amount of intermediate operations?

didibus05:04:05

As well as the memory? By needing less thunks?

Joel02:04:14

is it possible to modify an existing function, so that further usages use modified version?

hiredman02:04:25

that is generally how it works

hiredman02:04:27

user=> (defn f [] 1)
#'user/f
user=> (defn g [] (f))
#'user/g
user=> (g)
1
user=> (defn f [] 2)
#'user/f
user=> (g)
2
user=>

john02:04:00

@joel380 you can make a thing to "shadow extend" functions. I did something like that in dispacio https://github.com/johnmn3/dispacio#function-extension

Joel02:04:07

cool. didn't know it was that simple... and namespace doesn't matter.

jaihindhreddy07:04:46

How do I get an ISO 8601 string from an instant?

jaihindhreddy07:04:17

(str #inst "2019-04-15T00:00:00.000-00:00") gets me "Mon Apr 15 05:30:00 IST 2019"

jaihindhreddy07:04:31

I'm looking for "2019-04-15T00:00:00.000-00:00" or "2019-04-15T00:00:00.000"

arbscht08:04:30

so clojure inst on jvm extends java.util.Date. if you're happy to format using java interop using builtin DateFormat classes, it can be done something like this (-> (java.text.SimpleDateFormat. "yyyy-MM-dd'T'HH:mm:ss.SSSZ") (.format #inst "2019-04-15T00:00:00.000-00:00"))

arbscht08:04:26

clojure itself does something like that to print the default representation of inst values, which you can see here if you're curious https://github.com/clojure/clojure/blob/28efe345d5e995dc152a0286fb0be81443a0d9ac/src/clj/clojure/instant.clj#L168

arbscht08:04:52

but the more general advice is if you want to play with dates, maybe use a library like clj-time 🙂

Lennart Buit08:04:58

(or clojure.java-time, which uses Java 8's java.time.* package)

👍 16
jaihindhreddy08:04:20

Thanks everyone!

Arlo Christensen11:04:10

Hi guys, I've been struggling trying to port some little test projects from Lein to deps.edn, I was using https://github.com/seancorfield/dot-clojure/blob/master/deps.edn and could get some things working, but seems like it doesn't play well with Atom and VSCode REPLs also looks like too hacky to use, at the end after spending a lot of time on it I'm wondering if it really worth the effort? With Lein all works fine and its widely supported and documented, why to use clj & deps.edn if they doesn't solve the whole development tooling cycle as Lein does? is it needed to wait until it will become more standard then?

Ivan Koz11:04:26

you also can use lein + deps.edn

👍 4
Arlo Christensen11:04:19

I missed that then

dmaiocchi13:04:15

hi all, i have a noob question: i'm using cider + emacs. Sofar i have compiled the buffer with C-x C-k but in the cider-jack-in REPL, i get unable to resolve symbol: .. plus some java errors.. the code itself it is fine, but it seems to me that cider cannot load my project namespace, because it prompts user instead of the namespace..

Ivan Koz13:04:09

@darioszr thats to #cider and #emacs

pythonjokeun15:04:48

If i want to do distributed data processing in clojure, what is the best trick / technique / library to do that ?

pythonjokeun15:04:33

somehow onyx is too complicated for idiot like me 😞

pythonjokeun15:04:43

by distributed i mean across multiple nodes, not cores

gklijs03:04:00

For multiple reasons I really like Kafka. There isn't a recent client that I know of, but it's pretty easy to do Java interop. However it takes some knowledge to be able to run Kafka properly in production, also there are a lot of things you can configure, which can be overwhelming.

noisesmith16:04:48

@pythonjokeun I don't think there's anything for Clojure that actually makes this easy or simple. There are various frameworks available but they all have gotchas and trade offs and complexities that aren't directly related to the task you are attempting.

ok17:04:00

(fn add-five [x] (+ x 5)) why this optional add-five ?

hiredman17:04:06

because not all functions need to refer to themselves

evocatus17:04:38

I finally made it - lazy prime numbers generator (for ProjectEuler exercize #3). @tabidots, check it out: https://github.com/reflechant/project-euler-clojure/blob/master/src/ex03.clj

yuhan18:04:48

This looks pretty good! One small thing I would change is to define primes as a variable instead of a function, since its value is always the same

yuhan18:04:01

also I did a quick benchmark, by switching to vectors and conj/ peek you can get it about 8x faster 🙂

mloughlin18:04:46

which function call does peek replace?

mloughlin18:04:06

first in (inc (first xs))?

yuhan18:04:15

yup

👍 4
yuhan18:04:29

(defn next-prime
  ([xs] (next-prime xs (inc (peek xs))))
  ([xs x]
   (if (some #(zero? (rem x %)) xs)
     (recur xs (inc x))
     x)))

(defn primes []
  (map first
    (iterate (fn [xs]
               (conj xs (next-prime xs)))
      [2])))

(qb-stats [n 500]
  (vec (take n (primes))))
;; => ["8.968601 ms" {:n 500}]
;; => ["5.522698 ms" {:n 400}]
;; => ["3.352999 ms" {:n 300}]
;; => ["1.485483 ms" {:n 200}]
;; => ["0.389093 ms" {:n 100}]

;; original definition
;; => ["62.149674 ms" {:n 500}]
;; => ["35.983781 ms" {:n 400}]
;; => ["19.734515 ms" {:n 300}]
;; => ["8.039685 ms" {:n 200}]
;; => ["1.778897 ms" {:n 100}]

yuhan18:04:31

here's probably how I would write it:

(def primes2
  ((fn gen-primes [xs x]
     (if (some #(zero? (rem x %)) xs)
       (recur xs (inc x)) ; x is composite
       (lazy-seq (cons x  ; x is prime - add to output
                   (gen-primes (conj xs x) (inc x))))))
   [] 2))

👍 4
evocatus19:04:22

What is this qb-stats thing? I tried to look for simple benchmarking library but couldn't find any

yuhan19:04:41

ah sorry, that's a little utility macro I wrote for myself, it uses Criterium under the hood

evocatus19:04:53

As for the vectors - I thought they ought to be faster but after numerous unsuccessfull attempts decided to make it work first then optimize. When I did it I wanted to change to vecs right away but remembered that last isn't good for vectors but peek didn't come to my mind

tabidots01:04:41

Nice. You sure spent a lot of time on PE #3 😅 Any reason why you were so interested in implementing this as a lazy-seq though? I just checked against my unmemoized trial division filter and I’m getting roughly 2.35ms for (time (count (take 500 (filter naive-prime? (range))))).

tabidots01:04:20

I shied away from using lazy-seqs for this application because the next value depends on ALL of the previous values

tabidots01:04:25

So it becomes unwieldy at a certain point. You’d be surprised how well trial division works (up to n = 1 million or so, don’t know how many primes that is). Beyond that I resorted to sieving using JVM arrays (I had to do that for #437, which requires primes up to n = 100 million, and a modified Sieve of Eratosthenes… ridiculous)

tabidots01:04:17

But good work, though. You probably understand lazy-seqs very well now! Much better than I do. I think I’ve managed to do Fibonacci, triangular, pentagonal, and hexagonal numbers with lazy-seqs. That’s about all I have bothered to use them for so far.

tabidots02:04:08

@UEQDV142J Hey, check out this guy’s lazy-seq implementation (another Eulerian, but I found his gist through Google, rather than a post of his on the forum) https://gist.github.com/kohyama/8e599b2e765ad4256f32

tabidots02:04:36

He managed to fold this into an extremely succinct prime factorization function: https://gist.github.com/kohyama/5b47be8255c1eb859f16

tabidots02:04:12

I have no idea what the performance is like though. I should test it later. I have spent the last 10 days working on factorization algos. Some simple, some ridiculously complex.

hiredman17:04:40

add-five there is a local binding (only valid inside the bodies of the function) that can be used to refer to the function itself

hiredman17:04:16

in that case even, the binding isn't needed, because the function never refers to itself

👍 4
mloughlin17:04:37

@twaima

(macroexpand-1 '(defn add-five [x] (+ x 5)))
=> (def add-five (clojure.core/fn ([x] (+ x 5))))

mloughlin17:04:22

defn is a macro that binds the anonymous fn definition to the name passed using def

john17:04:29

I think some folks use the name for documentation too

delaguardo17:04:23

Not only, but also for making error messages nicer.

ok17:04:50

then why it does not define into namespace :thinking_face:

john17:04:58

because then it would be "anonymous" 😉

mloughlin17:04:00

defn is used to define into namespace

evocatus17:04:22

btw, I would appreciate any comments on my code (6 msgs above)

4
Ivan Koz17:04:53

@twaima def and defn macro creating Var 'container' and binding it to symbol you can either

(def add-five (fn [x] (+ x 5)))
or 
(defn add-five [x] (+ x 5))
(macroexpand '(defn add-five [x] (+ x 5)))
=> (def add-five (clojure.core/fn ([x] (+ x 5))))

🙏 4