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?!

kwrooijen09: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 ->

👍 1
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

also alows default if not found

jumar19:06:13

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

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

😮 2
Crispin11:06:05

(get-in coll path default)

dharrigan11:06:14

kk, helpful! thanks!

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

ghadi17:06:29

> For evaluating the lazy coll? say more @darioszr

ghadi17:06:41

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 facepalm 😁

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

clojure-berlin 1
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.

clj 1
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

ghadi17:06:08

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

clj 1
ghadi17:06:32

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

ghadi17:06:20

if you don't need them, doseq is fine

dmaiocchi17:06:11

Thx clj 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

ghadi19:06:13

you still need storage to remember things

ghadi19:06:28

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

ghadi19:06:45

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

NoahTheDuke22: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?

NoahTheDuke22: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 ...)

NoahTheDuke22: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.

NoahTheDuke23: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?

NoahTheDuke23: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 "[email protected]"]
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

NoahTheDuke23:06:37

ah, that's what I was missing