Fork me on GitHub
#clojure-norway
<
2023-10-16
>
slipset07:10:01

Kanskje dumt eller no. I TS/JS har man nå fått (eller sikkert hatt en stund) foo?.bar som basically gir deg en slags nil punning, dvs du trenger ikke sjekke om foo er null før du prøver å aksessere bar . Gitt at foo er null, ville foo.bar kasta en exception, mens foo?.bar returnerer null. Jeg rynker litt på nesen når jeg ser foo?.bar i koden vår og tenker at disse frontenderne ikke har kontroll på noe som helst , men klarer ikke helt å fri meg fra at vi gjør jo dette implisitt i Clojure i og med at (:bar foo) returnerer nil når foo er nil Har jeg blitt schitzofren?

😄 1
teodorlu07:10:02

js/ts er jo litt i midten av “typene beskriver det som er” og “ting er dynamisk”. Jeg trives godt i Clojure (ting er dynamisk) og godt i Elm (typene beskriver det som er). Usikker på om midtpunktet mellom de er et sted jeg ønsker å være. Enten gjør jeg en jobb med modellering av data så dataen passer inn i typene, og jeg har kontroll på hvor typene er på et gitt tidspunkt. Ellers koder jeg defensivt mot data, og returnerer nil hvis jeg ikke kan returnere noe fornuftig (med feks when-let). (så hvis du er schitzofren er jeg litt schitzofren jeg óg)

augustl09:10:30

tenker at det nesten må være sånn, når språket er objektorientert i data-aksess

augustl09:10:55

bloggpost-tittel: nil punning? In the kingdom? Of nouns?

leifericf07:10:53

For CSS: Det er et hav av valg hva gjelder styling og CSS, og jeg sliter litt med å se hvilke av disse "CSS rammeverkene" som er best fit med Clojure, Hiccup og HTMX. Bruker dere https://github.com/noprompt/garden (eller noe annet) i kombinasjon med Hiccup, og bruker dere https://getbootstrap.com, https://bulma.io, https://get.foundation, https://tailwindcss.com, https://m2.material.io/develop/web, eller andre "CSS rammeverk?" Hva liker dere (ikke)?

slipset07:10:40

Jeg har brukt bootstrap.

slipset07:10:55

Det er så flink jeg er med css og sånt.

slipset07:10:28

Jeg tror at problemet mitt er mer å få ting til å se pent ut enn hvordan jeg implementerer det pene.

😅 2
leifericf07:10:00

Jeg spurte en front-end utvikler kollega her nå. Hun sier at alle de kule kidsa bruker Tailwind i disse dager.

slipset07:10:26

Jo, men tenk på hva du har gjort med Clojure koden din.

slipset07:10:45

Du har løst problemet med så få deps som over hodet mulig.

👍 1
leifericf07:10:45

Samme her, @U04V5VAUN! Jeg blir så utrolig irritert av å gjøre front-end stuff 😅 "Neeei! Ikke sprett bort der da, din jævel!"

slipset08:10:09

Hvorfor skal du begynne å herje med rammerverk før du klarer å gjøre det uten?

leifericf08:10:15

Også åpner jeg siden i en annen nettleser, på iPhone eller en tablet… "NOOOO!"

leifericf08:10:43

Tanken var å få ting til å se relativt pent ut raskt uten å måtte gjøre så mye CSS-fikling selv.

leifericf08:10:08

Du har løst problemet med så få deps som over hodet mulig.Ja, det er et veldig godt poeng. Kanskje jeg må endelig må tvinge meg selv til å bli komfortabel med CSS fra first principles.

slipset08:10:56

https://github.com/slipset/www.bonzai-hvaler.no/blob/main/index.html er min siste reise i den verdenen. Dette er omtrent det enkleste jeg kunne komme opp med for å løse et problem.

👀 1
leifericf08:10:21

Brått så har du laget en restaurantmeny i HTML/CSS. Du slutter aldri å overraske 😁

leifericf08:10:16

"Det var et interessant navn på et bibliotek! Åja… Det er en nettside. Er den for bonsaitreentusiaster på Hvaler? Så sært! Nei, det er en restaurant! LOL!"

1
slipset08:10:02

Jepp. Har hytte på Hvaler, Ei dame har starta opp en thai greie der, de “fantes” bare på facebook med meny i bilder , så jeg kjøpte domenet, og mekka meny i html.

💜 2
leifericf08:10:19

Doing the Lords work.

slipset08:10:43

Hovedpoenget mitt er vel at dette kunne vært uendelig mer komplisert, men det er det ikke.

👍 1
msolli08:10:22

Jeg bruker Bulma for når jeg bare vil ha noen ferdige klasser å slenge på elementene for å få det “godt nok”. Når man ikke har noen designer, eller er spesielt flink med design selv (meg begge deler), er det fint å bare bruke noe som ser greit ut fra før. Inkluder CSS-fila, skriv HTML, ferdig.

💡 1
msolli08:10:36

Hvor på Hvaler er det hun thai-dama holder til, @U04V5VAUN? Skal dit i helga, og det var mye godt på den menyen!

leifericf08:10:57

Fastlandsveien 10, Vesterøy, Hvaler 🙂

msolli08:10:31

Thanks, lazyweb! 🙂

1
slipset08:10:42

Kan anbefale Phad Thai med kylling 🙂

cjohansen09:10:18

Haha, elsker det @U04V5VAUN 😄

cjohansen09:10:41

"Jeg bygde websiten deres fordi jeg orker ikke å gå på facebook" er bare helt chef_kiss

💯 1
msolli09:10:02

Liker trenden med små thai-sjapper som dukker opp overalt på mindre steder i Norge. Hadde en fantastisk matopplevelse på Ørnes i Nordland i fjor sommer, fra en sånn liten vogn utafor matbutikken.

💯 1
leifericf09:10:36

Enig! Kona og jeg fant en awesome Thai food truck i Røros av alle steder.

slipset09:10:44

Det er faktisk to av dem på under 200m. Den jeg har laget meny for er ved bensinstasjonen og ser ut som Jafs.

slipset09:10:25

Jeg synes forøvrig, sånn fra et Product Manager perspektiv at det er litt gøy å se hva en MVP faktisk kan være. Tenk om man var et eller annet selskap som skulle lage nettsted til den sjappa? Automagisk alt mulig, men hvor mye verdi ville det faktisk bringe over at man har en enkel html meny der man kan ringe inn (sånn bortsett fra at de ikke er så flinke til å ta telefonen 🙂?

💯 2
1
augustl09:10:47

jeg bruker enten tailwind, eller skriver CSS selv i tailwind-style

👍 1
augustl09:10:53

tailwind er vel på en måte det samme for CSS som “Christian sitt” pattern er for kode - CSS-en vet absolutt ingenting om domenet ditt, og er helt generisk 😄

💡 1
augustl09:10:06

egentlig er hovedgrunnen til at jeg digger Tailwind at man kan gjøre pseudo selectors og media queries med inline “styles”

leifericf08:10:32

Dette er kanskje utrolig pirkete, men… jeg liker at koden kan leses "fra toppen og nedover," slik at hvis funksjon A kaller funksjon B, så er funksjon B under funksjon A i kildekoden. Jeg oppdaget at jeg kan bruke clojure.core/declare for å oppnå dette. Men er det god praksis, eller hva synes dere om det? Her er et konkret eksempel: Før:

(defonce server (atom nil))

(defn app [req]
  (case (:uri req)
    "/" (h/home)
    "/greet" (h/greet req)
    (h/not-found)))

(defn stop []
  (when-some [s @server]
    (s :timeout 100)
    (reset! server nil)))

(defn start []
  (stop)
  (reset! server (-> #'app
                     (wrap-params)
                     (hk/run-server {:port 3001}))))

(defn -main []
  (start))
Etter:
(defonce server (atom nil))

(declare start stop app)

(defn -main []
  (start))

(defn start []
  (stop)
  (reset! server (-> #'app
                     (wrap-params)
                     (hk/run-server {:port 3001}))))

(defn stop []
  (when-some [s @server]
    (s :timeout 100)
    (reset! server nil)))

(defn app [req]
  (case (:uri req)
    "/" (h/home)
    "/greet" (h/greet req)
    (h/not-found)))

cjohansen08:10:33

Clojure-kode leses fra bunnen og opp. Jeg ville ikke begynt med det der

💡 2
cjohansen08:10:49

declare er ment for rekursive funksjoner som kaller hverandre

msolli08:10:59

Jeg hadde samme refleks i begynnelsen, men det blir bare slitsomt.

💡 1
leifericf08:10:19

Ja, dette er kanskje et eksempel på en vane som må avlæres.

cjohansen08:10:38

I Clojure kan du ikke bruke kode før den er definert. Det er en styrke (gjør ting veldig forutsigbart), men som @U06BEJGKD er inne på, en tilvenningssak

👍 1
teodorlu09:10:01

jeg pleier også å unngå declare — med mindre jeg har to mutually recursive funksjoner, feks eval og apply. (men det er sjelden jeg trenger mutual recursion i praksis!) Noe i hodet mitt liker veldig godt at avhengighetsgrafen er super-eksplisitt. Nå har jeg lest ned til linje 80. Det eneste som kan være i bruk er koden som allerede er skrevet over. Når jeg leser kode, hopper jeg typisk til funksjonen jeg er nysgjerrig på. Så fortsetter jeg å lese funksjonene den funksjonen bruker (bruker “go to definition” og “go back” og “find usages” veldig aktivt i editoren min).

💯 1
2food09:10:14

Det hender (sjeldent) jeg bruker declare hvis jeg vil ha to funksjoner "ved siden av hverandre" fordi de ligner eller noe, men avhengighetene ikke går opp.

augustl09:10:49

støttes, jeg er helt vant med å scrolle nederst til fila for å se “hovedkoden” i Clojure(Script)

teodorlu09:10:47

urelatert til spørsmålet ditt, @leif.eric.fredheim, jeg synes at koden din begynner å likne et megagodt “hvor bør man starte når man skriver en clojure-app”! Du har en veldig liten kjerne hvor det gir mening å bruke tid på nesten alle bitene du har med (kanskje unntatt wrap-params, vet ikke hva den gjør)

leifericf08:10:41

Uten wrap-params, når jeg går til http://localhost:3001/myhandler?name=param1¶m2 i nettleseren, kommer parameterne inn som en rå tekststreng à la name=param1¶m2 som jeg måtte ha parset selv. Når jeg bruker wrap-params, får jeg parameterne som et map bak en ny :params nøkkel som jeg kan bruke i handlerne mine slik: (get-in request [:params "name"]). Men kanskje det finnes en bedre måte å gjøre dette på uten wrap-params? Det var den første løsningen jeg fant når jeg søkte rundt etter hvordan en bør parse request parametere.

👍 1
teodorlu08:10:43

Jaa. Wrap-params er kanskje fra ring? (jeg mente mer “jeg skjønner ikke hvor denne kommer fra” enn “denne hører ikke hjemme”!)

slipset10:10:10

Ha! Det er ikke så dumt å dusje en gang i blant. Jeg kom plutselig på talken jeg skal sublitte til alle konferanser som et i neste år: «10 years with Clojure». Den lar meg snakke om alt jeg synes er lurt :). Og det som trigget ideen er web-appen til @leif.eric.fredheim :)

❤️ 2
slipset10:10:50

(Jeg regner forøvrig 2014 som året jeg begynte med Clojure :)

cjohansen10:10:58

Jeg hadde mitt første betalte Clojure-oppdrag i 2013! Men måtte krype tilbake til JS-verdenen en liten stund etterpå

leifericf04:10:31

Av nysgjerrighet, hvor godt kjent var du med Clojure (eller LISP mer generelt) før du fikk det oppdraget? Var du allerede på Clojure-toget før oppdraget kom?

cjohansen05:10:27

Oppdraget ba ikke spesifikt om Clojure, det var @U07FCNURX og mitt påfunn 😅 tror ikke jeg hadde gjort veldig mye Clojure før det, husker ikke helt akkurat når jeg plukka det opp. Jeg fikk sansen for Lisp via Emacs Lisp, det var vel kanskje et år eller to i forveien.

👍 1
cjohansen05:10:23

Mener å huske at jeg leste The Joy of Clojure i 2012.

👍 1
leifericf06:10:43

Det er digg med kunder som stoler på en og lar en gjøre teknologivalgene uten restriksjoner 🔥

magnars08:10:01

Det var vel ikke helt det som skjedde heller 🙈 😂

😂 4
cjohansen08:10:21

La oss bare si at vi ble leid inn, vi skrev Clojure, og vi fikk betalt 😅

🔥 2
cjohansen08:10:50

Det viser seg forøvrig at jeg roter noe fælt. Dette oppdraget var i 2014, ikke 2013

😂 1
leifericf13:10:17

Det var relativt enkelt å bruke https://bulma.io i Hiccup. Eksperimenterte litt med å lage "templates" via Hiccup og endte opp med dette:

(ns handlers
  (:require [hiccup2.core :as h]))

(def headers {"Content-Type" "text/html; charset=UTF-8"})

(defn hiccup-html->str [hiccup]
  (-> hiccup (h/html) (str)))

(defn inject-body [content]
  [:html
   [:head
    [:meta {:charset "utf-8"}]
    [:meta {:name "viewport"
            :content "width=device-width, initial-scale=1"}]
    [:title "My App"]
    [:link {:rel "stylesheet"
            :href ""}]]
   [:body
    [:section.section
     [:div.container content]]]])

(defn home []
  {:status 200
   :headers headers
   :body (-> '([:h1.title "Front Page"]
               [:p.subtitle "You are now on the front page."])
             inject-body
             hiccup-html->str)})

(defn greet [req]
  (let [name (get-in req [:params "name"])]
    {:status 200
     :headers headers
     :body (->  `([:h1.title "Greeting Page"]
                  [:p.subtitle "Hello, " ~name "!"])
                inject-body
                hiccup-html->str)}))

(defn not-found []
  {:status 404
   :headers headers
   :body (-> '([:h1.title "Page Not Found"]
               [:p.subtitle "This page does not exist."])
             inject-body
             hiccup-html->str)})
Funker gjør det! Men det er kanskje ikke den beste måten å gjøre det på 😅

leifericf04:10:31

Av nysgjerrighet, hvor godt kjent var du med Clojure (eller LISP mer generelt) før du fikk det oppdraget? Var du allerede på Clojure-toget før oppdraget kom?

leifericf08:10:41

Uten wrap-params, når jeg går til http://localhost:3001/myhandler?name=param1¶m2 i nettleseren, kommer parameterne inn som en rå tekststreng à la name=param1¶m2 som jeg måtte ha parset selv. Når jeg bruker wrap-params, får jeg parameterne som et map bak en ny :params nøkkel som jeg kan bruke i handlerne mine slik: (get-in request [:params "name"]). Men kanskje det finnes en bedre måte å gjøre dette på uten wrap-params? Det var den første løsningen jeg fant når jeg søkte rundt etter hvordan en bør parse request parametere.

👍 1
cjohansen08:10:50

Det viser seg forøvrig at jeg roter noe fælt. Dette oppdraget var i 2014, ikke 2013

😂 1