Fork me on GitHub
#beginners
<
2019-06-24
>
Daouda01:06:43

Hey Folks, why `dotimes` are presumably for side-effects?

andy.fingerhut01:06:25

because the return value is always `nil`

andy.fingerhut01:06:42

If you want something that always returns `nil` with no side effects, you can just use `nil` instead.

Daouda01:06:54

Sorry but I still didn’t get the point. Return always nil means a function is side effect?

andy.fingerhut01:06:40

No matter what `dotimes` expression you write, that entire `dotimes` expression will always return the value `nil`.

andy.fingerhut01:06:48

It will never ever return any other value.

Daouda01:06:45

oh okay, so he just do stuffs and return just `nil`

andy.fingerhut01:06:08

`dotimes` will evaluate its body the given number of times, and throw away all of their return values.

andy.fingerhut01:06:12

then return `nil`.

andy.fingerhut01:06:40

So if you want to get back return values of the body of something that is executed repeatedly, you should not use `dotimes`

andy.fingerhut01:06:36

If you execute `(dotimes [i 10000] (+ i 5))` you will get back nil, use up some electricity, and convert it to heat.

Daouda01:06:48

``If you want something that always returns `nil` with no side effects, you can just use `nil` instead.``
please can you give an example. I didn`t get this.

andy.fingerhut01:06:19

Suppose you want a function that returns `true` if x is greater than 5, otherwise it returns `nil`.

andy.fingerhut01:06:05

I could write it this way: `(defn x-gt-5 [x] (if (> x 5) true (dotimes [i 10000] (+ i 5))))`

andy.fingerhut01:06:18

or I could write it this way: `(defn x-gt-5 [x] (if (> x 5) true nil))`

andy.fingerhut01:06:36

The first way is not such a good idea.

Daouda01:06:00

Thank you very much I got it now 😄

vnctaing05:06:35

Hi, how do you set environment variables in clojurescript ? I’ve been using https://github.com/yogthos/config for the back-end, but doesn’t seem to be supported in clojurescript ?

ordnungswidrig06:06:39

I assume, you’re on nodejs?!

Kevin09:06:11

I personally use https://github.com/weavejester/environ for Clojure, but it should support ClojureScript as well

dharrigan10:06:25

I'm wondering, given a (edn) map, is idomatic, if you need to get to a sub value, to do this `(-> my-map :rootkey :subkey1 :subkey2)` I know there is `(get-in my-map [:rootkey :subkey1 :subkey2])`, but is it just a matter of preference?

noisesmith16:06:20

minor nitpick: edn is a string format, what you have is an instance of clojjure.lang.IPersistentMap, or you can just call it a hash-map

noisesmith16:06:12

in fact java.util.Map even works here (a clojure map is both)

lepistane11:06:34

i've seen both usually for extracting i use `get-in` but for transformation i use `->`

👍 4
Crispin11:06:21

I use get-in more now days. Can be chained in with -> like `(-> s some-func (get-in [:path :to]) some-other-func)`

Crispin11:06:47

jumar19:06:13

btw. the "keyword-based approach" also allows you to specify a default value:

``````(:b {:a 1} :not-found)
;;=> :not-found
``````

😮 8
Crispin11:06:05

`(get-in coll path default)`

dharrigan11:06:14

dmaiocchi15:06:29

@dharrigan I also use `get-in`. For transformation I think -> or --> macros are better

dharrigan15:06:36

thanks! 🙂

orestis16:06:27

Get-in also works for vectors if you know the index, eg. if you have a tuple

dmaiocchi17:06:36

Question is doseq an antipattern? Should be preferable to use map and then run! For evaluating the lazy coll?

manutter5117:06:07

It's an antipattern to misuse doseq, but there are legitimate uses.

noisesmith17:06:07

@darioszr run! is a replacement for map, I use run! when it's more straightforward to describe the operation as a function of one argument, and doseq when it's more straightforward to describe it as a body of operations

> For evaluating the lazy coll? say more @darioszr

what are you doing in the body of the doseq?

noisesmith17:06:52

(run! g (map f x)) can always be replaced by (run! (comp g f) x)

andy.fingerhut17:06:35

doseq is eager. It always returns nil. Because it always returns nil, it is useless for returning a sequence of processed items. dotimes shares these properties with doseq.

noisesmith17:06:52

oh yeah, the "for evaluating the lazy coll" part is weird there

andy.fingerhut17:06:30

That is why the doc strings for both doseq and dotimes say that their bodies are "presumably for side effects", because if they did not have side effects, you should very likely be using something other than doseq or dotimes.

dmaiocchi17:06:25

OK thx ! I'm iterating over a list of maps apply a function with the coll , then it can be that this collection contains also another collection so I needed to do map in map kind-of 😁

dmaiocchi17:06:13

I did doseq because I had some troubles, with the map in map

dmaiocchi17:06:30

But I think was my fault 😁

noisesmith17:06:41

are you doing this in order to construct a resulting data object, or purely for side effects?

andy.fingerhut17:06:48

If you like the way that doseq helps you iterate over nested things, but you want to return a value, `for` might be helpful.

andy.fingerhut17:06:28

But it is certainly possible to do a `map`, where the function you provide to it does a `map` on the elements of the sequence traversed by the outer `map`.

noisesmith17:06:40

or if you need an output shaped mostly like your input, there's clojure.walk

4
andy.fingerhut17:06:52

Uh, I said that last sentence incorrectly, I think..

andy.fingerhut17:06:53

I meant: It is certainly possible to do a `map`, and give it a function that also uses `map`. The latter `map` can straightforwardly be used to traverse over sequences or collections that are elements of the "top level" sequence or collection.

4
dmaiocchi17:06:57

OK thx ! I might check and rewrite it without doseq. I'm basically dispatching depending on the value of some conf, and then from there I call a Client API call for getting the result

ding ding -- you are doing a side-effect, and this cool and a totally appropriate use of doseq

4

doseq returns nil, and you may want to collect the results of calling the client API

if you don't need them, doseq is fine

dmaiocchi17:06:11

Thx walk looks also cool 😎

dmaiocchi18:06:41

In case of curiosity, I have seen some Talks about S3 advantages as storage solutions for a clojure application. But I was looking for an opensource solution for it, which one did you tried(a list is also welcome:clj: ) ? mean I would like to build an opensource project for learning, where justr try different storage solution à la s3

seancorfield19:06:50

@darioszr We're using the Cognitect AWS library for our S3 stuff.

dmaiocchi19:06:45

My rationale behind this, is that I got insipired by Rich talk about plop programming (place oriented programming) and since I don't want use S3, I was wondering to use some alternatives.(even if I need maybe to setup it first etc) I have found riak out there, which I was considering for building an app on top of it

you still need storage to remember things

PLOP as applied to S3 would be "don't rewrite the same object over and over"

or don't store customer 42's record in bucket/key/42

dmaiocchi19:06:23

Yep I would dont mind to setup storage to some servers

Azrea21:06:57

Is there a good way to get `clojure.jdbc` to return `java.time.OffsetTime` for `timezonetz` columns in Postgres?

seancorfield22:06:17

@atamiser Do you mean `clojure.java.jdbc` or `clojure.jdbc`?

Azrea22:06:58

I'm dumb, and meant `clojure.java.jdbc`

seancorfield22:06:45

(you'll need to extend `IResultSetReadColumn` to whatever PostgreSQL-specific type that column is in JVM-land)

Azrea22:06:17

I fear my problem is more subtle than that. By default, the Postgres JDBC driver returns `java.sql.Timestamp` values for `timezonetz`, which destroys the timezone information contained in the field, so by the time the value reaches `IResultSetReadColumn`, it has already lost its timeone information. The Postgres JDBC driver can deserialize `timezonetz` fields to better Java time objects, but only if you specifically request the right class in the `ResultSet.getObject` call, but I don't currently see an easy way to do that with `clojure.java.jdbc`

jumar07:06:36

If you meant `TIMESTAMPZ` then this doesn't store timestamp either - and in the same way as `TIMESTAMP` is stored as UTC internally.

jumar07:06:55

`TIMESTAMPZ` is mostly about the "conversions" when reading/writing from/to the database

hiredman22:06:49

what makes you think Timestamp destroys the timezone information?

hiredman22:06:23

my guess is it doesn't, but the default way clojure prints it formats it as utc

Noah Bogart22:06:41

quick question about multimethods: can multimethods do multiple parameter? like `(defn x ([y] (x y nil)) ([y z] (do-stuff y z)))`? if not, is there a common idiom for doing so?

Noah Bogart22:06:19

the documentation makes it seem like there isn't, but clojuredocs doesn't have any examples showing yes or no, lol

hiredman22:06:21

(defmethod whatever dispatch-value what-ever-can-go-after-fn)

hiredman22:06:51

``````ser=> (doc defmethod)
-------------------------
clojure.core/defmethod
([multifn dispatch-val & fn-tail])
Macro
Creates and installs a new method of multimethod associated with dispatch-value.
nil
user=>
``````

hiredman22:06:15

fn-tail is meant to imply anything that follows fn in a form like `(fn ...)`

Noah Bogart22:06:35

oh, interesting, okay

Azrea23:06:11

You're right, it doesn't destroy the TZ info. I'm getting confused by a clojure library I'm using to handle Java 8 times.

Noah Bogart23:06:32

I'm having trouble making that work in the repl, @hiredman. if you don't mind looking this over, can you tell me what i've done wrong?

Noah Bogart23:06:46

``````user=> (defrecord Step [c])
user.Step
user=> (def step (->Step 5))
#'user/step
user=> (defmulti continue (fn [x] (class x)))
#'user/continue
user=> (defmethod continue user.Step
#_=>   ([x] (continue x nil))
#_=>   ([x y] (println "you gave me y: " y)))
#object[clojure.lang.MultiFn 0x47b269c4 "clojure.lang.MultiFn@47b269c4"]
user=> (continue step)
Execution error (ArityException) at user/eval5886\$fn (form-init3452919453452640532.clj:2).
Wrong number of args (2) passed to: user/eval5880/fn--5881
``````

hiredman23:06:33

your dispatch function has to be able to handle all the arities

Noah Bogart23:06:37

ah, that's what I was missing