Skip to main content

Alternate Histories

A couple days ago I wrote a post about bash's history completion. It has since been brought to my attention that lesser programmers are in the habit of making "mistakes" when typing commands. This post is dedicated to those unfortunate souls.

If you're unsure what a history expansion will do, you can have bash print it out:

$ touch !-3*:p  # recall that !-3* is the arguments of the third most recent command.
                # the new command is echoed but *not* run
touch king of the world

The expanded line will be added to your history even though it wasn't run, so if it's what you wanted you can run it with !!. If it's close but not quite right, hit up or ^P to edit it.

Read more…

Beginner Eye for the Expert Guy

When I first installed linux I went through a phase of starting everything from a terminal ("lookit me, I'm a hacker!"), and every friggin one of them filled the screen with:

Info:  Invalid doohickey.
Warning:  Something bad is happening, just fyi.
Attempting to recover... failed.
Limping on valiantly.
Warning:  Doohickey appears to be growing fangs.
Warning:  Doohickey is attempting to
DOOHICKEY:  YOAR COMPUTER ARE BELONGE TO ME NOW
Info:  Emergency shunting from main loop in order to save humanity.  Tell my wife I love her.
Thanks for using VLC!

Watching those poor mutilated programs flailing helplessly away at each other in my RAM, I wondered how my computer could function at all. Now, of course, I ignore the pathetic cries for help unless something actually goes wrong.

I think this transition explains the saying, "can do, can't teach".

Read more…

Methodical Bondage

I mentioned a couple days ago that I look forward to writing a compiler 'someday'. Well, in the spirit of Failure Month, let's lower our sights enough that we can s/some/to. Let's just see how much of a class system we can put together. In this post, we'll get method binding working properly, and in a future one we'll look at inheritance.

To avoid muddying the waters with the implementation language's classes, we'll use one that doesn't have any - javascript. We'll avoid the dark corners & just work with functions and hash tables, so if you know any scripting language you should be able to follow this fine. [1]

Let's start without methods, and just get attribute lookups happening. We want to build the backend compilery bits that implement this sort of functionality:

class Foo: # make a class
  boop = 3 # instances of this class have an attribute boop, which by default is 3

f = Foo()  # make an instance of the class
f2 = Foo() # and another one

f.boop = 7 # set f's attribute boop to 7

print (f.boop) # get f's attribute boop, which is now 7
print (f2.boop) # 3; f2's boop is undefined, so we get the class value, which is not changed

We're not bothering with the frontend compilery bits, so we won't have that nice syntax to work with. Instead, we'll test by calling the backend functions directly in javascript. So the equivalent of the code above will look something like:

var Foo = make_class({boop: 3});

var f = instantiate_class(Foo);
var f2 = instantiate_class(Foo);

set_attr(f, 'boop', 7);

// console.log is the javascript equivalent of print
console.log("This should be 7: ", get_attr(f, 'boop'));
console.log("This should be 3: ", get_attr(f2, 'boop'));

After these functions are defined, then we can get to the good stuff. Excited?

Read more…

In Which I Mind the Gap

Oooh, a filler post consisting almost entirely of a link to an inspirational quote about why it bothers me to do a filler post consisting almost entirely of a link to an inspirational quote. Meta!

A week ago I had my first patch rejected. Not "oh we'll need a few changes" rejected; we're talking actual, outright "we do not want this code" rejected. Ouch.

Read more…

Bad Code Should Read Like Poetry

Yesterday's post went a lot longer than I expected, leaving me with a lot to get done today. So, I wanted to do something short. Unfortunately, I'm also aiming to alternate code/non-code articles, and code articles can take a while to do even passably well.

So, the dilemma facing me this morning was, should I just post a cheesy poem, or try to write some (inevitably crappy) code? Fortunately my friends pointed out that these two choices are not mutually exclusive.

Read more…

Ugly Kittens and Booze

They say life is what happens while you're busy making other plans, and so it is in programming.

I've spent my time as a programmer merrily bouncing from language to language ("Forth! Oooh, Haskell... no, assembly!"). But in the meantime, Python was casually easing its way more and more into my brain and fingers. So many moocs require it, so many blog posts use it for examples, so many of my friends know it. Over the last few months I've resigned myself to the fact that it has become my strongest language.

I don't mean to sound unkind. Python's a fine language. It's the vodka of programming languages - powerful, convenient, mixes well with a lot of things. If Point B is processed data and a lampshade on your head, Python and vodka will get you there. But I can't shake the feeling that they're both a little bland.

Read more…

Starting with a Bang

You don't use a linux system for long without learning about !!. It's handy in situations like this:

$ echo "I'm king of the world!" >/etc/fstab
lolwutno
$ sudo !! # DO NOT ACTUALLY DO THIS
sudo echo "I'm king of the world!" >/etc/fstab
pswdplz:
okfinewtvr

But history expansion can do much more than repeat the last command.

Read more…

30 Failures in 30 Days

I like writing, I like programming, I like writing about programming. So why haven't I been blogging?

You have to understand that I did not always enjoy writing. The key, as is so often the case, lies in the brain of my eight-year-old self.

I had been reading intensively since I was 4, and the first few times I tried to put a story down on paper were absolutely horrifying. I could see the vast gulf between what I had produced and what I would be willing to consume, but I didn't have the skills or maturity to bridge that gulf. The constant gold stars and head patting I got in math were much more appealing, so I decided that writing was not a thing I was going to do.

And I was stubborn enough to get away with this for a long time. Teachers don't always like stubborn kids, but they love quiet kids who get excited about books.

Read more…

Incremental Complexity

A friend suggested, perhaps facetiously, that I should do a post on incrementation. It took me down some surprisingly interesting roads; of them all, here's my favourite.

There are a number of implementations of Peano numbers in C++ templates, [1] but most of them use ints in some form or other, for example:

struct Zero { enum { value = 0 }; };

template<typename N>
struct Succ { enum { value = N::value + 1 }; };

This is fine as far as it goes, but it's still explicitly depending on the computer's ability to do arithmetic on ints. If you're going to type the characters "+ 1" anyway, you might as well give up and use python. I prefer the following:

struct Zero { };

template<class P>
struct Succ { };

This shows what's happening much more clearly. We're not using numbers to define incrementation; we're using incrementation to define numbers. Let's see what we can do with these numbers...

Read more…

Baby's First Decorator - Caching Functions

Here's a fibonacci function in python.

def fib(n):
  if n <= 2: return 1
  return fib(n-1) + fib(n-2)

You probably know why this is terrible. If you've never encountered exponential runtime before, try running this on increasing numbers - it's pretty eye-opening.

>>> for i in range(0,51,5):
...   print ("fib %d: %d" % (i, fib(i)))

On my computer, the values up to 25 print instantly. 30 takes a noticeable fraction of a second, 35 a couple of seconds... and 40 maxes out one of my processors until I get bored and kill it. Even if your computer and your attention span are both twice as good as mine, I bet you don't sit through fib(50).

Now, it's not too much trouble to write a better fib; we could make it iterative, or store and look up previously calculated values. But this is an example of a more general problem - what if this was a big hairy function we didn't want to mess around with? Or if we had 100 small functions with the same issue?

Read more…

Share