Blogs

Procrastination and Hubris

As they say, the devil's in the details.

I had the brilliant idea of putting off my project until the last minute. At the moment I am typing this sentence, it is -18 minutes until the project is due and I'm working furiously like a slobbering slave dog. The algorithm is simple enough. I wrote an iterative Collatz program. One mistake I made was that the iterative solution does not lend itself to lazy caching as I had planned out for my recursive solution. I spent precious minutes trying to implement caching before 10 pm and as a result now have a program with no caching that is, now, 19 minutes late. Perfect.

Another mistake I made was assuming the tools would work. Right now, PyDoc hangs on my RunCollatz.py file - which I didn't write. I do not recall there being anything on the forums which would alleviate this issue, and Google is turning up nothing. So now I also don't have the Python documentation.

I have a pretty sparse set of unit and acceptance tests as well, though I believe my tests are good ones. I saw in some other acceptance tests that people were getting "121" as the cycle length for 113383, when in fact the answer is "248." Despite this detail not mattering for UVa (it is the result of an integer overflow error which UVa has assured us will not occur), I insisted on making sure my program worked in that situation. So at least I got something done correctly.

What did I spend my time doing instead? Studying for other classes. I thought because I had used Git before and worked on actual projects that I could sail through this. However, this project has proven to be quite the teaching aid. I think I will have to thank Downing for this: I'm staring at a pretty awful grade right now and it's because of procrastination and hubris.

Ideally I'll have these issues sorted out tomorrow, but as 1 hour late is the same as 1 day late I think I'm going to go relax, get some sleep, and hope I learn my lesson for the future.

Automated Revision Control with vim

By default, vim keeps the last version of whatever files you've edited. By default, the backup file is stuck in the same path as the original with a ~ appended to its name. After a while, you end up with this sort of thing:

[tron@altair][~]$ ls projects/browser
Makefile                browser.ui              moc_browser.cpp
Makefile~               browser.ui~             moc_browser.cpp~
browser                 browsertab.cpp          moc_browser.o
browser.cpp             browsertab.cpp~         moc_browsertab.cpp
browser.cpp~            browsertab.h            moc_browsertab.cpp~
browser.h               browsertab.h~           moc_browsertab.o
browser.h~              browsertab.o            ui_browser.h
browser.o               browsertab.ui           ui_browser.h~
browser.pro             browsertab.ui~          ui_browsertab.h
browser.pro~            main.cpp                ui_browsertab.h~
browser.pro.user        main.cpp~
browser.pro.user~       main.o

Sure, you could run rm *~, but god help you if make a mistake writing that. You could write a bash function, script, alias, what-have-you to do that for you. Or, you could write a short script for your editor (It's vim, right?) to automatically keep diffs of every file you edit from the time you first :write a file with the plugin loaded to now.

Okay, this is kind of cool

In my previous post, I ripped at Joel Spolsky because I believe his company misses the forest for the trees, as its main goal is to be a great place to work at, rather than some external utility (like most companies), and so I responded to an article he wrote to advise CS students rather negatively because I don't think he's all that much of an expert in CS, his advice is bad, and he has bad hair and a terrible taste in shoes and he hit my dog with his car.

Ahem. Allow me to catch my breath.

Anyway, he did point out a really cool string copying technique that I'm sure everyone has already heard about, but which I will post here anyway for two reasons: first, it's new to me; and second, bounds checking and everything is done implicitly. It takes very few lines of code, has no security problems so far as I can tell at this hour and in this state of mind, and frankly it's just a really great use of pointer arithmetic.

On to the demonstration.

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. int main (int argc, char ** argv) {
  5.     char * orig = "This is the original string.";
  6.     char * dest = (char *)malloc(sizeof(orig));
  7.  
  8.     /* Simple technique is simple */
  9.     char * t = orig, *s = dest;
  10.     while (*s++=*t++);
  11.  
  12.     printf("%s\n",dest);
  13.     return 0;
  14. }

It works because the assignment operator implicitly returns the value of whatever was assigned - in this case, the characters of the string. At the end of all strings is the \0 character, which evaluates to false. Every other character evaluates to true, so the while loop will continue until it gets to the last character, post-incrementing the pointers at every step. Order of operations is a powerful ally.

Viewing Unmodifiable Files with vim

I've been playing around with my vim configuration files. There's this little script in $VIMRUNTIME/macros called less.vim that lets you view files basically in the same way less does, but with all of vim's cool features - like windows. The problem is, this script doesn't integrate nicely with your own vimrc, nor does it allow editing of one file while viewing another - something that would be quite useful if you wanted to have the documentation and the file you're editing on the same screen without using screen or twm.

So I wrote my own version. vim has the autocmd command which allows you to bind functions to certain events like BufEnter, which is called when the cursor enters that buffer. All you have to do is check if the file is read-only on load and display appropriately.

NOTE: The code on the full page is quite long. I had to split this post so it wouldn't clog up the home page.

Response to Spolsky's "Advice for Computer Science Students"

As one of our first assignments, we read "Advice for Computer Science students" by the eminent Joel Spolsky, a leader in the field of software development and a man whose word is considered second to none in the field of computer science. Before I comment on the article itself, let us first ask a question: why?

Spolsky is the founder of Fog Creek Software, a dev shop in New York that makes products such as FogBugz and Kiln. As a user of FogBugz for a number of different jobs, allow me to say something: it's Trac with a slightly better UI, except it costs more and is less extensible. As far as I can tell having used Kiln, it too is an expensive aping of something which already works, and something which already works well: Mercurial. They aren't even bashful about it. Kiln is a Windows-only port of Mercurial which adds nothing except a GUI. Perhaps his sales figures will tell me differently but I think much of this project already existed.

FogBugz itself, upon going to its front page, says this: "We help the world's best developers make better software." The entire purpose of this company is not to solve problems or do something good for the world, but to masturbate to its own greatness and give Spolsky notoriety. They write software primarily for other programmers, which is an insanely saturated market and frankly, a large barrel of fish. The persistent message across his blog and company website is that his company is a great place for programmers that meet his criteria, not an entity which serves any real purpose. This pleases him, but (not that there is any threat of me impressing Spolsky) I don't know that you could pay me to work there.

I'm sure he's a fine, good man, so please don't let's get started on ad hominem attacks or judgment where none is needed. I simply think it is fascinating that I see this man's words so often touted as pure, alchemic gold created from mere oxygen via his capable lungs when his two most notable accomplishments are a to-do list and a thin layer over someone else's hard work. I'm sure more work goes into the projects than I'm giving him credit for, but I can only speak for the final products.

And let us also be clear that I'm not some genius or super-productive android pumping out tons of quality code all the time. This is partly due to my having other hobbies, and also partly due to my not really having any itches to scratch at the moment. I have nothing which I need written at the moment, and my life has other pursuits awaiting me. I did not work on Excel at Microsoft; I do not own and run a profitable software company; and, most likely, nobody reads my blog. It's a fair cop.

But I do think it is a bit short-sighted to take his sage advice as gold when his goals are necessarily limited: he is a man primarily focused on making a profit using his skills, rather than solving useful, important problems with those same skills. I am the opposite, and my opinions of his article will reflect this.

The most glaring problem with his article is his slander of computer science theory. He recounts how he was given a proof of something rather silly on the first day of a logic class which he had trouble working with and understanding. So, being the motivated seeker of knowledge that he is, he dropped the course.

Wait, what?

He says something with which I do agree, but from which I draw different conclusions: software engineering and computer science are two different disciplines. Why, then, is he giving students the advice of dropping out of theory courses in a theoretical discipline? Why did he major in a field which he considers useless and unprofitable? There are technical schools out there which teach programming, and there are businesses which, unlike his, will look beyond the GPA and filter candidates based on ability and experience. I have worked for several and enjoyed myself thoroughly.

Computer science is necessary because all "useful" (though he does nothing useful so far as I can tell) disciplines such as mechanical engineering, electrical engineering, aeronautics, and a host of others depend on theoretical work which provides the foundation. He does not refute this in his article, but he paints a very narrow picture of academics as silly old men frittering away their time proving that things will work, rather than marching forward and banging the drum of global capitalism like a good worker should. I think this is incredibly unfair and, to say the least, rude.

Other advice he gives is very sane: learn C; learn to write; understand economics. As a matter of fact, most of his article has good stuff in it. There is a reason I read the whole thing. However, I think it is important that at least one person point out that his advice works well for someone focused on profits, and having nice working conditions, rather than someone focused on using their abilities for good or useful things. It's an important point, and not all CS students necessarily have anything to gain from his anti-intellectual screed.

Inaugural Post

The motivation for this blog comes from my Software Engineering course at UT Austin (CS 373, Downing). I will get extra credit if I write in here about my projects and development experiences in the class. So I have that going for me. It is very exciting that Downing has us using git, Python, and technology that actually works cross-platform and encourages us to focus on the problems at hand, rather than platform-specific licensing bullshit that our benevolent corporate overlords throw at us when we try to use their technology for anyone but their own benefit. Also, let's be honest, Python rules.

gmail-notifier

I finally got around to putting my gmail-notifier and generic-notifier up on github. They're tiny scripts that sit in your taskbar and notify you of new emails and whatnot.

Initially, I only needed a userland daemon that would poll gmail at specified intervals and send destop notifications that integrate with Ubuntu derivatives. I had written a shell script to do just that using wget and notify-send, but then I started working on machines that weren't using libnotify, so a better solution was in order.

I needed something to sit in the taskbar, have an easy way to change account settings, and fallaback to an at least decent notification bubble if it couldn't use libnotify. Qt offered a remarkably simple GUI setup, decent fallback for notifications, and python bindings. Pynotify (now python-notify) has python bindings for libnotify, but not everyone had pynotify installed back then. Dbus-python was more likely to be on systems that supported the notification spec (since that relies on dbus). I gave up trying to decide which to use, and just did both. Now I had a gmail scraper that did everything I wanted it to.

Gatlin pointed out that quite a few people could use something like this, so I decided to write a more generic version. I designed it so that, to extend the functionality to a different type of account, you would extend the GenericNotifier and PollingDaemon classes. The idea behind this was to have a different process running for each account. Why use threads and manage your own resources when the OS can do it for you?

That said, I'm starting to think that having a manager process running that just forks the different PollingDaemons would be a better UI design.

What do you think?

Now with 100% more mobile UI!

After finally getting one of these new-fangled mobile internet browsing devices, I became quickly annoyed that my own blag didn't have any sort of mobile UI. Enter the Mobile Theme module and my own variant of the Adaptivetheme Mobile theme. I haven't noticed any problems with it yet, but I'm sure some will pop up soon.

Your code snippet for this post is the entirety of the base.css for the mobile theme.

gmail-command

It turns out text messages from my phone to an email address are free. Google calendar can send sms notifications for calendar events. So now I'm working on a command interface that scrapes gmail messages and does... things. I'd send a text message from my phone, say "Tuesday, 3:00p, Meeting", and it would automagically add the calendar entry.

I know you're listening. Comment on it!

The 'correct' way to write in brainfuck

If you haven't heard about it, Brainfuck is one of those esoteric programming languages. When one is learning a language, it's customary that the first program they write simply outputs "Hello World". They then usually go on to do more complex things. Not so for Brainfuck, in which simple output is an exercise in reading an ASCII table and learning how to multiply with loops and pointers. This usually leads to long strings of things like ++++++[->+++++<]>, which are a pain in the ass to type out.

A wild python script appears.

  1. import sys
  2.  
  3. text = str(sys.argv[1])
  4. for letter in text:
  5.         ascii = ord(letter)
  6.         print "[-]>[-]<","+"*10,"[->","+"*(ascii/10),"<]>","+"*(ascii%10),"."