Launching Ragnarok Code

It’s my new website! Visit it at http://ragnarokcode.com.

For some time now, I’ve been stagnating in terms of writing code. My day job usually provides me with ideas for post material. The thing is, much of the code, concepts and business logic is proprietary and confidential. So the material’s fairly mangled to unrecognisable pieces before it’s seriously considered for publishing.

I’ve also noticed that my articles are starting to lean towards the theoretical, and not enough practical ones. Practical referring to code, and trying out new concepts, and testing new technology. Besides, I’m starting to bore even myself…

Thinking hard, I came up with the answer. Do my own thing and write code! But I need some purpose. It’s fine and dandy to just write code, but without any purpose, the motivation to write code dies quickly.

My considerations:

  • Show my work
  • Current interests in C# and ASP.NET
  • Love simulations

So I’ve decided to launch a new website, running on .NET. I’ll be able to fulfil the first 2 at one go. The simulations thing will probably be a Windows application, powered by DirectX (or XNA?) for graphics. I’ve got water surface simulations, particles affected by “gravity” fields and so on in mind. I can create the simulations, and make them available for download, maybe even the code (once I make it presentable).

Do you know what’s the hardest part? Coming up with a domain name. I thought through a few, and discarded them one by one. I finally decided on one, but it was taken (expired, but still renewable by the owner).

It’s gone on for a few days, with the search for the perfect domain name and the perfect ASP.NET web host. It started to drive me crazy. Until something inside of me screamed “Stop this!”. And I made a decision, and bought a hosting package and registered the domain name “ragnarokcode.com”.

After I registered the domain name, I realised a fatal mistake. I’m not going to rank well for the word “ragnarok” due to a popular game Ragnarok Online. Totally forgot about it. Eeesshh… It’s fine, since I plan on using the website like a test bed for concepts.

So right now, I’ve only got an implementation of reverse polish notation on the site. What it means is, you can type “2 + 6 / 3” and get “4” as an answer. Hardly noteworthy, since you can write that in code and get an answer anyway. Until you realise that to evaluate a new expression “4 – sin(pi/2)”, you have to recompile your code.

This type of dynamic evaluation requires dealing with the symbolic meaning of the terms in the expression (symbolic computing?). There’s this software called Mathematica, which I used in my university days. My implementation just scratches the surface of what’s achievable.

Because I want exceptions to fail silently, that even if the expression doesn’t make sense, every best effort was made to evaluate the given expression. Which gave surprising results when I tested my own creation. Did you know “love + hate” has a numerical answer? *smile*

So here’s the link again: http://ragnarokcode.com. Have fun!

Never incorrect

My friend approached me for help today.

“What does ‘He will never be incorrect‘ mean?” he asked.

The genius logician that I am, I answered “He will always be correct”. My friend gave me a puzzled look. Then I translated the answer into Chinese, because he’s more familiar with Chinese than English.

It took a while, but he finally got it.

Use “positive” words whenever possible. Even words such as “reckless” can be considered “positive”, in the sense that it’s opposed to “incautious”, a direct negation of “cautious”.

This applies to writing code too. Don’t expect the next programmer who reads your code to be an expert logician. Nor a philosopher.

I hate writing about double negatives… I always end up focusing on negatives myself…

From dilemma to tragedy

In game theory, there’s an interesting problem called the prisoner’s dilemma. There were these 2 prisoners who were accomplices in a crime, but they didn’t know each other prior to the crime. They’ve been caught, and were individually questioned. Assuming no social consequences nor retributions, each prisoner was asked to confess to the crime.

If prisoner A confessed, but prisoner B kept quiet, A was let go and B was to take the full blame (and vice versa). If both confessed, both gets jailed, but less than if a single prisoner took the fall. Now, if both kept quiet, both still gets jailed, but for a significantly less amount of time than the previous situation.

Prisoner hands by Andrejs Zemdega
[image by Andrejs Zemdega]

The action “keeping quiet” corresponds to “cooperate”. The action “confess” corresponds to “defect”.

When I first learned of the concept, it was in the form of rewards, as opposed to punishment above. So here’s a table where the values correspond to rewards.

  A cooperate A defect
B cooperate A gets 0.8
B gets 0.8
A gets 1.0
B gets 0.0
B defect A gets 0.0
B gets 1.0
A gets 0.2
B gets 0.2

[the table might look a bit crushed together if you’re reading in a feed reader]

I made up the values. They’re meant to illustrate the disparity between the cases. You might also have heard of other versions of the prisoner’s dilemma. I want to highlight the part where both prisoners benefit more from cooperation than defection. The special case is if one chose to defect and the other chose to cooperate. But cooperative benefits are higher than an individual benefit.

When total selfishness comes into play, the selfish individual achieves the optimal benefit. But the optimal benefit isn’t much higher than the cooperative benefit. Being even a little less selfish creates a better outcome for all.

Now compare this with tragedy of the commons. A group of people have a shared finite resource. When everyone cooperates by taking only their fair share, all is well. When one person selfishly takes more than his fair share, the group on the whole suffers.

Since there’s no real incentive to be selfless at that point, more people might start taking more (defecting). And suddenly the finite resource gets abused and becomes useless.

For example, carbon footprints. Everyone wants to be environmentally friendly. When someone thinks there’s enough clean air for everybody, he might selfishly decide to up the noxious gas output (as a means of upping his profit too). If it comes to a “every man for himself” situation, the planet is going to be in deep trouble.

Economically speaking, there isn’t much relation between the prisoner’s dilemma and the tragedy of the commons. Socially speaking, in particular selflessness and care for the common good, the latter is a scaled up version of the former.

With the rise of social media and software tools to connect people, I find the relation between the two concepts interesting. Let me know what you think.

Generation Y programmers

I guess I could be labelled as old-fashioned. I grew up knowing DOS and remembered being ecstatic over typing something on the command line and getting an output. When I was in university, Netscape was the browser, I used the vi editor to code on Unix, and Neopets and ICQ were the rage.

I’ve seen some truly horrendous applications. Truly and totally ugly interfaces. I’ve dealt with Delphi and PowerBuilder legacy applications, and had maintained my fair share of web applications. Sometimes, the user experience in those applications were downright hostile.

So when I read this article mentioning the younger workforce, I was stunned by this:

Will Generation Y, who is accustomed to Facebook Applications, Google Docs, Rich internet application interfaces, and advanced web technology (all public) be shocked to find out how bad your enterprise software is?

I’m still reeling from the implications…

Some of my users are, shall we say, sheltered from all the bling on the Internet nowadays. They are quite content to accept some of the user interface inconsistencies. Roundabout and duplicate methods of getting things done pop up, yet they are unfazed by the inconvenience.

How will the younger generation of programmers react to this? They’ve seen all the slick interfaces. How will companies react to them? Companies might be very attached to their legacy applications.

Hip young programmers. Hideous user interfaces. Hmm… Either the programmers spruce up applications from inside the companies, or companies stifle their energy, their passion with corporate rules.

Or maybe something fantastic will come out of this. What do you think?

Game programmer? Need math

I read this article on video game degrees and I felt like “Finally! Someone who got what I’m trying to do here!”. I didn’t know the United Kingdom is so supportive of video game productions. They need mathematicians and computer scientists huh?

What happened to great programming skills, you ask? “I can tell the difference between an ‘is a’ and ‘has a’ relationship in object oriented programming!”

Programming skills are still needed. We’re just talking about complementary skills to that coding ability. Math course too difficult? Well, it’s difficult for a reason.

Computational science approach to programming

Sometimes, I wondered why people write code in a certain way, usually inefficient, lengthy or just plain weird. There’s a classic

int i;
char c[3];
i = 0;
c[i++] = 'a';
c[i++] = 'b';
c[i++] = 'c';

when

char c[3];
c[0] = 'a';
c[1] = 'b';
c[2] = 'c';

works just as well, and more readable. Perhaps they thought, “Hey there’s an array! Must iterate something!”. They didn’t give any thought to why the array was used in the first place.

And so I had a theory. What if they were so engrossed in the intricacies of the programming language, that they’ve lost sight of the problem they were trying to solve?

Which brings me to computational science. I gave a short explanation at the start of another article, but it didn’t do justice to it. You might want to check out the differences between computational science and computer science as described by Wikipedia.

I majored in computational science and applied mathematics. What happened was that I’d be given a problem (usually scientific or math based), and I’d have to solve it. Calculations by hand on paper were done. After the theory of the solution was understood, and practical use (with physically calculations) were done, it’s time to scale up by coding the solution method.

For example, Gaussian elimination on matrices. It’s used to solve a system of linear equations, where the coefficients in the equations were used to form the matrices. Coefficients are just the number in front of the (math) variable. So in the equation
2x + 5y = 7
the coefficient of x is 2.

The theory was taught and calculations were done by hand on small matrices. I worked on 2 by 3, 3 by 4 and even 4 by 5 matrices. One small slip in entering figures into the calculator, and I’d have to start all over again.

Then I had to implement the method in code. To do that, I needed to understand the theory and the solution behind the method. I did calculations by hand, so I knew the pain. And then I wrote the code. The problem given was to solve a 100 by 101 matrix. It’d probably take a whole night to do by hand. Assuming I don’t punch the wrong numbers on the calculator or read the wrong figures. The computer probably took only a few seconds.

And I believe that is what’s really behind computational science. My studies taught me to solve problems first. If the solution benefit from the calculation speed of computers and ease of repetitiveness with computers (which is usually the case), then it’s go ahead and write the code to implement the solution.

A programmer could agonise over the implementation of some feature, without thinking if that feature could be solved in another way, an easier-to-implement way.

For example, the programmer could be frustrated by the tedium of retrieving values from the database, adding them up with intermediate variables in code, and then storing them back into the database. It’s very painful to do that in C (I know, I’ve seen it). Did it ever occur to the programmer that he could just do the summation and store the sum entirely within the database environment?

All he needed was to write code to execute a SQL statement or stored procedure. Which is much simpler than keeping track of temporary variables, worrying about floating point errors and hold database records in memory for looping.

And that’s how I write code, the computational science approach to programming. Think about the problem, solve the actual problem, then use the computer’s capabilities to scale the solution.

You just need to know enough to maintain code

When I was in university, every homework program was written fresh. There was no maintenance; the code was as new as definitions allow. For every problem, I read through the math or science (or common sense in some cases) required, thought up the logic, and proceeded to write the code.

Since copying was generally frowned upon, when helping fellow students, I had to come up with explanations that they understood, sometimes even coming up with new code.

When I first joined the workforce as a professional, all that changed. I was introduced to numerous programs and scripts, each with hundreds of lines of code. Each program was filled with business logic that was partly stored in documentation and partly stored in the heads of my colleagues and manager.

And I didn’t write a single line of that code.

The programs and scripts were run on a monthly basis, and generated lots of output reports. So the first order of things was to learn the broad idea of the whole system. That was over in, I don’t know, a few days?

Next came supporting the users. I had to look at reports and make sure the relevant numbers tally. I was dealing with financial data, so if there was a difference of even 0.01 cent, I needed to know and correct the error before the users look at the reports (there’s still enough time buffer).

The programs dealt with massive amounts of data. I’m talking millions of database records. Sometimes, something fails. I get to be the one being paged (yes, the pager was still around then) by the operators on shift duty. A few Saturdays and Sundays were spent at the office looking at data files, scrolling through lines of code and doing update statements in the database for correction.

As each month went by, my familiarity with the programs and business logic grew. I reached a point where I no longer needed to be hand-held by my then mentor colleague. Occasionally, I still ask for help, but I was trusted enough to maintain the code myself. Which was fortunate, because there was a new project then, and my manager and colleague were full into the meetings and request evaluations.

There were support calls to answer and user requests to fulfil. The new project required new programs to be written, and involved changes to existing programs. It was at this point that I learnt something due to task and time management.

I didn’t need to know everything about my existing programs to make useful changes.

The new project, new business rules, new code to be written, and support calls from users and operators, forced me to be effective in identifying lines of code for change, for maintenance or for correction. I didn’t have to be familiar with every program, every line of code, every nuance of business rules to do maintenance work. I just needed to know enough.

That required that I understand the code as was understood by the original coder. To the point where I not only know where to look, and also where not to look.

You must understand that when companies hire you, they want you to become productive as soon as possible. Spending months understanding framework code and business logic while you basically did nothing useful is a waste of resources. It’s not full understanding and then start being useful. It’s incremental steps to understanding and small increases to productivity, back and forth, in a cycle.

So what’s the takeaway lesson for you? Don’t get bogged down in the immensity of the code you’re facing and maintaining.

Floating point errors – Sine X Taylor series

Stop rolling your eyes. I actually have a point to make, and the Taylor series (from math) is the best candidate to illustrate it. Think of it as expanding your education.

In simple terms, the Taylor series is a polynomial approximating another function. For example, the Taylor series for the trigonometry function sin(x) is
x – x^3/3! + x^5/5! – x^7/7! …
(x^3 means x to the power of 3, or x*x*x. 5! means 5 factorial, or 1*2*3*4*5)

As you can see, the series is infinite. You’ll also note that if you leave only the first term, sin(x) = x. Remember my warning about the pitfall.

So, that’s about all the math knowledge you need. That was easy, right? Our problem is in calculating that series. Suppose you don’t have a math library in your code base, then you’ll need to resort to the Taylor series to help approximate the sine function.

In an ideal world, the math logic you implement in code will evaluate exactly in value. Because of the finiteness of representing numbers in computers, you will get an approximate answer. And it’s more “approximaty” if you come up with the wrong algorithm for implementation too.

Note that factorial values can grow very big. 12! is 479001600, which is the limit for a 32-bit integer (13! is 6227020800, exceeding 2147483648 = 2^31). Suppose we want to stick to 32-bit integer variables, then this means the Taylor series for sin(x) can only go up to
x – x^3/3! + x^5/5! – x^7/7! + x^9/9! – x^11/11!

6 terms only. It doesn’t feel very accurate… What if we could “remove” the factorial? Note that
x^5/5! = x/1 * x/2 * x/3 * x/4 * x/5
Then we could have more terms when we reduce the factorials into floating point values.

And I’m going to let you in on another secret. The direction in which you add the terms together yields different results! So your calculation for
x – x^3/3! + x^5/5! – x^7/7! + x^9/9! – x^11/11!
gives a slightly different answer for
– x^11/11! + x^9/9! – x^7/7! + x^5/5! – x^3/3! + x

This happens because of the limitation of the variable type you use to store intermediate results. Generally speaking, you should start with the smallest intermediate values and work your way up. So this:
– x^11/11! + x^9/9! – x^7/7! + x^5/5! – x^3/3! + x
is preferred. The factorial in the denominator increases faster than the exponential in the numerator, so higher order terms are smaller in value.

In a following code sample, I’ve labelled sections A, B, C, D, E, and F.

Sections A, C and E contain code where the for loops are in ascending order. Sections B, D and F contain code where the for loops are in descending order.

Sections A and B form the pair where the float variable type is used to store intermediate values.

Sections C and D form the pair where the double variable type is used.

Sections E and F still use the double variable type, and the implementation logic for x^n/n! is do x^n and n! separately, then divide x^n by n!. This reduces the number of floating point operations (by about half actually), and so reduces the calculation errors.

Because of the use of factorial, we’ll use a long (a 64-bit integer in C# and appropriate operating system) which has more capacity to store the intermediate factorial value.

We’ll be calculating sin(PI), so the Taylor series is
PI – PI^3/3! + PI^5/5! – …

Alright, a short lesson in math. Odd numbers can be represented in the form of (2n + 1), where n is an integer. Hence this part of the code

k = 2 * i + 1;

And this part does the alternating minus and plus sign of the series

if (i % 2 == 1) fBuffer = -fBuffer;

And here’s the code:

const int cnTerms = 9;
float floatx = (float)Math.PI;
double doublex = Math.PI;
float fAsc, fDesc, fBuffer;
double fAscInDouble, fDescInDouble, fBufferInDouble;
double fAscAlt, fDescAlt;
long iBuffer;
int i, j, k;
StreamWriter sw = new StreamWriter("taylorsinepi.txt");

fAsc = 0.0f;
for (i = 0; i < cnTerms; ++i)
{
	k = 2 * i + 1;
	fBuffer = 1.0f;
	for (j = 0; j < k; ++j)
	{
		fBuffer *= floatx / (float)(j + 1);
	}
	if (i % 2 == 1) fBuffer = -fBuffer;
	fAsc += fBuffer;
	sw.WriteLine("A {0,0:d2} {1,0:f8}", i, fBuffer);
}
sw.WriteLine();

fDesc = 0.0f;
for (i = cnTerms - 1; i >= 0; ----i)
{
	k = 2 * i + 1;
	fBuffer = 1.0f;
	for (j = k - 1; j >= 0; ----j)
	{
		fBuffer *= floatx / (float)(j + 1);
	}
	if (i % 2 == 1) fBuffer = -fBuffer;
	fDesc += fBuffer;
	sw.WriteLine("B {0,0:d2} {1,0:f8}", i, fBuffer);
}
sw.WriteLine();

fAscInDouble = 0.0;
for (i = 0; i < cnTerms; ++i)
{
	k = 2 * i + 1;
	fBufferInDouble = 1.0;
	for (j = 0; j < k; ++j)
	{
		fBufferInDouble *= doublex / (double)(j + 1);
	}
	if (i % 2 == 1) fBufferInDouble = -fBufferInDouble;
	fAscInDouble += fBufferInDouble;
	sw.WriteLine("C {0,0:d2} {1,0:f16}", i, fBufferInDouble);
}
sw.WriteLine();

fDescInDouble = 0.0;
for (i = cnTerms - 1; i >= 0; ----i)
{
	k = 2 * i + 1;
	fBufferInDouble = 1.0;
	for (j = k - 1; j >= 0; ----j)
	{
		fBufferInDouble *= doublex / (double)(j + 1);
	}
	if (i % 2 == 1) fBufferInDouble = -fBufferInDouble;
	fDescInDouble += fBufferInDouble;
	sw.WriteLine("D {0,0:d2} {1,0:f16}", i, fBufferInDouble);
}
sw.WriteLine();

fAscAlt = 0.0;
for (i = 0; i < cnTerms; ++i)
{
	k = 2 * i + 1;
	fBufferInDouble = 1.0;
	iBuffer = 1;
	for (j = 0; j < k; ++j)
	{
		fBufferInDouble *= doublex;
		iBuffer *= (j + 1);
	}
	if (i % 2 == 1) fBufferInDouble = -fBufferInDouble;
	fAscAlt += (fBufferInDouble / (double)iBuffer);
	sw.WriteLine("E {0,0:d2} {1,0:f16}", i, fBufferInDouble);
}
sw.WriteLine();

fDescAlt = 0.0;
for (i = cnTerms - 1; i >= 0; ----i)
{
	k = 2 * i + 1;
	fBufferInDouble = 1.0;
	iBuffer = 1;
	for (j = k - 1; j >= 0; ----j)
	{
		fBufferInDouble *= doublex;
		iBuffer *= (j + 1);
	}
	if (i % 2 == 1) fBufferInDouble = -fBufferInDouble;
	fDescAlt += (fBufferInDouble / (double)iBuffer);
	sw.WriteLine("F {0,0:d2} {1,0:f16}", i, fBufferInDouble);
}
sw.WriteLine();

sw.WriteLine("ASC     : {0}", fAsc.ToString("f16"));
sw.WriteLine("DESC    : {0}", fDesc.ToString("f16"));
sw.WriteLine("ASC   x2: {0}", fAscInDouble.ToString("f16"));
sw.WriteLine("DESC  x2: {0}", fDescInDouble.ToString("f16"));
sw.WriteLine("ASC  ALT: {0}", fAscAlt.ToString("f16"));
sw.WriteLine("DESC ALT: {0}", fDescAlt.ToString("f16"));

sw.Close();

And this is the output:

A 00 3.14159300
A 01 -5.16771300
A 02 2.55016400
A 03 -0.59926460
A 04 0.08214591
A 05 -0.00737043
A 06 0.00046630
A 07 -0.00002192
A 08 0.00000080

B 08 0.00000080
B 07 -0.00002192
B 06 0.00046630
B 05 -0.00737043
B 04 0.08214591
B 03 -0.59926460
B 02 2.55016400
B 01 -5.16771300
B 00 3.14159300

C 00 3.1415926535897900
C 01 -5.1677127800499700
C 02 2.5501640398773500
C 03 -0.5992645293207920
C 04 0.0821458866111282
C 05 -0.0073704309457144
C 06 0.0004663028057676
C 07 -0.0000219153534478
C 08 0.0000007952054001

D 08 0.0000007952054001
D 07 -0.0000219153534478
D 06 0.0004663028057676
D 05 -0.0073704309457144
D 04 0.0821458866111282
D 03 -0.5992645293207920
D 02 2.5501640398773400
D 01 -5.1677127800499700
D 00 3.1415926535897900

E 00 3.1415926535897900
E 01 -31.0062766802998000
E 02 306.0196847852810000
E 03 -3020.2932277767900000
E 04 29809.0993334462000000
E 05 -294204.0179738900000000
E 06 2903677.2706132800000000
E 07 -28658145.9693880000000000
E 08 282844563.5865330000000000

F 08 282844563.5865330000000000
F 07 -28658145.9693880000000000
F 06 2903677.2706132800000000
F 05 -294204.0179738900000000
F 04 29809.0993334462000000
F 03 -3020.2932277767900000
F 02 306.0196847852810000
F 01 -31.0062766802998000
F 00 3.1415926535897900

ASC     : -0.0000000102118100
DESC    : 0.0000000000000000
ASC   x2: 0.0000000224195107
DESC  x2: 0.0000000224195102
ASC  ALT: 0.0000000224195103
DESC ALT: 0.0000000224195102

I’ve printed the intermediate values for better comparison. And it looks beautiful that the section pairs appear symmetrical. So let’s see the first pair of results.
-0.0000000102118100 versus 0.0000000000000000

That don’t look very equal to me. I don’t know why we got zero for the second one (maybe the alternating sign code is wrong). I mean the correct answer is zero, just that it shouldn’t be from an approximation algorithm…

Anyway, the next pair looks promising:
0.0000000224195107 versus 0.0000000224195102
Except the last digit.

The last pair has different last digits too.

So what have we learnt? Use the correct variable type. And come up with a good algorithm. The most accurate variable type can’t save you if your algorithm is faulty. Change the cnTerms constant to something else, like 8 (which gives a more believable disparity for the first pair), to get a feel of the algorithm, code and results.

For your information, sin(PI) is zero, which is the value the algorithms are iteratively approaching.

A dragonfly skimming water surface

Concerned I am.

From my own adventures in this thing people call blogging, certain advice given I was.

  • Write compelling headlines (because people can’t be bothered to read anything more)
  • Use lists (because people can’t be bothered to read anything more)
  • Use images to break up text (because people can’t be bothered to read anything more)

I’ve read of students multitasking, of students surfing the Internet, doing homework for other classes, uploading pictures to Facebook, and doing shopping at eBay, all during lecture time. Sure the professor may really be boring, but still, have they done anything at all? Were they that pressed for time?

Imagination

There was a time in the past when informercials just came out, and I saw this speed reading package and thought, “How cool is that!”. After some deliberation, I bought it. I read through the instructions, I listened to the audio, and some time thereafter, decided that being able to boast to my friends that I could read at cheetah speeds was not worth it.

I’m a visual person. When I read, I conjure up images, scenes and even sounds to accompany the words. The product promised that I could still read at lower speeds for leisure, but that’s not the point. Even for deep reading and thinking stuff, such as study material, I need that imagery. It’s how I learn and recall. Sprinting through words rob me of that.

That student situation was supposedly a normal occurrence in America. People talk of information overload, and not just in America. There seems to be pressure to keep up with what’s going on. In the world, on the streets, about your friends. There’s the feeling of being left out if you’re not connected to the Internet somehow. This video of the Twitter Whore (her words, not mine) exemplifies this extreme case.

Concerned I am. Are people losing the ability to slow down, ponder and think deep?

Don’t need to think

I came across this article by Nicholas Carr: Is Google Making Us Stupid? He talked of the Internet and search engines combining to provide instant gratification. Instant answers, quick news bites, skim, click, easily distracted, skim, click.

The search engine had given rise to a problem in programming forums. People couldn’t find the code to their problem with search engines, so they turned to programming forums. The thing was, they asked their questions in exactly the same way. They posted their question and expected an answer with no effort on their part.

Code answers can only be copied and pasted up to a certain extent. Sooner or later, you’ll find yourself in a situation where you have to come up with something unique. On your own.

Yes, you can piece something together from different parts (which is part of what this site’s about). But you have to come up with that idea that pieces together separate code solutions into a solution for your problem. That idea has to come from you.

The Internet is a vast repository of information. Search engines provide an easy way to sift through that and come up with something, hopefully the answer. But the information comes from people, not computers. People who’ve thought, researched, analysed and then published that information.

Being able to “plug in” to the Internet’s wealth of knowledge can be empowering, akin to maybe the hive mind of bees. Perhaps some individuals find their own lives minuscule, and possibly unbearable. And only when they’re awash in the presence of, and illusionary omniscience of the Internet, do they find peace.

Which reminds me of a scene in the latest Indiana Jones movie, the one with the crystal skull. That agent of the Soviet Union, Irina Spalko, wanted to know everything. Her wish was granted. I find the part where she was begging “please, no more!” just a little amusing. Knowledge has to be acquired through one’s efforts (thinking, experimenting), and not just given.

Carr also said it’s unsettling about Google’s

easy assumption that we’d all “be better off” if our brains were supplemented, or even replaced, by an artificial intelligence

People complain about their jobs being outsourced to other countries, but they don’t find anything wrong with the idea of their thinking being outsourced?

Words and imagery

I’ve also read about print advertisements, and how they still work better than television advertisements. Print ads, such as those in newspapers and magazines, consist primarily of words. Print ads, surrounded by the context in which they’re read, require readers to come up with images, sounds and feelings to accompany those words. In contrast, television ads already came up with the imagery for the viewer.

Of course, print ads require more effort to capture the attention of the reader, but the effect is more lasting, because the reader comes up with his own version of how the product can make his life better. Television ads require little imagination from the viewer, less engagement from the viewer, and hence less attention. In the words of Carr,

In the quiet spaces opened up by the sustained, undistracted reading of a book, or by any other act of contemplation, for that matter, we make our own associations, draw our own inferences and analogies, foster our own ideas.

The dragonfly

The Chinese have this phrase, “qing ting dian shui“. It literally translates to “dragonfly touch water”. The full description should probably be “dragonfly skimming over water surface and lightly touching it (from time to time)”. Sometimes, I’m amazed at how Chinese characters squeeze so much meaning into them.

It’s usually in reference to a martial artist, being so skilful in his art, that he can lighten his body to the point where he can run on water, gently touching the surface on each step. Like a dragonfly.

Are people becoming dragonflies? Do they think skimming material, lightly grabbing news bites, flitting from hyperlink to hyperlink, of being hyper-connected, will help them in coping with information overload, of being in the information age? Are we losing the ability to do deep reading and thinking, to contemplate and reflect?

Concerned I am. Because dragonflies, in their adult stage, live only up to about 4 months.

Conversation with a blog

Blog: You’re staring at me again.
Me: What?
Blog: You’ve been staring at me for 15 minutes now. Got the writer’s block, huh?
Me: I’m thinking, ok? … What’s it to you anyway?
Blog: It’s just painful watching you type a few words, stare, type a bit, delete, and stare again.
Me: Well, I’ve got the main points. I just need to fill in the details.
Blog: …
Me: That’s not really why you’re talking to me, are you? So what’s up?

Blog: It’s just, well …
Me: Yes?
Blog: I, *shift position*, uh…
Me: Uh huh?
Blog: … uh *suddenly perks up* what about Saving Private Ryan?
Me: What?
Blog: You know, that guy you stuck in the stone ruins?
Me: *raise eye brow*
Blog: He solved some puzzle, and then you got him to go into the underground cave?
Me: Oh, right. I was going to save him. I mean I am going to save him. And he’s not a private. He’s not even in the military.
Blog: So what is he?
Me: Ryan’s a programmer, and also very good at solving puzzles. And I’m revealing too much already. Hey, are you taking down notes? *rising tone of alarm*
Blog: Uh huh.
Me: Hey delete that! You can’t publish that. All the mystery would be out.
Blog: Your readers will want to know what’s going to happen.
Me: Yes, of course. I have the story all mapped out. I just need to come up with an appropriate puzzle.
Blog: Riiight…
Me: Hey, it’s hard coming up with something unique, ok? I want to introduce a concept, it has to be moderately hard to figure out, and it has to fit into the story. It’s just hard ok?

Blog: I see you’re also slacking off. *checks files* You’re not posting as much.
Me: I’m re-prioritising. There’s a difference.
Blog: Semantics.
Me: Well, it’s just … my readers don’t seem to be talking to me much. They don’t seem to want to talk about what I wrote too. I don’t know if what I wrote was complete brilliance or utter rubbish. Either one could be the reason for their inertia.
Blog: Why don’t you just ask them?
Me: I did! At least I thought I did. A few people replied, probably out of pity *voice cracks, small voice* Can’t believe I’m talking to some nosy writing software…
Blog: Hey! I resent that.
Me: *smiles* I’m sorry. You’re a good friend. Oh yeah, where’s my contact page?
Blog: *points at a spot*
Me: Right. See? People can ask me any questions with that, or tell me I’m right on this or wrong on that or …

Blog: …
Me: Something’s still on your mind. Alright, cough it up. What’s going on?
Blog: It’s just, I’ve worked very hard for you.
Me: Yes, I know. And I thank you for it.
Blog: I mean, I displayed *checks some files* 197 posts for you.
Me: Wow! Has it been that many?
Blog: And got my friend, Defensio, to keep out spam. *checks another file* Like 2820 of them.
Me: Oh my goodness!
Blog: I work day and night …
Me: I work nights too …
Blog: *sniffs* 24 hours a day …
Me: I appreciate that …
Blog: 7 days a week. *sniffs* I even changed my entire outfit for you!
Me: Hey …
Blog: And what have you done for me? *voice cracks*
Me: Wait, are you crying?

Blog: Do you even know what day today is?
Me: Uh, it’s a Thursday?
Blog: *flips through folder, and grabs a sheet of paper* Here!
Me: *takes paper and read* … Oh, that’s my first post! Did I really write that? Oh man, that’s so embarrassing…
Blog: *bawls* Look at the date!
Me: Ok, ok… it’s 12 June, year 2007. What’s so speci… oh. Today’s 12 June, isn’t it?
Blog: *bawls some more*
Me: Hey hey hey… *grabs tissue paper and hand it over* Please stop crying.
Blog: *sniffs, wipe tears*
Me: I’m sorry, ok? You’re one year old today, aren’t you?

Blog: *nods*
Me: Happy birthday! I’m sorry, I totally forgot about it…
Blog: *tightens lips, eyes tearing*
Me: Hey, hey, hear me out! I’m sorry I didn’t get you a present.
Blog: *wipes tears*
Me: I have some plans, and one of them involves making you popular.
Blog: *in small voice* Really?
Me: Alright, maybe not celebrity popular, but more well-known. I’m also thinking of …
Blog: Not talking about math formulas?
Me: Getting some sponsorship … what? Hey, math is what makes you stand out, you know?
Blog: It does?
Me: It’s not like I write about differentiation of math equations… well, at least not yet.
Blog: Well, write more about programming stuff.
Me: I can’t exactly go around answering non-existent programming questions, can I? I’m looking…
Blog: Well, look harder. *sniff* I’m starting to feel a little lonely.
Me: It takes time and effort. I’m trying really hard…

Blog: There’s a programming party going on at Alltop, and I just barely got invited. It sucks to not know anybody.
Me: Hey, tone down your language.
Blog: You use the word “suck”.
Me: Well, I’m different. I’m a grown up.
Blog: Not by very much it seems. You still get mistaken for a student.
Me: Well, I have boyishly good looks… wait a minute, are you still taking notes?
Blog: Uh huh.
Me: Don’t you dare publish that! … Oh dear, it’s already published, isn’t it?
Blog: I’m a blog. That’s what I do.
Me: *groans*
Blog: Relax. Think of it as a birthday present for me.
Me: Right. *sighs*
Blog: And remember that popular thing.
Me: Of course. Now go bother someone else on the Internet, I’ve got some writing to do. And to find a hole to hide…