This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
En lørdagstanke.
Hvis du skal gjøre ikke-påkrevde tilpasninger på kode, er det fint å bruke binding
og dynamiske variabler. Hvis koden må ha argumenter for å fortsette å kode, bør du sende inn et parameter.
Å legge på en cache for kode som kjører fint uansett er OK å gjøre med binding fordi det funker fint uten cache. Databasetilkobling skal ikke være satt i en dynamisk variabel — uten den kjører ikke koden, derfor bør den være en eksplisitt parameter.
Enig/uenig?
På generelt grunnlag er jeg veldig skeptisk på å benytte thread-locals (som binding
er) til å styre noen form for flyt. Selv en cache (med unntak av evigvarende "memoization") er med på å gjøre koden din impure. Om cachen står foran noe som uansett er impure (som kanskje er det mest naturlige) er jeg fortsatt skeptisk. Jeg er veldig glad i la parametre styre flyt og ikke noe magisk thread-local som plutselig kommer inn fra siden langt nedi callstack'n.
Om du skal bruke binding
, husk å realisere all data du eventuelt henter ut og som er påvirket av bindingen inne binding
-uttrykket. Returnerer du en lazy seq som utfører operasjoner som hviler på bindingen din så har du noen overraskelser i vente.
Når det er sagt er binding
et fint verktøy. Jeg har for eksempel brukt binding
for å legge ved nyttig verdier (f.eks. korrelasjons-id'er) til loggerammeverket så jeg slipper å forholde meg til dette overalt hvor det logges.
Nå er jeg ikke noe fan av stubbing heller, men enkelte ganger er det vanskelig å komme unna. Da er jo binding
et greit verktøy (https://github.com/magnars/stubadub)
"You should treat stubbing your code much like stubbing your toe: It's painful and you should strive to avoid it." —@U07FCNURX 😂👏
Enig med @U0ESP0TS8 og tilføyer at binding er en sånn ting som nok er mest nyttig i biblioteker, og selv der svært sparsomt
Jeg tror bindings stammer fra Clojures barndom. Printgreiene bruker det feks. Print-greiene til Clojure er ikke det mest imponerende i språket.
Det er ganske mange dynamiske variabler i core, fra http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/*agent* og nedover
ja — jeg har skrevet (with-out-str (clojure.pprint/pprint my-data))
flere ganger enn jeg skulle ønske
det overrasker meg egentlig litt at det ikke finnes noen clojure.pprint/pprint-str
. Vi har jo pr-str
og prn-str
.
når Clojure var nytt husker jeg det var helt vanlig å bruke binding for config og sånt i Ring, i stedet for å bare putte det på request-mappet
Kult! Ja - kode på request-mappet blir mer eksplisitt. I alle fall når du skriver koden som legger noe på request-mappet, og når du skriver koden som henter ting ut av request-mappet.
i starten tenkte jeg at det er feil å putte ting som ikke har med et request å gjøre på request-mappet. Det var den gangen jeg var vant til OO og så på maps som aggregater, ikke data :)
Synes også det er skikkelig fint at man får mange funksjoner som tar inn ett argument: en request (med ekstra greier). Hvos man skal begynne å sende med ekstra greier som ekstra argumenter, blir det mye mer ... styr i koden. Og da blir det fristende å putte ting "på siden" - og man slutter å skrive funksjoner som tar inn argumenter og gir tilbake verdier. Som @U04V5VAUN var innom på fredag! https://clojurians.slack.com/archives/C061XGG1W/p1692955976169749?thread_ts=1692955976.169749&cid=C061XGG1W Jeg lærte først FP med Haskell, og akkurat denne tingen synes jeg "luktet feil" lenge. Fordi det er vanskelig å "request og ekstra ting man kan trenge".
Jeg tror at den tidlige bruken av bindings i Clojure (og biblioteker) er en arv fra Common Lisp? Hele condition systemet til CL er såvidt jeg kan forstå/huske bygget over dyn-vars. Man må også huske på at CL ikke nødvendigvis er et programmeringsspråk der man programmerer funksjonelt 🙂
Sant. Jeg prøvde meg litt på boka "Land of Lisp", der man skriver spill i Common Lisp.
I det første spillet tar man input fra brukeren. Da bruker man defparameter
. Jeg synes det var litt rart å "def-e" det, i stedet for å ta input til funksjoner - så man kan skrive tester som funksjonskall.
sant, det har aldri gitt mening for meg når folk sier de “programmerer i Lisp”, for meg høres det ut som “programmerer i et språk med C-style syntax”, aka det sier meg omtrent ingenting
History of Clojure har noen interessante betraktninger om designvalg clojure deler med (Common) Lisp.
Så litt på den over helga. Rich har skrevet rasjonale for valgene han gjorde i clojure 1.0, samt da defprotocol
kom i 1.2.
https://clojure.org/about/history