code-reviews

roelof 2020-12-17T19:19:18.104700Z

What do you expers think of my solutions: https://github.com/RoelofWobben/Learning_in_public/blob/main/ground_up/src/ground_up/chapter6.clj

2020-12-17T19:24:32.105500Z

> Use a promise to hand the result back out of the thread. Use this > ; technique to write your own version of the future macro. you made a function for this, not a macro, if that matters

2020-12-17T19:25:38.106300Z

and as mentioned elsewhere, your atomSum doesn't use future correctly - it doesn't start one thread until the other completes

2020-12-17T19:26:13.106800Z

also, since this is #code-reviews, I would recommend not using atom as the name for an atom

roelof 2020-12-17T19:27:07.107500Z

oke, so I can change def future to defmacro future ?

2020-12-17T19:27:20.108Z

also, we don't use camelCase for clojure names, we use kebab-case

2020-12-17T19:27:41.108900Z

well, defmacro works differently than defn, I don't know if you actually need to use a macro for this assignment

roelof 2020-12-17T19:27:44.109Z

and how I can I make atomSum work the right way ? I found this chapter very confusing

2020-12-17T19:28:07.109300Z

deref blocks the code until the future exits

2020-12-17T19:28:53.110100Z

if you have (let [a (deref (future ...)) b (deref (future ...))] ...) b doesn't start until a exits

roelof 2020-12-17T19:29:48.111200Z

I had that but if I remember you told me to do this way because the a and b where not used error message

2020-12-17T19:29:48.111300Z

if you have (let [a (future ...) b (future ...)] ...) they both run at the same time

2020-12-17T19:30:15.111800Z

that's not an error message, that's your linter

2020-12-17T19:30:28.112100Z

you still need to deref a and b, but after b is created

2020-12-17T19:30:44.112500Z

(let [a (future ...) b (future ...)] (deref a) (deref b) ...)

2020-12-17T19:31:09.113Z

the deref here is just telling the code to wait for that block to exit (so the atom has the right total in it)

roelof 2020-12-17T19:32:31.113600Z

oke

2020-12-17T19:32:44.114200Z

also, if you aren't using deref as a first class function, or using its optional timeout option, just use @ which expands to deref

roelof 2020-12-17T19:32:44.114300Z

So this is good clojure code :

(defn atomSum []
  (let [atom  (atom 0)
        part1 (deref (future (swap! atom +  (apply + (range 0 (/ 1e7 2))))))
        part2 (deref (future (swap! atom +  (apply + (range 0 (/ 1e7 2))))))]
    (deref atom)))

2020-12-17T19:33:13.115300Z

the deref is blocking part2 so it doesn't start until part1 exits

roelof 2020-12-17T19:33:51.116100Z

so I can ignore th linter message that part1 and part2 are not used

2020-12-17T19:33:57.116400Z

no

2020-12-17T19:34:14.116900Z

you need to deref after part2 is created, or the atom will have the wrong sum

2020-12-17T19:34:27.117300Z

(defn atom-sum []
  (let [a (atom 0)
        part1 (future (swap! atom + (apply + (range 0 (/ 1e7 2)))))
        part2 (future (swap! atom + (apply + (range 0 (/ 1e7 2)))))]
    @part1
    @part2
    @a))

roelof 2020-12-17T19:35:07.117500Z

sorry, I miss you now

2020-12-17T19:35:56.118200Z

deref means "block this thread until that other thread provides a value"

roelof 2020-12-17T19:35:57.118400Z

this is not good :

(defn atomSum []
  (let [atom  (atom 0)
        part1 (future (swap! atom +  (apply + (range 0 (/ 1e7 2)))))
        part2 (future (swap! atom +  (apply + (range 0 (/ 1e7 2)))))]
    (deref part1)
    (deref part2)
    (deref atom)))

2020-12-17T19:36:17.118900Z

what's wrong with it?

2020-12-17T19:36:28.119200Z

(other than the naming stuff mentioned elsewhere)

roelof 2020-12-17T19:36:48.119500Z

oke, then I miss that part

2020-12-17T19:37:21.120Z

also (range 0 x) is the same as (range x)

roelof 2020-12-17T19:37:28.120200Z

because you said this : and as mentioned elsewhere, your atomSum doesn't use future correctly - it doesn't start one thread until the other completes

2020-12-17T19:37:57.120600Z

right, you pasted a version that used deref inside the let block

roelof 2020-12-17T19:38:25.120900Z

oke

roelof 2020-12-17T19:39:35.121400Z

I thought that was on my code on gitlab

2020-12-17T19:40:04.122100Z

oh, that looked like a paste, I didn't notice it was a preview from some plugin

roelof 2020-12-17T19:40:05.122200Z

I see , there I have the version that uses deref

roelof 2020-12-17T19:41:48.122500Z

a moment, I will update my gitlab repo

roelof 2020-12-17T19:43:52.122700Z

oke, updated

roelof 2020-12-17T19:44:01.123100Z

is it now good ?

2020-12-17T19:49:38.123700Z

oh I see you had to fix the ranges too - yeah that looks better

roelof 2020-12-17T19:50:46.123900Z

🙂

roelof 2020-12-17T19:51:07.124400Z

rought ride to learn clojure but slowly i learn it

2020-12-17T19:52:49.125400Z

also note that if x is a double (like your ocde) range makes longs if you ask for (range x), and makes doubles if you ask for (range x y)

2020-12-17T19:53:03.125700Z

(ins)user=> (range 1e2)
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99)
(ins)user=> (range 1e2 2e2)
(100.0 101.0 102.0 103.0 104.0 105.0 106.0 107.0 108.0 109.0 110.0 111.0 112.0 113.0 114.0 115.0 116.0 117.0 118.0 119.0 120.0 121.0 122.0 123.0 124.0 125.0 126.0 127.0 128.0 129.0 130.0 131.0 132.0 133.0 134.0 135.0 136.0 137.0 138.0 139.0 140.0 141.0 142.0 143.0 144.0 145.0 146.0 147.0 148.0 149.0 150.0 151.0 152.0 153.0 154.0 155.0 156.0 157.0 158.0 159.0 160.0 161.0 162.0 163.0 164.0 165.0 166.0 167.0 168.0 169.0 170.0 171.0 172.0 173.0 174.0 175.0 176.0 177.0 178.0 179.0 180.0 181.0 182.0 183.0 184.0 185.0 186.0 187.0 188.0 189.0 190.0 191.0 192.0 193.0 194.0 195.0 196.0 197.0 198.0 199.0)

2020-12-17T19:53:16.126100Z

and I think your code is the kind of code where long vs. double will change the result

2020-12-17T19:53:42.126400Z

doubles are also slower to do math on than longs are

roelof 2020-12-17T19:54:15.127Z

oke, the 0 and the 1e7 were given by the challenges

2020-12-17T19:57:06.128200Z

it looks like in this case it will give the same answer, but if you use the long function eg. (long 1e7) you can ensure it uses integral math

2020-12-17T19:57:51.128500Z

it cuts the execution time in ~half

(cmd)user=> (time (long (apply + (range 0.0 1e7))))
"Elapsed time: 247.583409 msecs"
49999995000000
(ins)user=> (time (long (apply + (range 0 (long 1e7)))))
"Elapsed time: 120.047445 msecs"
49999995000000

roelof 2020-12-17T19:58:38.129Z

oke, so for math things I can better use longs ?

2020-12-17T19:59:04.129500Z

it varies, sometimes you need floating point

2020-12-17T19:59:12.129800Z

but in general longs are better (more accurate, faster)

roelof 2020-12-17T19:59:26.130100Z

oke, thanks for the feedback

roelof 2020-12-17T19:59:37.130400Z

im very slowly learning clojure

roelof 2020-12-17T20:00:15.130800Z

tomorrow I hope I can solve the last one of this page : https://aphyr.com/posts/306-clojure-from-the-ground-up-state

roelof 2020-12-17T20:00:29.131200Z

then I finishced this one after 3 - 4 days

roelof 2020-12-17T20:01:11.131400Z

now time to sleep