Fork me on GitHub
#beginners
<
2021-05-17
>
valerauko02:05:09

Thanks, I didn't know about arrayType. On the other hand Integer/TYPE need eval instead of resolve so not sure how I feel about that...

Ivan Koz02:05:39

@vale could bring them into a closure at function definition, so it only runs once at program start

Ivan Koz02:05:02

(let [get\\convert primitives here] (defn ..)

Juλian (he/him)12:05:38

are there tipps, when one should use defrecord or when they could be too much overhead or overcomplicate things?

Noah Bogart12:05:03

Records are good when your map is closed (no extra or missing keys), and/or when you want to implement/extend a protocol

Juλian (he/him)12:05:13

and when should I use or not use a protocol?

Juλian (he/him)13:05:22

sorry, will read more about them, maybe I'll understand it then

Noah Bogart13:05:03

that's a good intro to the topic

pithyless13:05:03

If someone wants to learn more about protocols/multimethods/etc. I found this booklet to be a really good summary of all the pros/cons and when you may want to use which: https://leanpub.com/clojurepolymorphism

👀 12
stagmoose15:05:45

I am using d3 in my project and it is possible to show result like this (first pic): with this code (second and third pic): I am a bit confused about the -> syntax here. I know that is https://clojuredocs.org/clojure.core/-%3E It said: • (-> x & forms)

Threads the expr through the forms. Inserts x as the
second item in the first form, making a list of it if it is not a
list already. If there are more forms, inserts the first form as the
second item in second form, etc.
But I want to ask why using (d3/scaleLinear) instead of d3/scaleLinear after -> Why is (d3/scaleLinear) the "x" above, not d3/scaleLinear Is it reasonable to call a methods like (d3/scaleLinear) without any given argument?

andy.fingerhut15:05:31

I am not familiar with d3/scaleLinear. Is it a Clojure function, perhaps?

andy.fingerhut15:05:40

Or from a quick Google search, perhaps it is an interop call to a JavaScript method?

dpsutton15:05:14

it's a function from d3 that takes no arguments. Whoever made that function made it so that it cannot take arguments. So it's pretty reasonable to call it that way.

🍻 3
andy.fingerhut15:05:00

In Clojure, the syntax (d3/scaleLinear) is the way to call a Clojure function, or a JavaScript method via interop, that takes no arguments.

stagmoose15:05:51

I used shadow-cljs to import d3.js installed using npm

andy.fingerhut15:05:56

Or to be more precise, it is one good way to do so. There are others, but that is the most commonly used.

stagmoose16:05:12

gocha, thanks!

Franco Gasperino18:05:45

when working with threading macros and interleaving -first and -last based on the functions applied, is it more idiomatic to use the as-> macro, or wrap composed in anonymous functions to conform arg positioning?

seancorfield18:05:21

It’s more idiomatic to not mix -> and ->> if you can avoid it.

👆 3
seancorfield18:05:04

See https://stuartsierra.com/tag/dos-and-donts — and the various posts about threading macros.

🙌 3
seancorfield18:05:47

as-> is specifically intended for use inside -> for occasional cases where the threaded value is neither the first nor the last argument.

Franco Gasperino18:05:50

thanks. having read the thread-as post he has on that site, he claims to prefer a wrapper to arrange the args to fit thread-first or thread-last. im staring at the common interaction of the various built-ins and 'into' as an example

seancorfield18:05:00

Rule of thumb: sequence operations use ->> because the “main argument” comes last; collection/object operations use -> because the “main argument” comes first.

Franco Gasperino18:05:52

yes. im reading that now. however, i ran into select-keys and for threading, the main argument is flipped onto its head

Franco Gasperino18:05:15

threading the map, main argument becomes the keyseq

Franco Gasperino18:05:32

"Don’t use anonymous functions to change argument position" ... i should have read this

seancorfield19:05:30

select-keys is a collection function: it takes a collection as the first (main) argument and produces the same type of collection. That’s consistent.

Juλian (he/him)20:05:33

I'm trying to make my input function nicer by adding a prompt at the beginning, but it doesn't work like I'd expect. Here a minimal example:

(defn prompted-read [prompt]
  (print prompt)
  (read))
When I try it in REPL (clj or lein repl) by calling it like this (prompted-read "Input: "), the prompt is shown only after I enter something. Is there a way to fix this?

seancorfield20:05:04

@julian608 You need flush:

dev=> (defn prompted-read [prompt]
 #_=>   (print prompt)
 #_=>   (flush)
 #_=>   (read))
#'dev/prompted-read
dev=> (prompted-read "Input: ")
Input: 123
123
dev=> 

ghadi20:05:04

@julian608 add a (flush) call after print, flushing only happens after newlines

Juλian (he/him)20:05:28

thanks, @seancorfield and @ghadi - should have known this from other programming languages facepalm

noisesmith13:05:39

I think this is a TTY API issue and not a language issue

orpheus22:05:35

How do I create an object with optional and default values? I have a function that returns an invoice object

(defn invoice [account-id]
    {:account-id account-id
     :key-1 "key-1"
     :key-2 "key-2"
     …
    })
If sometimes I want to create an invoice and only change key-1 or only change key-2 or change key-3 and key-4 but not 1 and 2. Is there a possible way or better way to go about this? That way I don’t need to create an arity body for each possible combination

phronmophobic22:05:06

It's kind of hard to tell what types of functions you're trying to write, but probably some combination of assoc or merge?

orpheus22:05:46

Thank you will look into. Writing functions to create object payloads to send over http

phronmophobic22:05:57

I usually end up using merge for similar use cases. You can pass the original map as the first arg and selectively overwrite keys. Eg.

(merge payload
       ;; always add these
       {:id (next-id)}
       ;; optionally add these
       (when (:checksum? opts)
          {:checksum (calc-checksum payload)})
       ;; choose one
       (if-let [user-agent (:user-agent opts)]
          {:user-agent user-agent}
          {:user-agent "batman"}))

phronmophobic22:05:20

not the best example, but hopefully shows the idea

orpheus22:05:16

fantastic thank you

noisesmith13:05:09

I always put "defaults" as the first arg to merge, that way you get the intuitive behavior that any provided keys are used as overrides

orpheus15:05:15

@U051SS2EU could you share an example please?

noisesmith16:05:23

(let [defaults {:user-friendly true}] (merge defaults opts)) - if opts has a : user-friendly key, that value is used, otherwise you get the default