2010-10-05

Religion Poisons Everything

I may have to get this book:

God is not Great

This excerpt is clearer than most things I've read from Dawkins or Harris.

One great quote : "Religion spoke its last intelligible or noble or inspiring words a long time ago"

2010-09-29

imagining the big G

When the inventor of concepts like "cyberspace" and the originator of cyber-punk and steam-punk talks about the most influential Artificial Intelligence the world has ever seen;

I listen.

Google’s Earth

We’ve seen nothing like it before, and we already perceive much of our world through it.
We’re citizens, but without rights. 
One thing I do take issue with though, is the idea that people should be divorced from their wild youth.
Nor do I take much comfort in the thought that Google itself would have to be trusted never to link one’s sober adulthood to one’s wild youth,
I think that future generations (or my generation) will just be more accepting of 'wild' behaviour, given that the majority of it will be discoverable by anyone.

One can hope anyway.

2010-09-28

Further down the rabbit hole

I was just reading Ben Hutchison's blog post on functional programming:
study-functional-programming-or-be-ignorant/

and I've come to a very similar realisation, with one notable additional point

lisp.

After watching some of the Structure and Interpretation of Computer Programs lectures,
my ideas about software, programming, data and computation have all been significantly changed.
The lectures focus on the theory of computer science using lisp.

In lisp, everything is (can be) represented as a list. This includes the source code, the interpreter, the environment, as well as data structures. The biggest change to my thinking occurred when they showed that something as fundamental as the list can be defined using closures and no other data structure. Something that I thought was an atom, built in, written in assembler; was actually definable in the language using other constructs.

This actually blew my mind.
It meant that all you needed was closures, and function application.
In the scheme example they showed in the lecture, it looked something like this:
(define (cons a b) (lambda (x) (x a b)))
(define (car x) (x (lambda (a b) a)))
(define (cdr x) (x (lambda (a b) b)))

The key is returning a when you call car(head), and b when calling cdr(tail).

I was so excited by this, I decided to implement it in a language I actually understood. ie NOT lisp.
I've been playing a bit with clojure and elisp, as well as haskell and I've been reading about F# and OCaml; But I keep coming back to scala, so I implemented it in that:
type consT[H, T] = ((H,T) => Any) => Any
def cons[H,T](a:H, b:T) : consT[H,T] = x => x(a,b)
def car[H,T](x:consT[H,T]) : H = x((a:H,b:T) => a).asInstanceOf[H]
def cdr[H,T](x:consT[H,T]) : T = x((a:H, b:T) => b).asInstanceOf[T]
 Most of which is actually type annotations, which ensure that the methods are completely generic. This is in contrast to lisps dynamic typing.

Some simplification is possible, but it's still not really the scala way:
type consT[H, T] = ((H, T) => Any) => Any
def cons[H, T](a: H, b: T): consT[H, T] = _(a, b)
def car[H, T](x: consT[H, T]) = x((a, _) => a).asInstanceOf[H]
def cdr[H, T](x: consT[H, T]) = x((_, b) => b).asInstanceOf[T]
If scala were to have some more advanced type inference or dynamic typing, it might look something like:
def cons(a, b) = _(a,b)
def car(x) = x((a,_) => a)
def cdr(x) = x((_,b) => b)
But it's pretty clear that that's not likely.

The beauty of it is, the lisp and scala uses of the above code is pretty similar.
something like this in clojure/lisp:
(def a (cons 1 (cons 2 3)))
(car a)
(car (cdr a))
(cdr (cdr a))

in scala:
val a = cons(1, cons(2, 3))
car(a)
car(cdr(a))
cdr(cdr(a))
So while the library side of things may be more complicated in scala, (also type safe), the actually usage is no more complicated at all.

2010-09-24

follow it through to the end

Developers should follow a piece of business functionality through to the end.

Going through every stage of requirements, design, implementation, testing, delivery.
Whatever process you are using from waterfall to agile, it doesn't matter.

The alternative is technology silos where each developer is assigned their own section, which leads to the abdication of responsibility:
"I only did the EJB bit"
"I only deployed the service"
"I just installed the thing"
etc

with no one being responsible for actually solving the business problem.

I might actually understand what a monad is

Monads are NOT elephants.

Monads aren't burritos.

Monads aren't even bullets.

Monads might be some kind of factory.

But after reading jquery-is-a-monad, it became clear that describing what monads are like, is NOT as useful as describing what things are monads.

In order to make a useful monad metaphor, the reader must be familiar enough with the subject that it helps understand monads more, not just confuse the issue.

no one explains objects in this fashion, no one says "objects are like buses" or "objects are like straitjackets"

After reading jquery-is-a-monad I think I might actually understand what a monad is!

then I came across what-is-a-monad, which makes a LOT of sense;
but would it have if I hadn't read the above descriptions first?

practising what exactly?

I was just reading another of steveyegge's blog posts from 5 or so years ago
http://sites.google.com/site/steveyegge2/practicing-programming
and he's talking about practising-programming, in a similar way to many other blog posts have.

There's one point that is mentioned here, and other places too that I have to disagree with.
...merely doing your job every day doesn't qualify as real practice.
I think it actually depends on what exactly you're practising.
For example, are you practising programming in a language you already know?
If so, you could try different approaches, or libraries or something

One thing I try to 'practise'/study is learning new technologies (or languages).
I take different approaches to learning each new technology, and monitor how easy/hard it is.

I think that counts as practising as much as any deliberate exercise.

I guess it all depends on what your job actually is.
If your job is to pump out as much code as possible, then practising programming itself is probably a good idea.

But I view my job (as a software developer) differently.
For the most part, my job consists of learning a technology or language or program or system that I know nothing about, and configuring or programming or modifying in some way.

The key part is the learning.

I'm practising learning.

it's for reading text

I bought a kindle 2 a few months ago, and I've enjoyed reading books, papers, etc on it.
Almost everything has been in pdf form though,
and the pdf fonts are not always optimised for e-ink reading (actually never optimised).

Yesterday I wanted to read an interesting blog on it, so I dumped the text from the website into a text file and loaded it up on the kindle.

I'd forgotten how much better the built in fonts are on the kindle.

Since then I've been converting all my pdfs to mobi format using calibre.
It converts the text perfectly, and almost all the images. The formatting can be pretty skewed though, which sucks for long lines of code.

Still, it's a hell of a lot better than reading the pdfs directly.

2010-08-04

the unreadable book?

According to steve yegge no one can finish Gödel, Escher, Bach: An Eternal Golden Braid

I have.


It's pretty heavy going, and I'm not really a fan of the Achilles and the Tortoise dialogues.
But I did finish reading it.

I particularly enjoyed the section which described the function of DNA as a self replicating program.

2010-07-28

switching religions

Today, I switched religions.

I used to be a vim man, and now I use emacs.

That's right, I've changed my default text editor

pretty big news eh?

it is actually, as a basic text editor is something I use most of the day.
Which makes it one of my main tools.

At uni, everyone used vim.
And at work everyone used vi.
Then when we all started working on Java, we all started using eclipse, and defaulted to vi for basic duties.
These days, most people use either vim or notepad++, or something very close to notepad++.

In fact, I think I've only _met_ one person who used anything other than vi (or some basic windows text editor).

Yesterday I read a blog, and somehow it convinced me to change my default text editor, which has only happened once before (from vim to notepad++).

http://sites.google.com/site/steveyegge2/effective-emacs

Already, (after half a day) I'm finding some basic tasks easier or quicker.

I'm converted!

2010-06-02

java dead?

I don't think Java's dead


it's just dead boring

I can't not submit

There are times when I'm not allowed to submit.

I wish I'd made a branch to begin with

so I'm going to run my own subversion server on my local development machine.

visual SVN server

tortoise svn client

2010-06-01

Can you balance space and time?

The balance between space and time is still relevant:

http://blog.tmorris.net/you-lazy-thunk/

In scala, there's the lazy keyword which will make an assignment lazy.
But I didn't know of anything that would trade space for time, ie caching.

I was reading about clojure (lisp on the java) programming-clojure ,
and they mentioned the built in memoization http://en.wikipedia.org/wiki/Memoization

So I decided to do my own implementation of memoization in scala.
 
    def mem[A,R](func: A=>R) : A=>R = {
        var cache = Map[A,R]()

        (a:A) => {
            if (cache.contains(a)) {
                cache(a)
            } else {
                val result = func(a)
                cache += a -> result
                result
            }
        }
    }


    val double = (x:Int) => {

        println("double "+x)
        x*2 
    }

    double(2)
    double(2)

    val memDouble = mem(double)
   
memDouble(2)
   
memDouble(2)
   
memDouble(4)
   
memDouble(4)

when you run this in the repl you get:

scala> double(2)
double 2
res13: Int = 4

scala> double(2)
double 2
res13: Int = 4

scala> memDouble(2)
double 2
res9: Int = 4


scala> memDouble(2)
res10: Int = 4


scala> memDouble(2)
res10: Int = 4


scala> memDouble(4)
double 4
res11: Int = 8


scala> memDouble(4)
res12: Int = 8


as you can see from the repl output;
When you call double, it executes the body everytime you execute the function. ie it prints double 2 each time.
The memDouble function is different however, the first time you call the memDouble function, it prints, but the second time (with the same arguments), it just gives you the value.

Using this mem function, we can automagically cache the results of any function that takes a single argument.
In order for it to work with functions of any arity (number of arguments), we need to implement different versions for each arity.
We can then wrap those functions up in a singleton object, to hide the arity details.
Here I've done it for 1 and 2 argument functions, it's pretty easy to extrapolate. The key to the cache map becomes a tuple of the arguments.


object Mem {
    def mem1[A,R](func: A=>R) : A=>R = {
        var cache = Map[A,R]()
        (a:A) => {
            if (cache.contains(a)) {
                cache(a)
            } else {
                val result = func(a)
                cache += a -> result
                result
            }
        }
    }

    def mem2[A,B,R](func:(A,B)=>R) : (A,B)=>R = {
        var cache = Map[(A,B),R]()
        (a:A,b:B) => {
            if (cache.contains((a,b))) {
                cache((a,b))
            } else {
                val result = func(a,b)
                cache += (a,b) -> result
                result
            }
        }
    }
    ...

  
    def apply[A,R](func:A=>R) = mem1(func)
    def apply[A,B,R](func:(A,B)=>R) = mem2(func)

    ...
}

object Test extends Application {
    val mult = (x:Int,y:Int) => { println("mult"); x*y }
    val double = (x:Int) => { println("double"); mult(x,2) }
    val hello = (x:String) => { println("hello"); "hello "+x }
   
    val memDouble = Mem(double)
    memDouble(2)
    memDouble(2)
    memDouble(4)
    memDouble(4)
    memDouble(4)
   
    val memMult = Mem(mult)
    memMult(2,3)
    memMult(2,3)
    memMult(4,4)
    memMult(4,4)
   
    val memHello = Mem(hello)
    memHello("me")
    memHello("me")
   
    case class MyObj(val value:Int) {
        def multiply(x:Int) = x*value
    }
   
    val memMyTriple = Mem(MyObj(3).multiply(_:Int))
   
memMyTriple(2)
   
memMyTriple(2)
}


As you can see, it's not just for basic functions, it also works with methods on objects as well.

I've found these functional concepts fairly straightforward to implement in scala, the only issue being with different function arities.

This is an effective way to use space in order to save time, while leaving your source code relatively unaffected.

2010-05-26

The paradigmatic chasm between programmers and normal humans is huge.

I was just reading a blog entitled The Myth of the Super Programming Language and came across an astonishing comment; partially reproduced here, (as I can't link to the comment itself)

...
Here’s a case study. I once asked our secretary to backup our shared mini-computer in the morning, before the rest of the company showed up. I wrote down, on paper, a simple set of instructions, that covered every case I could think of. For example, I wrote down “Go to any terminal. If you see c:> on the screen [ed. i.e. a developer forgot to logout before going home the night before], type ‘logout’. When you see ‘login:’ type ‘operator’, and then when you see ‘password:’ type ‘yyy’. Then type ‘backup’.”
I came in one morning and found the following on EVERY screen in the office:
c:> logout
login: operator
password: yyy
c:> logout
login: operator
password: yyy
c:> logout
login: operator
password: yyy

I had to ask her why she did this – being a programmer, I couldn’t understand what was in her mind. It turned out that the concept of ’sequence’ was not bred into her thought process. In essence, she treated the instructions in a declarative, pattern-matching manner. After every action, she re-scanned the whole sheet of instructions and picked the closest match, instead of treating the instructions in a sequential manner as I had intended. Every time she successfully logged in as operator, the closest match on the sheet of instructions was “if you see C:>, type ‘logout’”, so she did that. Again and again.
The paradigmatic chasm between programmers and normal humans is huge. We can’t even recognize that programmable computers are a burden to the general population, not a boon.
What we need are programming languages that allow software engineers to produce products – encased in epoxy – that provide solutions to specific problems. Whether we choose to use programmable computers inside the epoxy is our own problem, not the customers’.

Wow.

I think I now understand how there is a market for apple products.

I truly never understood before.

2010-02-20

Disagree and agree so strongly

I watched a strange documentary type program recently:

zeitgeist

It goes into a lot of different ideas, about a whole heap of different (sometimes completely unrelated) ideas.

One thing that I liked in it was that there is some factual truth to the christian bible. That basis being that all of the stories and characters in it are direct representations of  astrological signs and their astronomical connections.

That was about it though.

duct tape programming

Everyone thinks it at one point, "It's ugly, but it will work" and the next though is "I'd like to make it better, but I don't have time right now".
Now it has a name: duct tape programming

It's always a trade off, between two extremes:
wasting time on something that already works
vs
writing something that will fall apart with the next modification (or in a different environment)

It's important to be aware of the decision you are making.

2010-01-19

How to quit smoking in one easy step

Just stop smoking.




But seriously, for those of use addicted to nicotine or just cigarettes in general; there is a practical way.

Electronic Cigarettes or e-cigs, or as they're called in europe, electro fags.
So we'll call them e-cigs.

Since I got my order, a couple of months ago, I haven't gone back.
I had a drag of a 'real' cigarette, and my reaction can only be described as "blehhhrrgg".

Please check the legality of purchasing and selling these products, where you live.
They are not legal to sell in australia at the moment, for some fucking retarded reason that escapes me at the moment.
But it is legal to import them (in small quantities) from overseas.

Now, the benefits:

  • Arguably a safe alternative to smoking.
  • Cheaper, by far. a 30ml bottle costs around $10 and lasts 2-3 cartons!
  • Lotsa different flavours. ie doesn't taste like shit.
  • Feels like smoking a cigarette,
  • No smoke to stink up any room you're in
  • No ash.
  • You can put it in your pocket after having a single drag.
  • You get to pretend that you're from the future with you're "usb powered, nicotine delivery system, with flashing lights, and delicious flavours"



The sucky bits:

  • It doesn't help quiting nicotine, in fact I probably have a higher intake now than before, which is because of all the above benefits.
  • Some maintenance of the device is required, basically just cleaning.
  • You'll need to recharge the batteries when they go flat, (just keep one on charge and swap them over)
  • doesn't really fit behind your ear (if you're into that kind of thing)
  • ordering from overseas, instead of visiting the local shop
  • exhaling in someone's face causes them to smile (smells nice) instead of making you look tough.



The links:
These parts are from the company I've been purchasing from (no kickbacks or anything).

  • here's the starter kit, which includes all the basic bits you need
  • You'll need some empty cartridges to fill up with the new flavours
  • then some nicotine juice, with many choices of flavours. My favorites are RY4#, watermelon, french pipe, apple, vanilla, menthol, grape and lychee
  • you'll need to replace the atomizer every 2-3 months or so, depending on use
  • There are also bigger batteries and chargers of various sorts.

I'll make another post at some point with more details on cleaning, and other tips.



boring code

Boring code really is the worst.


Please don't write boring code


am-i-being-boring



I wouldn't be surprised at all, if boring code caused bugs.

The most complicated guitar rig ever

I have a line6 variax 700 guitar, in black.
This is not a normal guitar, well it is, but it has extra bits. It can model other guitars, including 12 strings, acoustics, banjos, sitars etc.

It's awesome.

It has a normal guitar plug as well as a cat5 network connection ( audio, data and power).
Because it's partially digital, there are a LOT of routing options available.
I've gone with a setup, that while complicated, allows the maximum flexibility, and being-able-to-modify-things-later-ability as possible.
I plug the network cable from the variax into my bass podxt live. That plugs into my PC via usb, so that variax workbench can modify the guitar model and tuning in real time. I also take a direct line out of the podxt, that goes into my echo audio audiofire8 which connects to my PC via firewire, so that I can record a clean guitar channel.
I've setup direct monitoring of the clean guitar channel, that goes out to my tonePort DI-Gold, the tonePort connects to the PC via usb, to gearbox which controls the amp and effects modelling on the output of the tonePort. The effected/amp modelled sounds from the tonePort then goes back into the audiofire8, which is direct monitored out to my m-patch 2 volume control then out to my M1 mk2 monitors. On playback, the clean guitar is re-amped through the gearbox vst plugin, giving me complete control of the guitar sound, after recording.
Now that sounds like there's a LOT of connections and digital conversions and buffers, which usually means .... LATENCY.

but there's not.

Hardware monitoring accounts for the normal Analogue -> Digital conversion latency (due to buffering), which is done at multiple stages.
The other magic latency defeater is the hardware (rather than software) effect monitoring done by the tonePort.

You'd think that the multiple stages of analogue -> digital and back again would degrade the signal, and maybe it does to some degree; but I can't really hear any problem with the sound and more importantly the flexibility is worth it.

A friend of mine had a play with the variax through this setup, while I played around with the workshop and gearbox settings. He would start playing a particular style of music, and so I'd modify, in realtime, the sound of the guitar, amp and effects. A very short cut-out (with no digital artifacts) occurs when switching between different guitar/effect/amp models. We were switching between hendrix, metallica, country music, classical; then at one point I got the song wrong, and put the wrong sound on. It was instantly obvious that the sound was wrong for the song, which made me realise it was actually by a different band than I thought.
If I was recording the session, I could have re-done the amp and effect sounds, but the guitar sounds is fixed.

I've never before had that level of control, and power over the overall sound of a guitar, with that kind of immediacy. It really is amazing.

now, I just need to make some time to actually play the bloody thing ...