Fork me on GitHub
#clojure-norway
<
2023-09-15
>
slipset07:09:55

Morn! Siste dag på Granka idag. Huff.

🎉 1
1
✈️ 1
cjohansen10:09:28

Å, granka, hørtes digg ut @slipset!

cjohansen10:09:36

Jeg skal oppsøke sol i høstferien

mariuene10:09:32

Morn. som en utvikler som liker meg best i kjelleren, så er eneste solen jeg får i meg http://sol.no trollface

teodorlu10:09:35

http://sol.no, ja! Der var det … litt av hvert.

leifericf10:09:11

Ah, ja, vi kjenner vel alle det gode gamle ordtaket: "Når teltstrengene henger ut av ræva til bjørnen, er det på tide å dra hjem."

😄 1
terjesb10:09:14

Morn! Fredag og jeg har tenkt litt på the thing about a thing. Rettere sagt om multi-arity fn, keyword argument fns som kan ta maps, om rekkefølgen på argumenter, eller om man bare skal sende alt i én map. Jeg har noen ganger brukt en slik multi-arity-sak istedenfor å ha to ulike funksjoner/navn:

(defn a-thing
  "Given things, returns the first thing. Optionally, instead gets the value of ks from the first thing."
  ([things]
   (first things))
  ([things ks]
   (get-in (a-thing things) ks)))
..men det kan jo være at dette heller burde vært to ting: a-thing og a-thing-in. Funker i alle fall som den skal:
(a-thing [{:the :thing} {:the :other-thing}])
;;=> {:the :thing}

(a-thing [{:the :thing} {:the :other-thing}] [:the])
;;=> :thing
Disse variantene funker også:
(defn a-thing [things & ks]
   (get-in (first things) (first ks)))

(defn a-thing [things & [ks]]
   (get-in (first things) ks))
..og kunne vel argumentert for at den siste der er mer idiomatisk enn eksemplet denne posten begynner med, kan til og med ha samme docstring:) Og kunne nå lett lagt på en not-found a la get-in, uten å måtte lage en tredje arity (selv om get-in selv gjør dette med to arities). Kan også enkelt endre den siste der til å ta en map / keyword argumenter, for litt fleksibilitet:
(defn a-thing [things & {:keys [ks]}]
   (get-in (first things) ks))
Funker fortsatt som den skal:
(a-thing [{:the :thing} {:the :other-thing}])
;;=> {:the :thing}

(a-thing [{:the :thing} {:the :other-thing}] :ks [:the])
;;=> :thing

(a-thing [{:the :thing} {:the :other-thing}] {:ks [:the]})
;;=> :thing
Hvis man heller vil ha de valgfrie argumentene først for å bruke med ->> eller partial, så funker ikke det, kan ikke begynne med variadic:
;; ikke tillatt
;; (defn a-thing [& {:keys [ks]} things])
Eventuelt måtte man med med [ks things] angi nil som første argument, hvis man ikke har noen ks: (a-thing nil …) Og vi liker jo ikke å skrive nil som et argument. Da vil jeg kanskje heller ha en arg-map først:
(defn a-thing [{:keys [ks]} things]
  (get-in (first things) ks))
eller hvis man skulle trenge å utvide med mer logikk, bytte til en cond-> når nødvendig:
(defn a-thing [{:keys [ks]} things]
  (cond-> (first things)
    ks (get-in ks)))
Som fortsatt funker:
(a-thing {} [{:the :thing} {:the :other-thing}])
;;=> {:the :thing}

(a-thing {:ks [:the]} [{:the :thing} {:the :other-thing}])
;;=> :thing
Eller vi kan kjøre alt i én arg-map:
(defn a-thing [& {:keys [things ks]}]
  (get-in (first things) ks))
Som funker, på alle mulige måter:
(a-thing :things [{:the :thing} {:the :other-thing}])
;;=> {:the :thing}

(a-thing :ks [:the] :things [{:the :thing} {:the :other-thing}])
;;=> :thing

(a-thing {:ks [:the] :things [{:the :thing} {:the :other-thing}]})
;;=> :thing
Når jeg ser på de nyere API-ene i Datomic (f.eks. qseq), så har det blitt mye arg-map som siste arg, dvs. at man også sender inn tingen i samme map som øvrige argumenter. Selv om de noen ganger også begynner med et separat argument for den “åpenbare” tingen, som kan være f.eks. client eller db. (Opprinnelige q er multi-arity og har både en liste-form og en arg-map-form.) Har det blitt så enkelt som at det alltid er MIMO - map in, map out - med mindre det er en veldig god grunn til noe annet? PS. En siste ting: a-thing burde nok heller vært kalt first-thing.

teodorlu11:09:19

> Opprinnelige q er multi-arity og har både en liste-form og en arg-map-form. Juxt gikk også den veien med xtdb.api/q: https://docs.xtdb.com/language-reference/datalog-queries/#structure

(xt/q
 (xt/db node)
 '{:find [p1]
   :where [[p1 :name n]
           [p1 :last-name n]
           [p1 :name name]]
   :in [name]}
 "Ivan")
Kun map-form, ikke noen vektor-form.

teodorlu11:09:55

Ellers synes jeg selv det kan være ganske vanskelig å si om jeg bør ha ett argument eller to argumenter. Det går kanskje litt på om det man putter i map-et er én ting eller to ting?

terjesb12:09:02

Enig. Heldigvis er det ofte enkelt å bytte fra noe annet til arg-map hvis/når man trenger det. Noterer at jeg samtidig har begynt å utforske kwarg/arg-map litt mer [& {:keys [this that]}] nå som de er map-kompatible, så istedenfor (my-function 1100 12) kan jeg bruke enten (my-function :this 1100 :that 12) eller (my-function {:this 1100 :that 12}). Så blir det tydeligere om 12 er en this eller that. I noen tilfeller kanskje også en :this+that [1100 12].

👍 1
slipset14:09:09

Jeg tror at jeg liker å skille på coersion og andre ting. Jeg husker vi hadde en fn som var litt sånn som dette:

(defn org-label [x]
 (if (string? x) x (:org-label x)))
Det var sikkert mer greier også, men uansett, den var litt sånn, gi meg hva som helst, og jeg gir det det beste jeg kan komme opp med.

slipset14:09:24

Det er mulig at eksemplet ditt ikke er poenget, men jeg skjønner liksom ikke verdien av a-thing funksjonen i det hele tatt, men det var kanskje ikke det du ønsket å diskutere.

terjesb15:09:41

Ja, bruker litt “jeg gir det beste jeg kan komme opp med” i noen tilfeller her også. Enig i at det ble et konsturert eksempel og at en get gjør jobben her, hadde vært bedre å finne frem noe som har vært gjennom “growth” og utvidet med flere argumenter (eller flere keys i en arg-map).

slipset15:09:11

Men sånn halvgenerelt så tror jeg at jeg synes at etter 1.11, så har kw-args fått en renessanse. Jeg synes de kan være fine for fns som skal brukes fra repl’et

(foo :bar baz :qix qux)
vs
(foo {:bar baz :qix qux})
spesielt hvis dette brukes fra et repl som ikke har paredit. Ulempen pre 1.11 var at samme funksjon ble da bare drit å progge mot, siden du da måtte herje med apply og greier, hvis jeg ikke husker helt feil.

💯 1
slipset15:09:14

Det er no sånn kode inni pomegranate som jeg sliter veldig med å lese. Det så også ut til at funksjoner som tok kw-args var mer på moten før (sånn fra tiden da pomegranate ble skrevet). Kanskje en arv fra CL?

cjohansen15:09:03

Jeg misliker asymmetrien mellom å sende masse løse biter som du tar imot som et map. Bare bruk et map.