Programmerer.com

Keeping fun in the house

Jeg vil ha en klokke på armen som teller ned til min død

I kveld fant jeg en fil datert 25. mai 2012, med en liste over ting jeg vil. Den var slik:

  1. Jeg vil ha en klokke på armen som teller ned til min død.
  2. Jeg vil sette opp et regnskap over alle pengene jeg kommer til å bruke i løpet av hele livet.
  3. Jeg vil se et plot av min subjektive følelse av lykke mot årsinntekt og fritid.
  4. Jeg vil skrive en blog post om implementasjonen av AND i Clojure.

Den siste har jeg i hvert fall gjennomført! 1 av 4 er ikke så aller verst. Fremtiden, her kommer jeg!

 

Hvis du ikke har hvis – eller «If assembly and Clojure»

Fra Kodemaker sin Yammer, hvor Clojure’s implementasjon av «and» leder til hvordan man implementere «if» — i assembly:

Sten Morten Misund-Asphaug

Sten Morten Misund-Asphaug

Ble forespurt om jeg ville holde foredrag på javaBins sommermøte 13. juni. Da kjører vi på med en usedvanlig vakker implementasjon av operatoren «and».

Det er Clojure sin (https://github.com/clojure/clojure/blob/master/src/clj/cloju…) — og den har jeg tenkt å gjøre forståelig (og deilig) for java-programmerere.

May 21 at 1:19pm Stein Tore Tøsse, Odin Hole Standal, Stian C. Alsos and 3 others like this.

  • Finn Johnsen
    Finn Johnsen: hva er forskjellen på and og -> egentlig?

    May 21 at 1:34pm You like this.

  • Finn Johnsen
    Finn Johnsen: ah, august forklarte, bare meg som kan fryyyyktelig lite clojure

    May 21 at 1:46pm

  • Finn Johnsen
    Finn Johnsen: at ‘and’ har en implementasjon, og ikke er i språket, var så ubegripelig i et øyeblikk at hjernen nekta for at det bare var plain old ‘and’

    May 21 at 1:50pm

  • Sten Morten Misund-Asphaug
    Sten Morten Misund-Asphaug in reply to Finn Johnsen: Ja ikke sant det er fett!

    May 21 at 1:51pm

  • August Lilleaas
    Eventuelt kan du jo lage en enklere versjon som bare gjør (if ~x (and ~@next)). Da blir ikke faktisk false-y verdi returnert, som `and` gjør, men det er kanskje bedre. Ye ye.

    May 21 at 2:02pm

  • Odin Hole Standal
    Odin Hole Standal: Genialt tema, denne presentasjonen kunne jeg likt å fått med meg :)

    May 21 at 4:31pm

    August Lilleaas likes this.

  • Trygve
    Trygve: …
    ([x & next]
    `(let [and# ~x]
    (if and# (and ~@next) and#))))
    Elegant?
    Nerder :)

    May 21 at 4:49pm

  • August Lilleaas
    August Lilleaas in reply to Trygve: Kjempeelegant! Fin bruk av rekursjon, og implementasjonen piggybacker bare på if. :D Nesten ikkenoe kode heller.

    May 21 at 4:57pm

  • Trygve
    Trygve: Ser at det er virkelig mye snacks for nerder i core.clj. Skal prøve å skjønne noe her :)

    May 21 at 4:59pm

    Kolbjørn Jetne likes this.

  • Kjetil Jørgensen-Dahl
    Kjetil JD: Og for de uinnvidde – klarer dere å pønske ut hvorfor ‘if’ faktisk må være en del av språket (et spesialtilfelle)?

    May 21 at 9:11pm

  • Sten Morten Misund-Asphaug
    Sten Morten Misund-Asphaug in reply to Trygve: Trygve – ALGORITMEN er elegant — dessverre ser ASCII-tegnene stygge ut ;)

    Wednesday at 10:21am

  • August Lilleaas
    August Lilleaas in reply to Kjetil JD: Merker at jeg ikke en gang klarer å tenke meg hva «if» egentlig er. Trenger å kikke på litt assembly-koding..

    Wednesday at 4:23pm

  • Sten Morten Misund-Asphaug
    Sten Morten Misund-Asphaug in reply to August Lilleaas: For å få til det, trenger du conditional jumps. JE (jump equals), JNE (Jump Not Equals), etc., som sjekker om verdien er lik noe i et register.Så:
    if( a == b ) c = d; else b = b + 1;… blir noe sånt som
  • mov( a, eax ); -- flytt a inn i register eax
     cmp( eax, b ); -- sammenlign b med eax
     jne ElsePart; -- hvis de ikke er like, hopp til ElsePart
     mov( d, c ); -- vi har ikke hoppet, de er like, så flytt d inn i c
     jmp EndOfIf; -- hopp ut av if-true
     ElsePart: -- navn
     inc( b ); -- b++
     EndOfIf: -- nå er vi ferdige med vår if og kan gå videre

Personlige leveregler gir dybde og mening

For noen år siden fant jeg ut at jeg ville prøve å lage et sett «leveregler» for meg selv. Noe som ville inspirere og motivere meg, og som jeg kunne la guide meg når jeg var i tvil om neste trekk.

Hver gang jeg tar dem frem, gir de meg noe nytt. Samtidig gir de en dybde og mening, og er en rød tråd i livet.

Hvis du tar deg tid til ettertanke i dag, kanskje min lille remse kan gi deg noen innspill. Disse er selvfølgelig svært personlige. Dine vil være annerledes.

* * *

Ha integritet.
Med den, søk først suksess hjemme.
Hjelp de jeg er glad i å dyrke det de vil.
Snakk aldri stygt om noen.
Gi fritt av kjærlighet, uten forbehold, uten å skulle ha noe tilbake.
Vær rolig, trygg og støttende.
Gi av din tid – mest til de nærmeste, og mye til de andre, og husk å ta vare på deg selv.
Hvil.
Hold kroppen og hodet i stand. Bygg sakte.
Søk friheten til å gjøre enda viktigere ting, men ikke la det ødelegge for det andre.
Ikke vær redd. –
Vær moden nok til å balansere egne ønsker og behov med andres –
trygg nok på meg selv til å holde på mitt, og stor nok til å gi slipp.
Skriv ditt eget liv. Ta ansvar for det som har skjedd, og for det som skal skje.
Lær av feil – og gi slipp.
Tilgi deg selv og andre.
Vær ditt eget livs visjonær – tenk stort. Tenk i generasjoner.
Basert på prinsipper, verdier og visjoner – planlegg.
Sett planene ut i live.
Gjør de viktigste tingene først.
Gjør deg ferdig med det du har startet på. Ta beslutninger raskt, og endre dem langsomt.
Evaluer. Zig-zag. Rett opp kursen.
Lær.
Mediter.
Vær taknemmelig.
Behold kontakten med naturen.
Verdien kommer innenfra deg – både den menneskelige og den økonomiske.
Tjen menneskene, de som er nå, og de som kommer.
Ta vare på venner.
Menneskene først.

En deilig implementert and

Lite er så godt som en deilig implementert and.

Ta en titt på denne. Dette er en Clojure macro. Hvis du ikke kan Clojure, gjør ikke det noe, dette skal bli veldig forståelig likevel.

(defmacro and
"Evaluates exprs one at a time, from left to right. If a form
returns logical false (nil or false), and returns that value and
doesn't evaluate any of the other expressions, otherwise it returns
the value of the last expr. (and) returns true."
  {:added "1.0"}
  ([] true)
  ([x] x)
  ([x & next]
   `(let [and# ~x]
      (if and# (and ~@next) and#))))

(Hvis du vet hva en macro er i språket C, må du umiddelbart glemme den definisjonen du kan. En macro i et lisp-språk er ikke det samme.)

Macroen er verkøyet som gjør en vanlig, dødlig programmerer til Gud over Gudene.

Nå er det jo slik at ethvert programmeringsspråk, i hendene på Den Rette, er et gudommelig verktøy. Det lar deg Skape: Når du programmerer, tar du en tanke og gjør den til virkelighet.

Det er sterke krefter du besitter. Likevel: macroen hever deg til et nytt nivå. Et meta-nivå, i forhold til der du var.

For mens du før var bundet av mulighetene i det språket du programmerte, er du nå i stand til å forme selve språket.

Du kan skape muligheter som ikke fantes før.

Clojure selv et er godt eksempel, for Clojure er for en stor del skrevet i Clojure. Til og med noe så basalt som operatøren and, er skrevet i språket selv.

Det hadde ikke vært mulig uten macroer. (Prøv å implementere and i ditt språk, uten å bruke den innebygde operatoren. Prøv så å lage unless.)

Så la oss ta en titt på hvordan dette er gjort.

(defmacro and
"Evaluates exprs one at a time, from left to right. If a form
returns logical false (nil or false), and returns that value and
doesn't evaluate any of the other expressions, otherwise it returns
the value of the last expr. (and) returns true."
  {:added "1.0"}
  ([] true)
  ([x] x)
  ([x & next]
   `(let [and# ~x]
      (if and# (and ~@next) and#))))

Denne macroen heter and, og har tre forskjellige «inngangsporter». Den kan ta ingen, ett, eller flere argumenter, og bruker forskjellige «kropper» alt ettersom hvor mange argumenter den blir kalt med. Den første inngangsporten, har en enkel implementasjon:

  ([] true)

Dette sier: Hvis du kaller macroen med ingen argumenter [], så returner true.

Et kall uten argumenter ser slik ut: (and), og det returnerer true.

user> (and)
true

Hvis du kaller and med ett argument, får du verdien av det argumentet tilbake.

  ([x] x)

Det kan vi test ut:

user> (and true)
true
user> (and false)
false
user> (and 3)
3
user> (and wdcd)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: wdcd in this context, compiling:(NO_SOURCE_PATH:1)

Aha. Symboler som har en verdi, i hvert fall, de får vi rett tilbake. (La oss glemme det siste forsøket her, det får være tema for en annen gang. (Hvis du virkelig ønsker å gå i dybden, ta en titt på min implementasjon av lisp, I Groovy, med forklaring.))

Så kommer vi til kjøttet i anda.

  ([x & next]
   `(let [and# ~x]
      (if and# (and ~@next) and#))))

Hvis vi sender inn et argument x, og flere argumenter (i en liste som nå heter) next, så skaper vi nå litt kode, on the fly. Clojures «backtick» operator

`

gjør noe vi er vant til fra web templating, men ikke i kode: Den sier at det som kommer nå, skal settes verbatim inn i koden til kalleren. Det betyr «quote», med andre ord.

Når vi ikke ønsker å quote, altså når vi faktisk ønsker oss verdien av noe inne i denne templaten vår, bruker vi unquote:

~

Så når kalleren kjører denne koden, skjer dette: Vi lar symbolet and# (vi bruker # for navngiving av variabler i macroer, for å unngå navnekonflikt med eventuelle variabler kalleren har i sin egen kode)… altså … vi lar symbolet and# være verdien av unqote x — altså x som ble sendt inn i makroen med kallet.

Hvis vi kalte (and true), så er variablen #and == true, nå.

Med dette gitt, kjører kalleren videre.

      (if and# (and ~@next) and#))))

Hvis det er slik at and# == true, så kaller vi macroen and igjen (med noen argumenter ~@next, se neste paragraf). Hvis and# !== true, så returnerer vi and# selv:

user> (and false true)
false
user> (and false 1)
false
user> (and false 3 2 1)
false

Ok, nå vet vi hva som skjer her:

      (if and# (and ~@next) and#))))

når and# er false (vi får den i retur). Hva når and# er true?

Siden det jo er den kjente and-operatoren vi driver og implementerer, så må jo også resten av argumentene være sanne, for at and skal returnere true, sånn alt i alt.

Husker du inngangsporten vår for denne versjonen av and-macroen?

  ([x & next]

Vi sender altså inn ett argument x, pluss en liste med de resterende argumentene, next.

Denne mystiske karen her:

~@next

er Clojure sin syntax for «unsplice». La oss for enkelhets skyld si at den tar hele listen av argumenter som ligger i next, og flater den ut. (Se http://clojuredocs.org/clojure_core/clojure.core/unquote-splicing for en mer nøyaktig beskrivelse av unquote splicing.)

Vi skal jo kalle and igjen, og vi ønsker ikke å sende hele listen med argumenter til x (og ingenting til next), for da blir

  ([x] x)

kalt (og da får vi bare returnert listen av argumenter, og det der jo dumt), istedenfor

  ([x & next]

som fortsetter evalueringen.

Det som er nesten magisk, og som gjør dette til en så vakker implementasjon av and, er at vi nå er ferdige.

Hvordan kan det ha seg?

Jo, Clojure and oppfører seg sånn:

user> (and true)
true
user> (and true true)
true
user> (and true 1 true)
true
user> (and true 1)
1

Altså: Hvis alle verdier er sanne, returner den siste verdien, ellers returner false.

Deilig, deilig, deilig. And.

Tanker er vanedyr

Jeg tok trappen i dag.

Jeg ville ikke. Hele kroppen verket etter en dårlig natt med hostende unger.

Men jeg vet en ting. Jeg vet at tanker er fysiske. Da mener jeg ikke på sånn new age mumbo jumbo måte. Men at det som skjer i hjernen når jeg tenker, er at elektriske impulser blir sendt gjennom fra et neuron til et annet, fra det ene neuronets aksoner til det andre neuronets dendritter. Og at hver gang en slik overføring skjer, så styrkes banen mellom de to nevronene

Det vil si at det neste gang er lettere å tenke nøyaktig den tanken jeg tenkte nå.

Tenk litt på det: Tanker er også vanedyr.

Har du tenkt noe en gang, er det lettere å tenke det igjen. Når du velger ikke å ta trappen i dag, blir det lettere å velge ikke å ta trappen i morgen.

Og det som skjer når du tenker «jeg tar ikke trappen i dag, jeg tar den i morgen», er ikke at du tar trappen i morgen, men at det er lettere for deg å tenke «jeg tar ikke trappen i dag, jeg tar den i morgen» — i morgen også.

Det blir ikke lettere å ta trappen dagen deretter.

Konverst, kan du bruke denne kunnskapen til å gjøre det lettere for deg selv å ta trappen i dag. For ikke bare får du treningen det innebærer å ta trappen i dag, du kan også fortelle deg selv, med rette, at det blir lettere å ta trappen i morgen. Både fysisk og psykisk.

Du vet den følelsen du av og til har, den Eureka- eller «aha»-følelsen, når du plutselig forstår noe du ikke har forstått før? Den følelsen av at «hvorfor har jeg ikke sett denne koblingen, nå skjønner jeg endelig alt» … ?

Hjerneforskere kan med moderne real time, høyoppløslig MRI se at det skjer. Det er nemlig øyeblikket da det dannes en ny kobling mellom neuroner. Forskerne kan se koblingen dannes. Så fysiske er tanker.

Er du vant til å være sint?

Er du vant til å være taknemmelig for de fine tingene i livet ditt?

Hva du tenker er en vanesak. Og det fine er at nye vaner kan bygges. Det krever disiplin i starten. Og vi har en begrenset mengde viljestyrke å bruke hver dag (viser nyere forskning). Så det kan lønne seg å velge én ny vane av gangen. Konsentrere deg på ett felt.

Jeg skal velge trappen hver dag i to uker.

… eller …

Hver morgen når jeg våkner de neste to ukene, skal jeg tenke over hva i livet mitt som gjør meg takknemlig.

Enhver god beslutning vil styrke deg og gjøre det lettere å ta gode beslutninger i fremtiden. Enhver dårlig beslutning vil svekke deg, og gjøre det enklere å ta dårlige beslutninger i fremtiden.

Ta vare på deg.

Syncing av pdf-lesing

Jeg ønsker meg en pdf-leser som kan synke hvor langt jeg har kommet, mellom devicer. Slik som Kindle kan med Amazon-bøker. Kindle-appen selv kunne gjerne gjort det…

Men siden den ikke kan … hvem lager det først? Jeg er villig til å betale kr 35 for en slik leser, tenker jeg. Sånn cirka.

Programmeringsglede

«I think that it’s extraordinarily important that we in computer science keep fun in computing. When it started out, it was an awful lot of fun. Of course, the paying customers got shafted every now and then, and after a while we began to take their complaints seriously. We began to feel as if we really were responsible for the successful, error-free perfect use of these machines. I don’t think we are. I think we’re responsible for stretching them, setting them off in new directions, and keeping fun in the house. I hope the field of computer science never loses its sense of fun. Above all, I hope we don’t become missionaries. Don’t feel as if you’re Bible salesmen. The world has too many of those already. What you know about computing other people will learn. Don’t feel as if the key to successful computing is only in your hands. What’s in your hands, I think and hope, is intelligence: the ability to see the machine as more than when you were first led up to it, that you can make it more.»

Alan J. Perlis (April 1, 1922-February 7, 1990)