Life Codecs Ruminations. Reflections. Refractions. Code.

April 25, 2011

Mystery of Dinkle Berry

Filed under: general,gripe — Tags: , — Kamal Advani @ 23:04

Let’s edit this now1 force-footnote3.

“Dinkle Berry” is.. dinkle berry. A test user so abused in my test
data. Ah Dinkle Berry, where did your name come from?

I should google you, eh2?

Footnotes:

1yep, still messing with my blog to email thingie.

2ok, so I did google it… whatever you do, please ignore
urbandictionary’s
interpretation… it’s scary how I came up with that word
independently, and had no such mental association, kthnks.

33 6 edits now… textile support seems a bit.. flaky in Python.

April 23, 2011

Love Will Keep Us Alive

Filed under: software dev — Tags: , — Kamal Advani @ 22:45

Love Will Keep Us Alive1

I was standing
All alone against the world outside
You were searching
For a place to hide

Lost and lonely
Now you’ve given me the will to survive
When we’re hungry…love will keep us alive

Don’t you worry
Sometimes you’ve just gotta let it ride
The world is changing
Right before your eyes
Now I’ve found you
There’s no more emptiness inside
When we’re hungry…love will keep us alive

I would die for you
Climb the highest mountain
Baby, there’s nothing I wouldn’t do

I was standing
All alone against the world outside
You were searching
For a place to hide
Lost and lonely
Now you’ve given me the will to survive
When we’re hungry…love will keep us alive
When we’re hungry…love will keep us alive
When we’re hungry…love will keep us alive

1Of course, these are lyrics to the famous Eagles song. In the
context, I am messing with my
textile formatted
email to blog software.

September 20, 2010

A Tribute to Vajra

Filed under: general,personal,poetry — Tags: , , , — Kamal Advani @ 22:03

I just gave away my laptop of some 8 years. Its hostname was “vajra“, a Sanskrit multi-semantic word – some meanings rather less subtle than others, but that’s a tale for another rainy day. The meaning I first encountered for it however was ‘diamond’. That is the name I gave to it.

I do not know if I can confer this name on to an equally worthy machine in the future – whether I do, or do not – equality in this case will never replace Vajra’s intrinsic identity.

The Vajra that just left was truly a diamond, it stuck with me through thick and thin, all throughout my university and personal life – the whole of my time in Melbourne. A most resilient machine. It was sad seeing it go having been a significant part of my life for so long. Yet it is well that it went to someone who wanted to reuse it as a small mail server, as my main use for it has, sadly, since dissolved.

While a university student with a tight budget, it gave me no trouble. Many days it ran at least 10-15 hours a day, compiling code, browsing the net, playing music, yapping on IRC. It has been a companion for the longest time.

I remember that on the way to Melbourne, the first time, I managed to lose its original power adapter due to tardiness at the airport security check. I found an original, new, and cheap replacement not long after though. Truly it was Divine synchronicity. Even when I messed up, it remained kind to me.

2-3 years ago, the one thing that died was its hard drive. I replaced it the next day, and it was buzzing with life once more.

Vajra – a Compaq Presario 1700 AP – has the following featureset:

  • Pentium 3 (Coppermine), 750 MHz
  • 384 MB RAM
  • 110 GB HDD (the original was 40GB I believe)
  • NIC
  • Built-in (soft-)modem
  • Floppy drive-bay

It has accomodated several OS spirits during its time with me:

  • Linux: Mandrake, Redhat 7.2, Debian, and most recently Ubuntu Karmic
  • Windows: WinME, WinXP

I wish it well, and when the time comes – may its various elements evolve further: the minerals powering its chipsets, the metals of its frame, the luminous atoms of its LCD.

May the spirit of Vajra,
the diamond,
be forever.
In one form
or another.

April 5, 2010

Generics and Method Selection: A Backwards Compatibility Gotcha

Filed under: software dev — Tags: , , , — Kamal Advani @ 22:45

If you managed to read through the rather long post title… let’s move on to a much longer post.

I recently came across an interesting bug at work which was rather eye-opening on just how nasty backwards-compatibility (which prompted type erasure!) can be. Credits are due to my friend and colleague Marcus Hasslinger who reasoned through the issue with me from a backwards compatibility viewpoint.

Some background: we use Java 5 and EJB 3, we also make use of annotated methods that are inspected by custom EJB 3 interceptor(s). A sample EJB might implementation might be:

1
2
3
4
5
6
7
8
9
10
11
@Local
public interface Foo {
    void doSomething();
}

@Stateless
@Interceptors({TransactionHandlerInterceptor.class})
public class FooServiceImpl implements Foo {
    @RollbackWhen(...)
    public void doSomething() { /* ... */ }    
}

In the above, the interceptor (TransactionHandlerInterceptor) is an around-invoke type interceptor which intercepts doSomething(), reads the annotation on it (RollbackWhen) and decides some rollback logic.

The defect was that in a particular EJB, it would not detect the method as having this annotation, and thus the necessary rollback logic was never executed. Thus begins our saga. Rather than going through work artifacts (which I probably can’t show anyway) and bore you with our business domain, I’ll create an essentially similar example using the classic ‘Shape’ set of objects (I know.. I know…).

This particular EJB had the following structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// package foo
// Domain objects
public interface Shape {
}

public class Circle implements Shape {
}

// Services
public interface ShapeService<T extends Shape> {
    void draw(T shape);
}

@Local
public interface CircleService extends ShapeService<Circle> {
}

@Stateless
@Interceptors({TransactionHandlerInterceptor.class})
public class CircleServiceImpl implements CircleService {
    @Override
    @RollbackWhen(...)
    public void draw(final Circle shape) {
        System.out.println("Drawing circle");
    }
}

// Sample dumb, non-EJB client
public class Client {
    public static void main(final String[] args) {
        final CircleService circleService = new CircleServiceImpl();
        circleService.draw(new Circle());
    }
}

The issue was that whenever the interceptor intercepted CircleServiceImpl.draw(), it would not detect that it was annotated with @RollbackWhen. So I printed out the actual method.toString() output from within the interceptor – this turned out to be:

1
public void draw(Shape)

instead of the expected:

1
public void draw(Circle)

Obviously draw(Shape) is not annotated with @RollbackWhen, draw(Circle) is. Hmm. So where exactly does draw(Shape) come from though, we only ever implemented draw(Circle) in CircleServiceImpl. It’s time to look at type-erasure in action under the hood using ‘javap’ – a useful little bytecode disassembler that comes as part of the stock JDK. The following output was obtained by running ‘javap -c <classfiles…>’ (without the .class).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// javap -c Shape Circle ShapeService CircleService CircleServiceImpl Client
Compiled from "Shape.java"
public interface foo.Shape{
}

Compiled from "Circle.java"
public class foo.Circle extends java.lang.Object implements foo.Shape{
public foo.Circle();
  Code:
   0:   aload_0
   1:   invokespecial   #10; //Method java/lang/Object."<init>":()V
   4:   return

}

Compiled from "ShapeService.java"
public interface foo.ShapeService{
public abstract void draw(foo.Shape);

}

Compiled from "CircleService.java"
public interface foo.CircleService extends foo.ShapeService{
}

Compiled from "CircleServiceImpl.java"
public class foo.CircleServiceImpl extends java.lang.Object implements foo.CircleService{
public foo.CircleServiceImpl();
  Code:
   0:   aload_0
   1:   invokespecial   #10; //Method java/lang/Object."<init>":()V
   4:   return

public void draw(foo.Circle);
  Code:
   0:   getstatic       #18; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #24; //String Drawing circle
   5:   invokevirtual   #26; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return

public void draw(foo.Shape);
  Code:
   0:   aload_0
   1:   aload_1
   2:   checkcast       #35; //class foo/Circle
   5:   invokevirtual   #37; //Method draw:(Lfoo/Circle;)V
   8:   return

}

Compiled from "Client.java"
public class foo.Client extends java.lang.Object{
public foo.Client();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   new     #16; //class foo/CircleServiceImpl
   3:   dup
   4:   invokespecial   #18; //Method foo/CircleServiceImpl."<init>":()V
   7:   astore_1
   8:   aload_1
   9:   new     #19; //class foo/Circle
   12:  dup
   13:  invokespecial   #21; //Method foo/Circle."<init>":()V
   16:  invokeinterface #22,  2; //InterfaceMethod foo/CircleService.draw:(Lfoo/Shape;)V
   21:  return

Let’s start with the simple cases: Shape and Circle – Shape is a simple interface, all fine and dandy. Circle is a class implementing Shape, we can see the default constructor generated since we didn’t provide one of our own.

Next we look at ShapeService – a bit more interesting – it has an abstract method draw(Shape). Generics information is erased, there’s no ‘T’ anywhere. T is replaced by its upperbound, i.e. Shape. Thus the generated method too is draw(Shape). So far so good.

Moving on to CircleService – once more, the parameterisation is nowhere to be seen, there’s therefore no notion of Circle in CircleService, it simply extends ShapeService, and thus inherits the same method signature: draw(Shape). This is what got me – it of course, needs to be this way due to type erasure. You get the illusion of full type-safety, as if a new method draw(Circle) is automatically generated in CircleService – since after all, compile-time code completion, etc. in your IDE works just dandy on a reference of type CircleService – CircleService.draw(Circle) – never does it show CircleService.draw(Shape)!

Let’s move on further – things are getting more interesting. CircleServiceImpl has 2 overloaded methods, draw(Circle) which is our code converted to bytecode, and a compiler generated draw(Shape) – which casts (or at least does a cast-check – haven’t read the bytecode description) to ensure the supplied Shape is indeed a Circle, and then delegates on to our draw(Circle). Think about this for a moment – by itself, it’s just madness – but from a backwards compatibility viewpoint — 2 methods need to be there, our own draw(Circle) which as you can see, did not override any method in the interface as such(!), and draw(Shape) the compiler generated one – which is needed to satisfy the type-erased interfaces we implemented!

One final piece of the puzzle — client code: once more we see a default constructor is generated since we didn’t create one. And then the main() method which in fact calls draw(Shape), not draw(Circle). This is once more correct in a backwards-compatible-whacky way — as we saw above CircleService only ever had draw(Shape) — since we used the CircleService reference, that’s the method we got. And thus the implementation class needs to generate draw(Shape) and delegate to our draw(Circle).

In as far as our defect goes — this is exactly why it did not detect the annotation — it was intercepting the client-invoked, compiler-generated draw(Shape) which in turn invoked draw(Circle). draw(Circle) is of course an internal invocation, not accessed via the EJB proxy anymore, and hence never intercepted again.

Ah backwards compatibility.

That aside, there are a few observations to be made:

  • A generics call in the above fashion will always incur an additional cast check and method call, not a big deal for most code, but within a loop, etc. best to measure it. On the bright side, the checkcast is a single JVM instruction. Another optimisation – if you can even call it that! – is to explicitly declare a method draw(Circle) in CircleService – then it is generated as per normal, and client code goes directly to CircleServiceImpl.draw(Circle) – at this time, this is our workaround for the defect. I’ll leave the discussion of where the annotation should belong for another time (i.e. implementation class or interface – this is more a design principle/responsibility issue)
  • It’s interesting that specifically from an EJB 3 interception and transactional semantics viewpoint – this is quite nasty since you do not intercept a method that you think is part of your EJB interface, nor does the transactional semantics get applied (apart from the default ‘required’ of course)! I wonder if it might be better, if in an EJB 3 class, the generated draw(Shape) method did not do a plain invocation of draw(Circle), but accessed it via an internal EJB proxy reference (circleServiceEjbRef.draw(Circle)) – this would ensure proper transactional semantics and interception. Wait – the generated method in fact should not enforce any transaction type either — it should just be (if I recall correctly) using ‘supports’ semantics. As it stands, if draw(Circle) were annotated with a transaction attribute other than ‘required’ – this would not be picked up at all since it was a direct invocation, not via the EJB transactional proxy! Nasty, nasty! It could lead to some very obscure bugs!

Hmm.. I never remember reading about this in any generics book :P. Anyway, if you got this far, hope it was an informative read.

February 10, 2010

New Code: Groovy JSON Decoder/Parser

Filed under: software dev — Tags: , , , , — Kamal Advani @ 22:42

Finally got around to uploading this. Have not had time to make a proper public repository, doubt I will have time, so as usual, sources and tests are there to light the way!

January 27, 2010

fold / reduce

Filed under: how to,software dev — Tags: , , — Kamal Advani @ 01:51

Recently, I’ve been messing around with a fair bit of Groovy, a little bit of Scala, and a background-favourite (whatever that means), Python.

All 3 languages have functional traits, one functional idea is reduction where a collection of items is operated upon and finally reduced (hence the name) into a single value. From a practical viewpoint, this could be an overall analysis derived for all items in that collection – a sales percentage, a sum, or some other statistic. I am not a functional programming guru, so apologies for the rudimentary description. I was curious to see how each language handles it, and how I might write an implementation of reduce().

In particular I came across Scala’s List.foldLeft(). It also has a corresponding foldRight (and both functions have shorter operator notations :/ and :\ — which look like emoticons as I type this). Right and left determine where in the list it starts converging/reducing. Left starts from the start of the list (if you imagine the list horizontally rather than vertically, with the first/top most item on the left), while right starts at the bottom/end of the list. Depending on values in the list, and/or operations performed on them, the traversal order could obviously impact the result. Thus we note that fold-left and fold-right are basically types of reduce.

On to some code. I’ll keep it simple, albeit a little boring and predictable, the reduction will yield a sum of all elements in the list (yawn…). We’ll see some interesting properties of this simplicity however, and why it matters. I’ll start off with using the stock API for each language, and then roll my own. In all cases, essentially the following happens:

  • Decide on a collection of items (usually repeatably ordered!) to reduce
  • Apply the fold-left/reduce call which takes in an initial value to be used as we wish, in our case it will be a total result, initialised to zero
  • The fold-left/reduce call also takes a closure which is called for each item in the collection. The closure must return/yield a single value each time it is called (i.e. for each item in the collection), and takes 2 parameters, the running total and the current item being iterated over in the collection. I say ‘running total’ for our example, but more generally: for the first item in the collection, it is passed in our initial value, for subsequent items it is passed in the last ‘reduced’ value, i.e. the value that it yielded in the previous iteration.
  • A value is finally yielded and returned to the caller after the last item in the collection has been visited. In our case, the total.

Scala:

1
assert(List(1, 2, 3).foldLeft(0) { (total, item) => total + item } == 6)

Groovy:

1
2
3
4
5
6
7
assert [1, 2, 3].inject(0) { total, item -> total + item } == 6
/*
Note: inject() is on the (GDK) Collection supertype, java.lang.Collection.inject(), see:
http://groovy.codehaus.org/groovy-jdk/java/util/Collection.html#inject(java.lang.Object value, groovy.lang.Closure closure)
This is interesting, because a HashSet is a collection, and it's ordering is arbitrary, which means
you want to be careful if your collection is a Set, and your operation expects an ordering!
*/

Python:

1
2
# reduce(func, sequence, init)
assert reduce(lambda total, item: total + item, [1, 2, 3], 0) == 6

A Few Notes on Syntax (skip this section as needed):
For the Scala and Groovy versions, note the syntactic sugar, both inject() and foldLeft() are functions that take 2 parameters, the initial value and a closure. It’s just that the closure can be defined as if it is ‘attached’ or ‘hooked to’ to the function rather than passed in, rather nice. With Groovy, the closure arg has to be the last one to allow this syntax (otherwise you can pass it in ‘foo(“bar”, { /*closure */ }, “meow”)’ like a regular parameter. In Scala, it depends on how the closure parameter is defined – in the case of foldLeft it is in its own parameter list, and so is not part of the initial set of args. I’m still a Scala n00b however, so I’ll stop there!

The Python case looks a little funnier, I am using the lambda form to create a new anonymous function, I could have also defined a function in the scope, and passed its name in as the first argument. This would be needed if I had something more involved in the function which the lambda form could not accomodate or accomodated hell-ishly (its body has to be a single expression only, no statements). Python doesn’t support more complicated anonymous functions as a language construct (there are code-level hacks though).

Implementing fold-left:
Now let’s try re-implementing fold-left using Python for clarity. Python has the idea of ‘sequences’ – positionally-ordered collections (from Learning Python 3E) – lists, strings, and tuples. However I am not sure why there’s no specific ‘sequence’ type, because this would have allowed setting a foldLeft/reduce call on this supertype leading to a more OO feel where you could do sequence.foldLeft(…). Instead the approach is much more procedural as you saw above. I’ll stick to the procedural approach for my implementation so arbitrary sequences can be passed in generically. I have not had a look at the source code for foldLeft in the languages above, I shall soon, however here’s my go at it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def foldLeft(sequence, reducefunc, initval):
    if not sequence: return initval
    for i, item in enumerate(sequence):
        return foldLeft(sequence[i+1:], reducefunc, reducefunc(initval, item))

def foldLeftMutable(sequence, reducefunc, initval):
    if not sequence: return initval
    reduced = initval
    for item in sequence:
        reduced = reducefunc(reduced, item)
    return reduced
 
# Test it.  
adderfunc = lambda total, item: total+item
# immutable version    
assert foldLeft([1, 2, 3, 4, 5, 6], adderfunc, 0) == 21
assert foldLeft([], adderfunc, 0) == 0
assert foldLeft(None, adderfunc, 0) == 0
# mutable version
assert foldLeftMutable([1, 2, 3, 4, 5, 6], adderfunc, 0) == 21
assert foldLeftMutable([], adderfunc, 0) == 0
assert foldLeftMutable(None, adderfunc, 0) == 0

There are 2 versions of the fold-left functions above, foldLeft() and foldLeftMutable(). The latter holds mutable state, albeit localised to the function (the localvar reduced), so probably no big deal (considered a non-functional implementation though?). Both functions have O(N) complexity[1]. I initially thought I had something exponential for the recursive version, but then realised that I was returning at each iteration, phew! Of course, O(N) also assumes that reducefunc here is O(1)! foldLeft() though holds zero mutable state even within the function. The sequence is sliced resulting in a new sequence each time before the recursive call. This is probably overkill, resulting in new objects each time – but kinda cool anyway from an immutability viewpoint. Needless to say that immutability is based on the assumption that items in the sequence are also immutable, or if mutable, are not being messed around with by the passed in reducefunc argument (in this case adderfunc). But as far as the direct objects that foldLeft() deals with – the sequence, initval, and reducefunc – it in no way changes them.

foldLeft() is, however, I think tail-recursive (another thing I need to read up on!) so it could just be converted to a plain iterative version by the bytecode compiler which would result in something similar to foldLeftMutable(), any specific comments on this would be highly appreciated. Anyway, bed time.

Footnotes:
[1] I just realised that slicing the list to produce a new list is likely to be O(N) rather than a constant time operation, which would invalidate my claim that the recursive version is also O(N), grrrr. Now I really am off to sleep.

January 26, 2010

GNU Screen Config

Filed under: how to,software dev — Tags: , — Kamal Advani @ 22:39

I have been using GNU Screen – an awesome terminal multiplexer – casually for quite a while now, but never really customised it much, since I still use a fair bit of GUI applications, even if I do frequent the terminal a lot. Today however I bit the bullet and set up a Screen config, nothing fancy, just a set of terms initialised to stuff I often use with proper term titles (I know, how did I live without them… since I rarely turn off my computer it’s only an issue when I do, since otherwise my term stays on). For my reference, and in case someone finds it useful, here’s the contents of my ~/.screenrc file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Status line
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{=kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B}%Y-%m-%d %{W}%c %{g}]'

#
# Default screens
#

# Root shell
screen -t rootsh su

# Utility shells
screen -t sh1
screen -t sh2
screen -t sh3

# eclipse workspace shell
chdir ~/eclipse_workspaces
screen -t eclipsews

# interpreters
chdir ~
screen -t python2.6 python2.6
screen -t groovysh groovysh
screen -t scalash scala
screen -t js js

# books dir
chdir ~/documents/ebooks
screen -t ebooks

# tmp dir
chdir /tmp
screen -t tmp

# launcher shell to launch other gui programs
# allows all sorts of logging junk to stay in one shell
chdir ~
screen -t launchsh

The ‘hardstatus’ details are based on this Red Hat zine article on GNU screen. I have yet to look up in the man page what exactly each formatting code/escape strings mean, all I know is it’s a decent set-up :P.

Of course, you’ll need the relevant programs installed if you use this as is – I just need my interpreter shells running to test snippets of code in different programming languages. You can also do stuff like set-up ssh sessions, send commands to running screens – almost collaborative – haven’t explored this much.

August 17, 2009

Groovy Closure and Its Execution Context

Filed under: software dev — Tags: , , , , — Kamal Advani @ 03:17

I’ve been messing with Groovy – truly – the name aside – it is groovy, and I am impressed.

At some point I’ll say more about it, or dump out various code snippets I’ve been experimenting with to learn it, but for now I wanted to ensure I have this snippet recorded for reference – it is on closures and their context in Groovy. It took me a while to get it. It is always interesting how closures are defined within the context (no pun intended) of the JVM, where functions are not first-class types.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*
 * For a closure: basically local vars are the ones passed in {x,y,z -> blah}, everything
 * else is picked up and searched for from the execution context. Internally generated as
 * innerclasses with a supplied context consisting of 'this', owner, and delegate (the
 * internal Groovy closure base type is: groovy.lang.Closure -- see its Javadoc, this is
 * what closure blocks get translated to).
 *
 * Method/property resolution order for unqualified methods within a closure is in the
 * following order (and defined by the following context vars available to the closure):
 *
 * 1. this -- execution context - object to which the closure is first bound, e.g. script
 *    or class where defined, NOT the closure instance itself!
 *    
 * 2. owner -- usually equal to this, except when a closure (itself implemented as an
 *    innerclass) then creates an inner closure, that inner closure's 'this' is the outer
 *    closure instance. So that's one way to get access to a closure itself - create a
 *    subclosure and mess with it's 'this'!
 *    
 * 3. delegate -- usually set to owner, but can be modified (others are fixed), for
 *    metaprogramming purposes
 *
 * For better illustration check the following snippet
 */

enclosingInstance = this
outerclosure = {
    // by default, 'this' is always execution context (object enclosing the closure), never this
    // closure instance (which is implemented as groovy.lang.Closure (.doCall))
    assert this == enclosingInstance
    // And so is owner
    assert owner == this
    // this.owner throws a MissingPropertyException, since the outer script has no 'owner' property,
    // and 'this' is the outer script, not the closure instance!
    // But if the closure (outerclosure) creates another closure like so...
    innerclosure = { return this; }
    // The inner closure's owner is the outer closure instance!
    assert innerclosure.owner == outerclosure
    // However the inner closure's 'this' (returned) is still the initial enclosing instance, not the
    // outer closure.
    // Not quite sure if this is intuitive, hmm.
    assert innerclosure() == enclosingInstance
}
// run it!
outerclosure()
// check out it's superclass -- groovy.lang.Closure
println "superclass type: "+outerclosure.getClass().superclass
// done.

Type that out into some file say Foo.groovy and run it (yes you don’t need a static main() method in an enclosing public class with the same filename). The example is focussed on context, it does not provide samples of parameterised closures, or even parameterless ones (technically the closure above has one default parameter called ‘it’ which is null unless otherwise set in the call to the closure :P).

May 5, 2009

New Code: FormGen

Filed under: software dev — Tags: , — Kamal Advani @ 01:36

Just wrote and uploaded FormGen, a quick and dirty HTML form generator, in the code section. Haven’t uploaded sources yet though. Check it out!

April 28, 2009

Bad Browser Haiku

Filed under: poetry — Tags: , , — Kamal Advani @ 01:53

Yes, I have nothing better to do. Enjoy the following haiku, which is potentially a pseudo-ku (not to be confused with Sudoku – gosh I am funny :P!), though I tried to stick to the rules and spirit of it.

1
2
3
Fox on fire, why, how.
Script gone rogue, Face... book, so cold.
Kill... the tab. Okay.

Yes, poetry is like code, and vice versa ;-).

Older Posts »

Powered by WordPress