Rcjp’s Weblog

October 28, 2009

Review of the book “Coders at Work” by Peter Seibel

Filed under: misc — rcjp @ 11:04 pm

Over the weekend I read Peter Seibel’s latest book in which he interviews fifteen big name programmers using a set of similar questions about their programming approach and background.

Apart from a few slow sections it is a worthwhile read. Most interviews I’ve read before of famous coders gloss over interesting answers, but Peter is a practicing programmer and his personal interest shows through in attempting to dig a little deeper. Having said that, unfortunately I don’t think his probing turned up much gold. If you are hoping, as I was, to glean some productive techniques from these computing gods you are likely to be disappointed.

Anyway, on a first reading at least, I pulled out some quotes I thought insightful:

The physical properties of matter are such that 99.9 percent of the time you can understand it in aggregate. And everything you have to know about it, you can understand from dealing with it in aggregate. To a great extent, that is not true in the world of software.” … L Peter Deutsch

And later talking about advice from Jerry Elkind

…measure things. Even sometimes measure things you don’t think you need to measure. That [advice] had a profound effect on me.

Ken Thompson who, it is rather surprisingly revealed, doesn’t have code commit privileges where he works at Google said

“I’ve never been a lover of existing code. Code by itself almost rots and it’s gotta be rewritten. Even when nothing has changed, for some reason it rots.”

Grouping the interviews collectively is perhaps a wrong of me to attempt, but the book as a whole gives the impression of these hackers with sharp minds, primitive tools and not much interest in the software development literature. Quick to rewrite the code they don’t understand, mulling over problems in their head a few weeks, before jotting down a few data structures and debugging the resulting code with print statements.

I guess the book could have been titled “Greybeards Still A Work” as almost all are old-timers as evidenced by the answers to the usual opening question of “When did you learn to program”. The answer is often a lengthy description of some antique paper tape hardware for which they rewrote the operating system over a long weekend. So I’m not sure this book is a picture of an average “coder at work” and there is also a definite west-coast lisp slant to the book, not surprising really as Peter is a west-coast lisper!

There were a few lines of questioning that didn’t seem to lead anywhere like asking all of them if they’d read Knuths ‘The Art of Programming’ (mostly a little bit) and if they’d used literate programming (nope) and what they thought of C++ (they hated it). But, even with these dead ends, its definitely worth a read if only to confirm there isn’t much in the way of programming magic out there – just persistence and obstinacy and little inhibitions about rewriting code.

Finally, I can’t resist a few of quotes that made me laugh:

The whole Web is built on one mistake after another. We have this big pile of accidents.”…Douglas Crockford

Seibel: I think Larry Wall described [lisp] as a bowl of oatmeal with fingernail clippings in it.
Deutsch: Well, my description of Perl is something that looks like it came out of the wrong end of a dog.

and my favourite quote from Joe

…the problem with object-oriented languages is that they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.… Joe Armstrong ”

Right, now I’m off to go and measure something I don’t think I need to measure…

November 8, 2006

Notes from TV Interview with Clive James

Filed under: misc — rcjp @ 4:37 pm

Its rare enough that I find anything worth watching on tv; even rarer to find something that I’d watch twice and positively nonexistent that I’d watch it a third time and scribble down some notes. Well, almost nonexistent, because here are some rough notes on a interview Clive James gave recently on TV on his life:

Born 1939, left Australia at 21, went to Pembroke Oxford and wrote a humorous tv column for the Observer in the 70’s, poems and a three volume autobiography.

Defining moment was his fathers death; he had survived the slave labour camps in Japan but died when, instead of waiting for the ship, he boarded an American plane laid on to take them back home to Australia which flew into a typhoon.

Saw Japanese ‘Endurance’ tv programme as a way to move the violent militaristic culture ‘Bushido’ onto television where it belongs.

Over-attached to his mother, but left for 16 years. “I didn’t get a very amazing degree from Sydney University and later on I didn’t get a very amazing degree from Cambridge. I knew some brilliant students and I wasn’t one of them – I spent too much time reading off the course, and I still do – its an inability to do what is set down.”

Terrible first jobs. Poems came back for two years. His old professor got him into Cambridge. “Very little happened because I willed it. On the whole I have to be asked to do things.”

Liked being a tv critic because it gave him a chance to talk about everything – since there is a programme about every subject. Critics these days get sent a dvd with a week’s tv, he used to watch the channels simultaneously (three) and scribble furiously as there was no way to wind back! Always thinks of pieces in terms of a running order – as he did when at Cambridge foot-lights. He’d take his notes from a week of watching tv and sit down at someone else’s typewriter at the Observer on a Friday morning and type.

“Whenever I thought of a joke, it was usually then, it was usually compressing an argument I already had – what’s the fastest way of saying this and I’ll think of a way that came out funny. And then sit back and laugh at it …”

This became legendary i.e. that he would sit there just laughing.

“…that was possibly a mistake – I was laughing because it had just hit me like a lightening bolt. All the other journalists which stretched into the distance, hated me because they already thought I only worked one day a week and there I was yodeling at my own stuff.”

Infamously described Arnold Schwargzenegar – Brown condom full of walnuts
and a tennis player as ‘a smile like a car crash’ (she had braces).

Some quotes (often abridged but hopefully representative) from the interview:

Ideally I’d like to make every answer an epigram. I was always trying to write the ideal paragraph; and sometimes the ideal paragraph is only a line long. I use a joke as a means of compression, its the fastest way of conveying an argument. But I always did love the tradition of the aphorism.

Some of my favourite things were said anonymously in Hollywood. Someone one said about a young actress “She’d be an nymphomaniac if only they could slow her down”

Rhyming slang I think is the dullest thing that ever happened to the world.

Get the joke in first – no one can say anything about my personal appearance because I got there first. Get your self deprecation in very early before the deprecation starts.

Interviews – Sit there mute, but put something on the desk.

It takes 10 years to build an image on Fleet St, I started finding a 1000 word column restrictive.

I will never stop writing poetry; thats a real test of seriousness because nobody really wants it. Hardly anybody reads poetry habitually, I do, and I like the people that do. But its a small market.

A woman’s world is what I look forward to.

The big lesson I’ve learned – A free society is simply bound to be full of things you don’t like – thats what freedom is.

He has a website http://clivejames.com

June 6, 2006

LUA and OOP

Filed under: misc — rcjp @ 3:52 pm

Its interesting how LUA can simulate oop by just using tables. (the following is from the manual)…

    --
    -- Define an Account object
    --
    Account = {}

    function Account:withdraw (v)
       if v > self.balance then
          print "insufficient funds"
       else
          self.balance = self.balance - v
       end
    end

    --
    -- An Account instance
    --

    a = {balance=50.0, withdraw = Account.withdraw}

    a:withdraw(100.00)
    print("balance = ", a.balance)

    --
    -- do static methods, variables with metatables
    -- 

    Account = {balance = 0}   -- default value for balance

    function Account:new (o)
       o = o or {}   -- create object if user does not provide one
       setmetatable(o, self)
       self.__index = self
       return o
    end

    function Account:deposit (v)
       self.balance = self.balance + v
    end

    a = Account:new{balance = 5}  -- sets a = table with balance=5 and metatable with
                                  -- balance of 0, so this overrides the default
    a:deposit(100.00)
    Account.deposit(a, 100.00)  -- same thing as previous line
    print("a balance = ", a.balance)

    b = Account:new()  -- balance not set so will pick up 0 from above
    print("b balance = ", b.balance)

    --
    -- Inheritance
    --
    SpecialAccount = Account:new()
    s = SpecialAccount:new{limit=1000.00} -- the self parameter will refer to SpecialAccount
                                          -- so the metatable of s will be SpecialAccount

    -- redefine superclass methods

    function SpecialAccount:withdraw (v)
       if v - self.balance >= self:getLimit() then
          print "insufficient funds"
       else
          self.balance = self.balance - v
       end
    end

    function SpecialAccount:getLimit ()
       return self.limit or 0
    end

    -- so with a special account you can go overdrawn
    s:deposit(100.00)
    s:withdraw(200.00)
    print("s balance = ", s.balance)

    -- If only a single object needs a specific behavior
    -- with Lua you do not need to create a new class to specify a new behavior
    -- just implement the necessary function in the _instance_ itself...

    James = SpecialAccount:new{}
    James:deposit(100.0)

    -- James' limit is always 10% of his previous balance
    function James:getLimit ()
       return self.balance * 0.10
    end

    James:withdraw(109.00)
    print("Jame balance = ", James.balance)
    James:withdraw(10.00)
    print("Jame balance = ", James.balance)

June 4, 2006

Raytracing in LUA

Filed under: misc — rcjp @ 3:54 pm

Just learning lua so this might not be correct code; but I thought I’d try a quick translation of a ray tracing program from Common Lisp into lua using some simulated OOP…

    --
    -- Based on Paul Graham's raytrace
    --

    function math.round(num, idp)
       local mult = 10^(idp or 0)
       return math.floor(num  * mult + 0.5) / mult
    end

    function magnitude(pt)
       return math.sqrt(pt[1]^2 + pt[2]^2 + pt[3]^2)
    end

    function unit_vector(v)
       local mag = magnitude(v)
       return {v[1]/mag, v[2]/mag, v[3]/mag}
    end

    function distance(p1, p2)
       return magnitude{p1[1] - p2[1], p1[2] - p2[2], p1[3] - p2[3]}
    end

    function minroot(a, b, c)
       if a == 0 then
          return -c/b
       else
          local disc = b^2 - 4*a*c
          if disc < 0 then
             return false
          else
             local discrt = math.sqrt(disc)
             return math.min((-b + discrt)/(2*a), (-b - discrt)/(2*a))
          end
       end
    end

    --
    -- Sphere functions
    --
    sphere = {}
    sphere.mt = {}  -- do i need to reset this??
    sphere.mt.__index = sphere
    -- sphere.mt.__tostring = sphere.tostring

    function sphere.new (o)
       setmetatable(o, sphere.mt)
       return o
    end

    function sphere.tostring()
       print('the sphere')
    end

    function sphere:intersect(pt, ray)
       -- Calculate if/where a ray starting from point pt hits this sphere s
       local n = minroot(ray[1]^2 + ray[2]^2 + ray[3]^2,
                         2*((pt[1] - self.c[1])*ray[1] +
                            (pt[2] - self.c[2])*ray[2] +
                            (pt[3] - self.c[3])*ray[3]),
                         (pt[1] - self.c[1])^2 +
                         (pt[2] - self.c[2])^2 + (pt[3] - self.c[3])^2 - self.r^2)

       if n then   -- minroot might return false if there is no root
          return {pt[1] + n*ray[1], pt[2] + n*ray[2], pt[3] + n*ray[3]}
       else
          return false
       end
    end

    function sphere:normal(pt)
       return unit_vector {self.c[1] - pt[1], self.c[2] - pt[2], self.c[3] - pt[3]}
    end

    function sphere:lambert(inter, light)
       local pt = self:normal(inter)
       return math.max(0, light[1]*pt[1] + light[2]*pt[2] + light[3]*pt[3])
    end

    function first_hit(eye, ray)
       local hitsomething = false
       local hit = false
       local mindist
       local surface = false
       for i,shape in pairs(world) do
          local inter = shape.intersect(shape, eye, ray)
          if inter then
             local d = distance(inter, eye)
             if hitsomething == false or d < mindist then  -- found nearer shape
                hit, surface = inter, shape
                mindist = d
                hitsomething = true
             end
          end
       end
       return surface, hit
    end

    function sendray(eye, ray)
       local reflect = 0.0     -- defaults to background if first_hit failed
       s, inter = first_hit(eye, ray)
    -- ??   if isinstance(s, shape):
       -- if getmetatable(s) == sphere   
       if s then
    --       print("here s=",s)
          reflect = s:lambert(inter, ray) * s.colour
       else
          reflect = 0
       end
       return reflect
    end

    function colour_at(x, y)
       local ray = unit_vector {x - eye[1], y - eye[2], 0 - eye[3]}
       local reflected = sendray(eye, ray)
       return math.round(reflected*255)
    end

    function tracer(filename, res)
       f = assert(io.open(filename,"w"))
       print 'Writing data to ', filename
       f:write(string.format("P2 %d %d 255\n", res*100+1, res*100+1))
       for y = -50*res, 50*res do
          for x = -50*res, 50*res do
             f:write(string.format("%d ", colour_at(x/res, y/res)))
          end
       end
       f:close()
    end

    world = {}
    eye = {0, 0, 200}

    function raytest(option)
       res = option.res or 1
       world = {
          sphere.new{c={  0.0, -300.0, -1200.0}, r=200.0, colour=0.8},
          sphere.new{c={-80.0, -150.0, -1200.0}, r=200.0, colour=0.7},
          sphere.new{c={ 70.0, -100.0, -1200.0}, r=200.0, colour=0.9}
       }

       for x = -2, 2 do
          for z = 2, 7 do
             table.insert(world, sphere.new {c = {x*200, 300, z*-400},
                                             r = 40.0, colour = 0.75})
          end
       end
       tracer('luaspheres.pgm', res)
    end

    raytest{}

June 2, 2006

LUA Programs

Filed under: misc — rcjp @ 3:40 pm

Been playing with LUA which is a clean simple embeddable language to see how it compares to python. The first thing to write, as all lisp programmers probably do, is a factorial program

    function factorial(n)
       if n == 1 then return 1
       else return n * factorial(n-1)
       end
    end

    print(factorial(10))


I’m a bit suprised there is no default easy way to dump out a table (which is lua’s basic data structure), but found and fiddled with something from the lua
mailing list…

    function mydump(t, indent)
       local indent = indent or 0
       if type(t) == "table" then
          for key, value in pairs (t) do
         io.write(string.rep (" ", indent))
    --   print("key = ", key, "value = ", value)
         if type (value) == "table" then
            io.write(string.format("table[%s]--v\n", key))
            mydump (value, indent + 7)
         elseif type(value) == "function" then
            io.write(string.format("%s\n", tostring (value)))
         else
            io.write(string.format("[%s] => %s\n", tostring (key),value))
         end
          end
       else
          io.write(t .. "\n")
       end
    end


A few test programs…

    function occurences (lst)
       local occur = {}
       for key, value in ipairs(lst) do
          occur[value] = (occur[value] or 0) + 1
       end
       return occur
    end

    z = occurences{'a', 'b', 'a', 'd', 'a', 'c', 'd', 'c', 'a'}
    for key, val in pairs(z) do print(key, val) end


and

    --
    -- read words line at a time
    --
    function readwords1()
       local dict = {}
       local words = assert(io.input("/usr/share/dict/words"))
       for line in io.lines() do
          _, _, word = string.find(line, "^%s*(%w+)%s*$")
          table.insert(dict, word)
       end
       table.sort(dict)
       io.input():close()
       return dict
    end

    --
    -- read whole file then use gfind
    --
    function readwords2()
       local dict = {}
       assert(io.input("/usr/share/dict/words"))
       for word in string.gfind(io.read("*all"), "%w+") do
          table.insert(dict, word)
       end
       table.sort(dict)
       print("size = ", table.getn(dict))
       io.input():close()
       return dict
    end

    --
    -- read whole file using io.open then use gfind
    --
    function readwords3()
       local dict = {}
       local f = assert(io.open("/usr/share/dict/words", "r"))
       for word in string.gfind(f:read("*all"), "%w+") do
          table.insert(dict, word)
       end
       table.sort(dict)
       f:close()
       return dict
    end

    function findwords(word, dict)
       local found = {}
       for _, dictword in next, dict do
          if string.find(dictword, word) then table.insert(found, dictword) end
       end
       return found
    end

    d = readwords3()
    res = findwords("shovel", d)
    for _, w in ipairs(res) do print(w) end


On the lua mailing list I found a nice prog to print out globlals…

    -- find undefined global vars
    -- typical usage: luac -p -l *.lua | lua globals.lua

    local S={}
    local G={}
    local F

    while true do
       local s=io.read()
       if s==nil then break end
       local ok,_,f=string.find(s,"^[mf].-<(.-):[%d,]+>")
       if ok then F=f end
       local ok,_,l,op,g=string.find(s,"%[%-?(%d*)%]%s*([GS])ETGLOBAL.-;%s+(.*)$")
       if ok then
          if op=="S" then S[g]=true else G[g]=F..":"..l end
       end
    end

    for k,v in next,G do
       if not S[k] and not _G[k] then
          io.write(k," may be undefined in ",v,"\n")
       end
    end


and an interesting way of implementing the fibonacci sequence with meta-tables

    fibs = { 1, 1 }                                 -- Initial values for fibs[1] and fibs[2].
    setmetatable(fibs, {                            -- Give fibs some magic behavior.
      __index = function(fibs,n)                    -- Call this function if fibs[n] does not exist.
                   fibs[n] = fibs[n-2] + fibs[n-1]  -- Calculate and memorize fibs[n].
                   return fibs[n]
                end
    })

August 15, 2003

Fuerteventura Holiday

Filed under: misc — rcjp @ 4:46 pm

I first landed in Fuerteventura mid July, low season apparently. A more appropriate term may be touched down as the first hour of so driving through the countryside from the airport down to Jandia felt more like a lunar expedition.

The rocks littering the entire island are called volcanic spree and it was stressed by the tour rep in all seriousness that it was not building rubble. Although given the vast amount of building work in flux across the island that would be entirely possible.

I enjoyed the holiday, mostly lazing on the beach and choking on the salt spray (Fuerte apparently means ‘windy’ and it is!) except the mealtimes, these I started to dread. Wine brought to my table was dispatched by the waitress with such violence, once most of the cork was out of the bottle, from the near vertically inverted bottle that I felt the need to lean back from the table.

After a careful slurp from my brimming wine glass, I commenced battle to retain what food I’d brought from the buffet on my table. I do not know how the staff eat at home but it clearly is, how can I put it, in one go. The merest hint of my knife and fork settling on the plate, even though not together, signaled the start of an competition for the staff of the large restaurant to race and retrieve it. This made me wonder if they get paid a bonus per plate. Spookily they would sneak up from behind when you weren’t ready, ask if you had finished and since you were still chewing whatever head movements you made were interpreted as yes. At one point, and I kid you not, one of the prowling staff used the back of my chair, whilst I was eating, to change their trajectory.

But of course, being English, I didn’t complain. I took the holiday to consider moving to a sunnier climate away from England’s dullness. I asked the barman ,”When does it rain here?” He sighed and said, “Maybe one day in the spring, for about 50 minutes. Its just sun, sun, sun.” He looked more fed up than I did about our constant drizzle, I explained we had the opposite problem and then it struck me: perhaps he looks forward to holidays in a dank rainy climate with all our flora and fauna, canals and streams.

Blog at WordPress.com.