2008-11-26

Using python's sorted method with key functions.

Python's "sorted" method allows you to pass a key to it for returning the value to compare by. I'm surprised I didn't end up using this before. I had read about it in the documentation, but hadn't put it to use yet. This is best shown through a short example.

I have a list of dictionaries, the values of which are being displayed to the user in a tabular format. Some of these dictionaries have a key, 'money', which contains a string representation of a monetary value, perhaps with a currency symbol, perhaps not.

We want to display the values from the dictionaries that have the 'money' key at the top of the results list, sorted from lowest to highest. This is not a very difficult problem to begin with, but it's trivially easy in python. The solution looks something like this:



def get_results():
def by_monetary(item):
if item.has_key('money'):
value = to_decimal(item['money'])
return value
else:
return 0

...

return sorted(results, key=by_monetary)

This is going to come in really handy in the future, especially in cases where I have no control over where my data is coming from, or what format it is in. You probably already knew about this, but if you didn't, I hope you find it useful

2008-11-20

Typealyzer

I found out about typealyzer from here. It's a pretty interesting idea, although it seemed to work too fast.

It classified me as an INTP, which is what I tend to get classified as.

2008-11-19

On anarcho-primitivism and the capabilities of humanity.

If you are not familiar with anarcho-primitivism, it is a subset of anarchism which rejects civilization as a whole. People who self-label as anarcho-primitivists tend to also reject technology, "science", and the scientific method - which the view as little more than tools for the compartmentalization of reality into small, easily understandable parts.

I am not going to present an entire overview of anarcho-primitivist philosophy here. Chances are that if you are still reading this post, that you are at least marginally familiar with it. If you are not, some notable anarcho-primitivist authors include Derrick Jensen (whom I have much respect for, although I disagree with quite a few of his conclusions), John Zerzan, Daniel Quinn (whom I also have much respect for, his writing is beautiful and explores some profound concepts and David Watson. Bob Black, while not an anarcho-primitivist himself, is often cited as influential - my views have been influenced quite a bit by his "The Abolition of Work". Some publications that are prominent within anarcho-primitivist circles are Green Anarchy, Species Traitor (the species traitor archives are down the page a bit on that link, the page also includes links to a lot of anarcho-primitivist writing), and Fifth Estate.

There is definitely some interesting reading there. I have admittedly not read through all of it. I would recommend Derrick Jensen's Endgame - not as a complete overview of anarcho-primitivist thought, but as an interesting and thought-provoking read at the very least. Jensen is a very good author, and although it has been a while since I read through the two Endgame books, they definitely made me think, and question my mindset - good stuff.

Ishmael by Daniel Quinn is also a good read - it's presented in an innovative fashion, and his interpretation of the mythology in the Bible's Genesis is quite interesting.

Anyhow, enough overview.

I do not agree with anarcho-primitivist philosophy, although some of the points made by (for example) Jensen and Quinn are valid. The main problems that I have with it have to do with the rejection of technology, science, and civilization as a whole. I am not going to present rebuttal of anarcho-primitivism through direct analysis of the philosophy - this has already been done. Notably, Noam Chomsky (among many others) has pointed out that in order to achieve anarcho-primitivists goals, a mass reduction in human population would be necessary, and that a lot of anarcho-primitivists are, for all intents and purposes, advocating an almost total speciescide (for lack of a better term). The anarcho-primitivists I have talked to have been somewhat reluctant to address this (until I make it clear that I am not interested in calling them monsters for their views), but generally admit that they think that such an event is either very likely, or desirable for the good of all living things.

What I am going to present is an explanation of how I (and many others) view humanity, civilization, technology, etc - with a focus on parts that I feel that are particularly important (and valid), and that anarcho-primitivism is ignoring - specifically parts that deal with what it means to be human.

I feel as though anarcho-primitivism is missing some very large, unavoidable facts about the nature of humans, what we collectively know right now, the extent of what we are able to accomplish, the uniqueness of this point in humanity's history, and the nature of civilization - and although I am glad to see criticism of modern society (which is very much in need of criticism), I almost think that they are doing something close to the opposite of "missing the forest for the trees" - something like "missing the trees for a very specific forest". But I digress. What follows will not all be directly related to anarcho-primitivism, but I feel that it is necessary in order to understand where I'm coming from - it will hopefully become obvious why I view the philosophy as incorrect, or at least as incomplete. I would humbly request that (if you are reading this from the perspective of an anarcho-primitivist, or just for the purposes of getting a bit of brain exercise) you read it in full before rebutting it. It's long, but I hope it's worth the effort.

Standard disclaimers apply - I do not mean to come off as being dismissive, condescending, or arrogant, although I realize that I probably do at times. I am far from being a master of textual communication (or communication otherwise). I do not hold my opinions as being concrete truths - what I consider to be "correct" in matters like these is not set in stone. I believe in questioning everything that you can, and in examining things from as many angles as possible in order to enable yourself to have a complete, valid opinion on something, and do not believe that one should hold their opinions as being infallible. What I am expressing is something that I have put a lot of thought into, but I am human - and I myself may be missing some large, obvious points. I welcome rebuttals and criticism of my viewpoints, and have modified my opinions and mindset because of such criticism many times in the past. Everything that I write here should probably be read as if each sentence was prefixed with "In my opinion," - I would think that should be the default mode of reading political pieces, especially on the internet, but too often people forget about it. There may be areas where I am not thorough enough in defining what I am talking about. If clarifications are needed, I'm sure that they will be made in the comments, and at the bottom of this post.

We humans can be quite stubborn, and I think it is a very sad thing that more people are not willing to question how and what they think. Furthermore, I find the state of a lot of anarchist writing to be largely preaching to the choir, and that saddens me - but that's another topic. Suffice it to say that I think that a lot of writers would benefit from giving Politics and the English Language a good read (wiki link).

Now on to the "fun" stuff.

Like every other living being, humans are unique within nature. Every thing that we are capable of observing, as far as we can tell, has some unique things that make it it. Every living thing, as far as we can tell, has some unique traits that enable its survival - some things share traits with others, but every one has something unique about it. Over the time that we have been examining the world around us (which is probably ever since our brains developed to the point that allowed introspection, perhaps even before that if Bicameralism turns out to be correct), we have been able to identify tons of different traits that enable things to survive. We've noticed enough to create entire classifications for types of matter, to types of life, to types of types of life, and so on. Plants, while considered to be alive, are different than animals, and are able to survive because of different things.

It seems probable that the cause of these different traits are physical laws that deal with what and how things are able to combine, these laws (if we knew what they were in entirety) would be expressions of properties of matter, or of the "building blocks" of matter. Evolution. Things are able to combine in a myriad of ways - over time, they have combined in a myriad of ways - and the combinations that led to stable things stuck. In the case of non-living things, this would be part of the reason that we have planets and stars. In the case of living things, the combinations happen at a bit higher of an abstraction (e.g. instead of different types of elements combining into a molecule, you have DNA/chromosome/other biological mutations that allow for beaks, that are the result of some combination. This is a woefully inadequate description, but I hope the point is clear), and if a combination (more specifically in these cases a mutation) does not cause the death of an individual in a species, it tends to stick around and propagate itself given enough time. Over enough time, species diverge from one another - a point gets reached where there are enough individuals with a specific set of mutations within one species, that they can be considered their own species. More often than not, it seems like the things that differentiate one species from another within the different branches of what we call the "Animal Kingdom", are directly related to survival. I doubt that they are all the time, but it makes sense that they would be most of the time - a random mutation that increases an individuals capability for survival is more likely to stick around and propagate through their offspring than a random mutation that decreases an individuals capability for survival, or one that is neutral to their capability of survival.

As a loose example, plants have the ability to pretty directly harvest the Sun's energy, and to pull nutrients out of the soil; birds have wings and build nests and lay eggs; mammals can have sex and reproduce and have fur for warmth and so on. (Yes, there are exceptions to these "rules").

Humans, as far as I can tell, have two very important traits that allow us to survive. We can manipulate physical objects rather well (that is, we have thumbs and nimble hands), and we are capable of reasoning on a very high level of abstraction. At the base level, this is what enables humans to survive, regardless of the form of organization (or lack thereof) that humans live in.

These abilities are part of what makes us the human species. Without them, we would not be human - and, if we had one of them and not the other, or neither of them, we would not be able to survive in the same manner that we do now. There are no (again, as far as I know) humans that survive without utilizing them.

Now, let's assume that we can put ourselves in the shoes of the hunter-gatherer people of old. Over time, members of our group, however small, are going to make little discoveries through the application of our "survival traits". They might find out that certain types of plants are not good to eat, or they might figure out how to coax fire out of the aether, or they might figure out how to sharpen sticks, or make bows, or boats, or whatever else. They might discover these things on accident, or they might discover them through guessing and trying.

If a discovery is kept and improved upon, what is happening is that new technology is being invented or used, and that people are "practicing science". Everything that is made by humans that is meant to serve a practical purpose is technology. The hammer, the lever, the wheel are all technology. A sharpened stick is technology. Everything that is refined through experimentation can be viewed as science. Figuring out which rocks will sharpen which is science. Figuring out what plants are good to eat is science. Figuring out what animals are good to hunt, and how to hunt them is science.

Each thing that is discovered, each new combination of physical items or ideas, leads to the possibility of new discoveries and combinations. All of our current technology - the computer, cars, electricity, and so on - is based on abstractions and new combinations of previous knowledge.

That is not to say that technological progress is an inherently good thing. There are serious complications with how we (for instance) create energy right now. Technological progress can not be an inherently bad thing either. There is no evil in electricity - it's all over nature. There is no evil in a hammer, or in a walking stick.

I would argue though, that while technological progress is not inherently good or evil, that it is inherent. It is a direct side effect of what makes us human - of what enables us to survive.

Let us think for a moment about what would happen if the anarcho-primitivists goals were accomplished for all of humanity. Let's say that we do face a giant die-off of humanity - we blow ourselves up with war, or get smacked by an asteroid, or ruin the planet to the point that it cannot sustain human life anymore on the levels that it is currently. A few small packs of humans survive - hell, for the sake of this argument, we can assume that everyone who survives considers themselves to be an anarcho-primitivist. Let's assume that they're prepared for the event, and are capable of surviving indefinitely. What would happen?

After some period of time, say a few hundred generations, there will be no real memory of the way that we live today, except perhaps as mythology. Languages will either be entirely different, or just starting to re-emerge depending on how the original survivor humans felt about verbal "symbolic communication". The reasons that anarcho-primitivists have now for advocating what they do will no longer exist - humans are largely small groups of individuals, living in a hunter-gatherer type of situation, presumably in pure harmony with nature and with no division of labor, and all that stuff.

Unless we have, at that point, turned into an entirely different species, the series of discoveries that led to modern civilization would be rediscovered as humans play around with things. Assuming that there is not a permanent taboo against utilizing new discoveries to make survival easier, these discoveries will be used. Eventually, at least one group of people will discover agriculture again, and will start farming and using their capabilities for physical manipulation and abstract reasoning to influence the form of Nature around them for the purposes of making survival easier.

This wouldn't happen in one day, or one year, or one century. Possibly not even in one millennium, but it would happen eventually. By the time humans were discovering enough that their groups populations would be expanding, the situation would be rather interesting. We would have tribal groups of people, who had only ever been exposed to their elders, and perhaps another tribe here and there. Tribes that were separated by a great physical distance would have developed differing cultures, languages, and habits. Tribes would probably have a pretty large variance in how they lived, and in what tools and discoveries they utilized to enable their living. A lot of this would be dependent on physical area - fishing poles are not a great survival tool compared to spears if you're nowhere near an ocean or large body of water, and just the opposite if you're nowhere near the plains.


If one of these groups figured out how to make a boat, and travelled farther than anyone their tribe was aware of anyone travelling before, they would eventually run into a group of other humans that was different from them in every way except for base physical appearance, almost in the same way that we are different than other apes in every way except for base physical appearance. How would these two groups of people even recognize each other as people? Sure, they both make sounds - but lots of animals make sounds. Sure, they've both got two legs and two arms, but other animals look like that as well. There would be no means of communication, probably no observable similarities, and more likely than not they would not recognize each other as the same species - how could they?

If one group, or multiple groups, had figured out agriculture, and had started to use up more land for the support of their group, and they ran into another, totally alien, group of people - they probably wouldn't even recognize them as people.

What I'm trying to get at is that if we did see a mass reduction in the population of humanity, and humans ended up having the hunter-gatherer lifestyle as the only really viable means (by choice or otherwise) for survival, that given enough time we would see a repeat of history up to this point - the same discoveries would be made eventually, the same growth of religion and mythologies and cultures, the same clash of cultures and warring, the same discovery of electricity, etc. We would end up doing all the things that anarcho-primitivists rail against in modern society again, and would quite possibly end up in the same situation that we have now.

Now, we are currently in a very interesting time. It has become apparent in the last three or four decades that a lot of how we live is harmful to other species, and harmful to their ecosystems, harmful to everything - eventually (and in many cases, right now) including us. The most interesting thing about this, in my opinion, is that we weren't even capable of knowing that we were screwing things up so badly until the last three or four decades. There's been warning signs, and some speculation for probably a few hundred years - but no real connection linking our actions with the "warning signs", and no data to back up the speculation. This is an incredibly short amount of time in human history.

I suppose that the critical response to those last few sentences would be that civilization has only existed for a very short time in human history. That's true, however I do not think that it is because humans weren't making "new technology", or because they had no "scientism" to speak of, or because they weren't attempting to understand the world around them - I think that it is for an entirely different reason, namely that of what is discoverable with a certain bank of knowledge.

For each new thing that a person, or group of people discovers, there is generally ways to use that new knowledge to discover a bunch more new things. Some discoveries open the door to a lot of new knowledge and applications, some do not. If you track humanities capability for communication, and humanities "body of knowledge" throughout history, you'll see that it follows an exponential curve very closely. The ability for humans to communicate across differing cultures and languages allows groups of people to share their discoveries, and over time this starts to snowball. You can't exactly discover the practical uses of fossil fuel without having any idea what a knife is - some discoveries primarily allow us to further investigate the nature of the world around us. Having the insight to start planting food is significantly easier than figuring out fire. Discovering electricity is significantly easier than figuring out that planting food can make your life easier - this is, of course, assuming that you have never seen anything like that before. By the time we figured out electricity, we had a huge bank of data about the world around us to come up with theories from, and there were still tons of what we would now call "crackpot" theories about the world.

It is, at least partially, the difficulty of discovering the prerequisites to agriculture, and then figuring out agriculture that caused humanity to live without it for so long. Possibly, the discovery was entirely chance.

Back to what we know now - again, it is practically undeniable that our current means of energy production is harmful - not only to us, but to everything around us. We've only been aware of this for perhaps twice as long as I've been alive - and it's only become apparent to the average person in the last few years, as far as I can tell. We also are now capable of producing energy in a way that does not just rape the Earth with no regards to other forms of life. We know (for example), that energy is not used up, just transferred - and we have a giant yellow source of energy blasting the Earth every day in the form of the sun. We know how to utilize the wind and the water to create energy, etc.

Furthermore, we can communicate globally instantaneously, and we are more than capable of recognizing other groups of humans as humans, regardless of their culture. Some groups of humans even have a concept of rights that living beings have just for being there. Younger generations of people have cultures that are based less on their immediate surroundings, and more on the other members of their generation - globally. We can transport things globally with ease, we can set up organizations, temporary or not, and impromptu or not, to deal with anything.

We (and here when I say we, I mean humanity as a whole) have the ability to have our cake and eat it too. From the ability standpoint, we are entirely capable of providing for every single person on this planet if they want it. We have plenty of ways already of providing energy, homes, etc that are not based on methods that push us closer to ecological disaster. We have tons of people finding out new ways to do things that have been, for a long time now, accomplished through methods that are not sustainable. We are, for the first time in recorded history, technically capable of having civilization (as in, not being hunter-gatherers) without violent coercion. Our technology, and "science" is the enabler of that.

What is holding us back is not that we have civilization, and is not technology, it is not science - these are side effects of what make us human. What is holding us back are economic structures, power structures, and cultures that came to rise before we were capable of large-scale organization and communication without them (which are also, partially side effects of what makes us human, but they are not required for human survival. This hints somewhat at Marx's theories about the progression of human forms of societal organization). This is not to say that I think that we could just jump into an anarchist utopia, but we are not held back by how capable we are of communicating, or how capable we are of getting places anymore - and really, communication and transportation are the base things that are needed for humans to function in groups larger than one anyhow, whether it be in groups of six or six-billion - the main difference there is scale.

Emacs Tidbit #3

For those of you who have blogs hosted on blogger (like this one), and use emacs, I'm sure you've run into this - writing a post in emacs with auto-fill mode on leads to an ungodly amount of reformatting needed because of the insertion of hard line breaks.

If you weren't already aware of it,

longlines-mode
solves this problem.


longlines-mode is an interactive compiled Lisp function in `longlines.el'.
(longlines-mode &optional arg)

Toggle Long Lines mode.
In Long Lines mode, long lines are wrapped if they extend beyond
`fill-column'. The soft newlines used for line wrapping will not
show up when the text is yanked or saved to disk.

If the variable `longlines-auto-wrap' is non-nil, lines are automatically
wrapped whenever the buffer is changed. You can always call
`fill-paragraph' to fill individual paragraphs.

If the variable `longlines-show-hard-newlines' is non-nil, hard newlines
are indicated with a symbol.

This, in combination with the ability to post stuff to blogger through email, makes using emacs with your blogger account a bit easier.

One more thing - never, ever, while in the blogger "new post" editor, hit Ctrl-P, unless you really want to publish. It can be awfully frustrating.

2008-11-12

A little userscript for reddit.

If you read this and reddit, and the "my reddits" dropdown in the top-bar was too big for you (it scrolled past the end of my screen), here's a little userscript to make it a bit nicer.

You'll need to be using greasemonkey and firefox, of course.

2008-11-11

Emacs Tidbit #2

Ever make a throwaway buffer in some random directory that you didn't intend on saving, but then ended up wanting to save - but not in that directory?
M-x set-visited-file-name

Is what you want.

From the docs:

set-visited-file-name is an interactive compiled Lisp function in `files.el'.
(set-visited-file-name filename &optional no-query along-with-file)

Change name of file visited in current buffer to filename.
This also renames the buffer to correspond to the new file.
The next time the buffer is saved it will go in the newly specified file.
filename nil or an empty string means mark buffer as not visiting any file.
Remember to delete the initial contents of the minibuffer
if you wish to pass an empty string as the argument.

The optional second argument no-query, if non-nil, inhibits asking for
confirmation in the case where another buffer is already visiting filename.

The optional third argument along-with-file, if non-nil, means that
the old visited file has been renamed to the new name filename.


This just saved me a few commands, hope you find it useful, fellow emacs-learners. Don't forget to follow the link to files.el and read the code for the function.

2008-11-09

Creating dynamic client-side image maps with javascript/jQuery

I recently ran into an odd problem - I needed a dynamic client-side image map. Dynamic as in "the areas will be in the right spot regardless of how large the image is client-side".

I've been working on a site for the house I live in, which creates a lot of various forms of media. We decided to offload video hosting for videos we make to youtube, since we can't afford hosting costs for streaming video at this point in time. Youtube offers a pretty neat chromeless player that you can control through javascript, and the guy who does most of our design work whipped up a pretty nice-looking television with buttons image to use as the player. Given that he's not exactly very tech-savvy, it seemed like using an image map (which I haven't really heard much about for years) would be an appropriate way to make the player

Now, the problem with image maps is that since the coords attribute of the area tags is based off of pixels, you can't easily use an image that you don't know what dimensions it will end up being on the clients browser.

This is one of the situations I've run into where the solution probably would have been obvious if I had gone to college, but I enjoy solving problems anyhow - I got out the graph paper and pencil, drew a few boxes with points in them, and it became apparent that if I represented the coords for the areas as ((x/image_width)/(y/image_height)) instead of just (x/y), that it would be pretty easy to modify for any image size.

Javascript to the rescue:


//the height and width of the image on the server
CircleButton.prototype.base_width = 800;
CircleButton.prototype.base_height = 600;

//stores information about where buttons are as the ratio of
//(x/base_width)/(y/base_height)
function CircleButton(x, y, diameter, func) {
//express x,y,diameter as ratios instead of pixels.
this.x = x / this.base_width;
this.y = y / this.base_height;
this.diameter = diameter * ((this.base_width / this.base_height)
/ (this.x / this.y));
this.func = func;

this.adjust_coords = function(width, height) {
//coordinates for an image of (width, height) on the client
return [parseInt(width * this.x),
parseInt(height * this.y),
parseInt(this.diameter)];

}

this.tag_string = function(width, height) {
var coords = this.adjust_coords(width, height);
return '<area shape="circle" coords="' + coords.join() + '" href="javascript:' + this.func + '"/>';
}
}


This only works for circular buttons, but would be easy to modify for any of the other shape options (I only need circular buttons at the moment).

To use this on a page, you need to

  1. Initialize some buttons with the coords that they would have in the image on the server
  2. Find the image's width and height on the client
  3. Generate the area tags with the previously found width and height
Like so:

function setup_map() {
var base_buttons = [new CircleButton(525, 127, 15, 'ytplayer.playVideo();'),
new CircleButton(584, 153, 15, 'ytplayer.pauseVideo();')];

//size of the map image on the client
var map_width = $('#my-image').width();
var map_height = $('#my-image').height();

$('#my-map').empty();
$('#my-image').removeAttr('usemap');

var the_map = document.getElementById('my-map');

for (var i = 0; i < base_buttons.length; i++) {
(function(b) {
s = base_buttons[b].tag_string(map_width, map_height);
//we have to append to the innerHTML like this because of the way
//jQuery appends stuff
the_map.innerHTML += s;
})(i);
}

$('#my-image').attr('usemap','#my-map');
}


Assuming markup like this:


<div id="video" class="content">

<map id="my-map" name="my-map">
</map>

<img id="my-image" src="images/my-image.png"/>
<object width="48%" height="52%" id="video-player"
allowscriptaccess="always"
data="http://youtube.com/apiplayer?enablejsapi=1&playerapiid=ytplayer">
</object>
</div>


The calls to empty and removeAttr can probably be removed if, unlike me, your image and map are not residing in a jQuery tab. We have to append to the innerHTML of the map because of a quirk with how jQuery does appends - as far as I can tell, it appends to an empty div - and area tags aren't valid inside a div, so the browser ends up not displaying them. That was a bit frustrating to figure out.

Also, if you're like me, and the image and map are residing in a jQuery tab, you'll want to bind setup_map to the click attribute of the tab with a timeout like so:


$("a[href='#my-tab']").click(function() {
//we have to wait a little bit for the player
//image to load, otherwise it reports a width of 0
setTimeout('setup_map()', 100);
});


Just about any amount of delay should work, 100 milliseconds is unnoticeable, 500 would work if you wanted to be really safe

Image maps don't get much action these days, probably because when they were made, there wasn't much of a use for them - and now, there are other ways to accomplish what they were generally used for. I do feel that they were quite appropriate for making a custom player with youtubes chromeless player, and it was fairly straightforward to allow for differing image sizes on the client side. Hooray!

2008-11-01

Viewing the world as a programmer / curious fuckhead.

Steve Yegge wrote a post the other day entitled A programmer's view of the Universe, part 1: The fish. Jokes about the length of Steve's posts aside (I really don't mind the length, myself), this was a beautifully written piece, and it got me thinking.

I came to a bit of a realization about the way that I think, how being a programmer has influenced that, how being just generally curious has influenced that, and how my mindset contrasts with (specifically) creationists. I am an atheist, in the more "modern" sense of the term - I do not profess faith in any sort of deity. I do not discount the possibility of one, although my reasons for that are more because I don't like discounting possibilities, and less because I actually think that a deity or deities are even close to being a probable occurrence.


Some introductory matter


Most of my family, and some of my friends are religious folk. The vast majority of the religious part of my family, and most of my religious friends profess Christianity as their religion. The vast majority of these people are intelligent (for whatever it's worth, my Grandfather was a member of MENSA until he got fed up with them being all uppity), and mostly willing to discuss issues of faith on the debate-level

Now, religious debate is a funny thing. I doubt the very existence of a deity of any sort - and doubt the existence of your god(s), if you have one or more, much more than I doubt the existence of a god in general. That's saying quite a bit. As such, debating faith and religion with people of faith is pretty interesting. A lot of the time, the debates follow one of two paths:




    1. Someone tries to use their religious text to back up their entire belief structure

    2. I point out that I don't believe in god to begin with, and start pointing out logical fallacies within their belief structure

    3. They continue to counter-point with their text, and we repeat steps one and two until the debate just fizzles out





    1. We start talking about how we view the world, and how what we have seen and experienced has lead to our current mindsets.

    2. We eventually come to the conclusion that we are seeing the same thing, but interpreting it differently

    3. Trying to explain why we interpret the world the way we do ends up being very frustrating to accomplish - something that ends up being on such a high level of abstraction that it's hard to find words to describe.


The first type of debate is tiring, and almost never leads to anything worthwhile - debates that follow the first format tend to just devolve into very emotional processes, with one side being very and legitimately (taking into account their beliefs / worldview) concerned for me and what's going to happen to me after I die, and with myself getting rather annoyed, and sharp in tone.

The second type of debate tends to be slower and more thoughtful, with both sides considering the arguments put forth by the other, and while it does generally end in something of a "stalemate", both sides probably come out of it with a better understanding of the other sides mindset, and with perhaps some new viewpoints, and new things to think about. I greatly prefer the second style, and people with which I have had the second style of debate are the people that I had the epiphany regarding how our mindsets contrast. People with which I have had the first style of debate, and their mindset, is perhaps a subject for a separate post, and it would be a rather complicated and sad post indeed.

The most interesting thing about the second style of debate is that myself and the person I am debating with are often using some, if not all, of the same observations as our reason for thinking the way we do, at least at a high level of abstraction.

We both see patterns all over the place - the difference is in how we interpret them.


The point


When I look at the world, I see patterns upon patterns, loose rules upon loose rules, abstractions upon abstractions. The intelligent theist or deist sees the same thing, and interprets it as being evidence pointing at the existence of a god, or intelligent creator of some sort. After all, there is so much similarity in everything, it's only a small leap of faith to assume that something intelligent had its hand in the creation of it, and perhaps even in the day-to-day happenings within it.

What I see is stateful protocols built on top of layers of abstracted stateful and stateless protocols. I see the ways that base elements are able to combine, combined up to the point where other interactions are able to occur, those interactions combined, and so on and so forth until we get plants, and self-awareness.

The above "explanation" of what I see does it no justice, and to be honest I don't have enough knowledge of physics, chemistry, biology, and all the other realms of human knowledge to do it justice.

As a life-long curious fuckhead, and an almost life-long programmer, I have had first hand experience with:

  • How very complex rules for interaction can be built from very simple bases (see SICP)
  • How unexpected outcomes can occur even in simple systems
  • How it is possible to implement stateful protocols on top of stateless ones
  • How entirely random occurrences can drastically change the behavior of a system, or agents in a system
That last one is largely from reading about the craziness that happened when random mutation was added to the old "core wars" game.
It's an incredible read, and it did a lot to solidify the validity of evolutionary "theory" in my mind when I first read it.



Of course, one can argue that all the direct experience I have had was set up by intelligent beings. I don't think this needs to be the case - mutations on the edge of a set of rules ability to mutate get kept or discarded according to whether or not the organisms with the mutations are capable of surviving long enough to spread them. They are caused by chance (much how cosmic rays can flip bits). This is yet another thing that I can not describe eloquently enough to do it justice - how chance and very base rules about combination can lead to complex systems, and drastic changes within complex systems given enough time.


In conclusion


I'm not the sort of person who likes faith very much. I don't like having opinions that I can't back up, I don't like relying on "gut instinct", I don't like not questioning what I think I know. This is part of the reason why I like programming - there is always something new, and there is always reason to question your assumptions, and often it turns out that what you produce will be of a higher quality if you do question your assumptions.

I like to think that this is applicable to many other areas of life (in fact, I thought it was a good thing to do before I ever started programming), and my life experience - as well as others - greatly supports the notion that examining your mindset and questioning your assumptions is a very good thing to do.

I can see how being a programmer has changed the way that I look at the world - it has not reduced the wonder I see in the world, but has changed the nature of that wonder from one of pure mystery to one of plausibility. I swear, I can almost see where the layers of abstraction separating life from matter and separating sentience from life lay - the lines are fuzzy, but they're there - and I probably wouldn't even be close to being able to sense them if I wasn't a programmer.

2008-10-13

A simple HTML generator using python2.6s format method.

So, python2.6 got released a little bit ago, and the changes are looking pretty nice - no real surprise there. One of the new things is a "format" method for strings that is meant to replace the % operator. You can read more about it here.

I like it quite a bit compared to the % operator - it's clearer, and not much more verbose. I've been writing a lot of web-based stuff lately, and a lot of times I don't want a full templater, I just want to return a couple of tags with ids / classnames, maybe some nesting. This is very easy to pull off in a clear manner with the format operator (it wasn't much less clear before either really):


from string import Formatter
tag = Formatter()
tag_string = """<{tag} {attrs}>{contents}"""

def generate(items):
result = ""
for item in items:
if isinstance(item['contents'], list):
contents_string = generate(item['contents'])
item['contents'] = contents_string
result += tag.vformat(tag_string, None, item)
return result


From here it's really easy to write little functions to generate what you need - all you need to make is a dict. I'll be using this over the next few weeks, and I'll probably be improving it a bit, but so far it, combined with some dict-making functions for tags I generate often, has suited my html generation needs just fine.

2008-10-08

Creating a small addition of functionality to emacs behaviour.

I thought it might be a nice thing to illustrate what a lot of people really like about emacs with a small example of a little added functionality that I implemented earlier today.

There's a function called "kill-some-buffers", which steps through your buffer list (the list of open editing areas, most likely mainly files) and asks you if you want to kill them. This is useful when you find yourself with a whole bunch of buffers open, some of which you haven't touched for a while - and I've been using it lately.

I wanted to be able to mark certain buffers as "this is not getting killed by kill-some-buffers". Looking at its documentation, it doesn't say that it supports this functionality (C-h f kill-some-buffers). Looking at its code confirms this (click "files.el" in the output of C-h f). It's a short function, although if you're not familiar with a lisp, this may look like nonsense. If you're familiar with a lisp it'll be fairly obvious, and if you're passingly familiar with elisp you shouldn't have a problem reading it.

It just walks through the list of open buffers, performs some checks, lets you know whether they're modified or unmodified and asks if you want to kill them or not, taking the appropriate action.

Rather than modify the emacs source, I copied the body of kill-some-buffers, and added a variable and another utility function.

(defvar kept-buffers nil
"A list of buffers to never kill when running `limited-kill-some-buffers'")

(defun add-to-kept-buffers (buffername)
(interactive "bAdd to kept buffers list: ")
(setq kept-buffers
(append kept-buffers (list buffername))))

The line "bAdd...." tells interactive that it expects a buffername (which comes with autocompletion, and is just a taste of what you can do with interactive....). Interactive itself tells emacs that the function can be called by a keystroke, like M-x add-to-kept-buffers.

The only change to what used to be the body of kill-some-buffers is a single check after the others that it performs:
(not (member name kept-buffers))
The only thing I might change in the future is pruning of the kept-buffers list - which can be easily done by defining "advice" on the function kill-buffer to check to see if the buffer being killed is in the kept-buffers list, and if it is to remove it from it, but kill-buffer is a "primitive" function (written in C), and defining advice on those is generally frowned upon. I want to see if there's a more appropriate way to do that cleanup before doing that. I can always manually prune the list if it gets too large. Also, right now it seems like if I add a file to the kept-buffers list, I'm probably going to want to keep that file there for a while (if I kill the buffer, and then re-open the file, I want the restriction to stay).

If I had decided to modify the files.el source file, this would have been a 7 line change. Granted, this is a pretty trivial change - but the ease with which it was performed is amazing. A little bit of reading the provided (and high quality) documentation (through C-h i), and a little bit of reading through the source, and it's possible to totally bend the editor to your whim.

So a few minutes of coding, and something that was a minor annoyance to me about one functions performance is solved.

2008-09-29

Compiling a kernel using the modules you actually have loaded.

So today on reddit, someone named sping was wondering if anything existed to take the modules you have loaded on a linux system, and automatically compiling a kernel with those compiled in.

Now, this is probably not that great of an idea if you plan on updating your kernel any time soon, but it may come in useful for people who know have a computer whose kernel and/or hardware aren't going to need updating for a few years.

I wasn't (and am not) aware of a tool for doing this, so I decided to write one - as it sounded like a fun (not to mention educational) exercise. I figured there would be a pretty easy-to-find correlation between module names and kernel configuration options (since they are marked with "m" or "y" and such). I'm far from being a kernel-configuration guru, or a master of the kernel internals, but I know a little bit (and better yet I know how to find stuff out, hooray.).

It was a lot harder than I expected to figure out how to relate the currently loaded modules to their configuration options. The reliable method I found is slow.

Basically, once you have the kernel sources, you can find what kernel option you need with this nastly oneliner, from the sources directory, where FOO is the name of the module you're looking for:

find . -name Makefile | xargs grep .*CONFIG.*FOOo$ | awk -F "$" '{print $2}' | grep -o \(.*\) | sed -e "s/(\|)//g"
This looks pretty nasty, but it's not that bad. Its just doing this:

  1. Find any file named Makefile under this directory.
  2. For each match of step 1, look for a string in it containing "CONFIG", "FOO", and ending with an o. These lines look like this: "./fs/hppfs/Makefile:obj-$(CONFIG_HPPFS) += hppfs.o
  3. For each match of step 2, split the line on the "$" and print out the part of the second half surrounded by parentheses with the parentheses removed.
Anyhow, once you have the links between module names and kernel configuration options, all you have to do is modify the kernel config file and compile (and perhaps still answer a few compile config questions if an invalid kernel config got generated).

This was a lot more work than I expected it to be, but really wasn't that hard when you take into consideration that I don't really know much about linux internals, or how the kernel works except at a high level, and was able to come to a solution primarily by searching through and modifying text files, and having a program call the commands that I normally would.

I wrote the actual "I would give this to people who know what they're doing to try" version of this in python, you can see it (or download it) here. It might for any debian-based distro, but I've only tested it on Ubuntu. There's a script called prelims.sh that will download and install what you need to compile a new kernel, and the kernel sources. The script is still rather hackish, there is some ugly code, may only work on Ubuntu, and is not appropriate for people who don't know how to step through a kernel config process already.

So, it's not polished - but it works as a proof of concept, and that was the goal here.

2008-09-27

What I would do if I had 100K per year.

Earlier today, there was a post on HN asking people what they would do with their life if they had solved the "money problem". Say you had $100,000 per year, adjusted for inflation and all that - what would you do with it?

I know what I would do with it. I would make a huge attempt to get the average person concerned more with the quality of life of humanity as a whole than with the quality of their own life. We've got a metric shitton of problems we're facing right now, and $100K per year - while not a gigantic sum of money - is more than enough to put some stuff to action.

What I'd probably want to do first is buy a large building of some sort - a wharehouse, or an old apartment complex. Something that would be maintainable and have a whole lot of space.

I'd revamp this place to have:

  • Learning space: Ample library of educational material, rooms for lectures / group study.
  • Rooms for fiddling around with electronics /metal working / audio recording / painting / sculpting / woodworking / etc.
  • Living space for around 50 people.
  • Coffeeshop / open library area, with ample supply of good literature
  • A robust network, and applicable software (there's all kinds of stuff that could be done on an intranet in a place like this)
  • Space for holding larger meetings of people (plays, bands, and so on).
  • Space for indoor food growing - delicious vegetables.
  • Gym / recreational area.
I already know a few people I would want to be living there, but I (we) would be open to anyone passionate about learning, and / or passionate about using technology to improve the living conditions of humans, with a focus on technologies that don't entirely rape the earth.

Ideally, I'd want the spot to be as self-sufficient as possible. Most of the $100K/yr should cover that, and there's a bunch of ways to reduce costs, mainly through having people who are into autodidaticism around. DIY folk. Autodidacts and DIYers are not the same, but there is a pretty significant overlap. We could run generators through excersize equipment, solar stuff, etc to reduce power costs.

I would want the projects started at the place to have a focus on the community that it's located in. Get involved with everyone we can find in the area who would be interested in improving the quality of life for everyone around them, and work with them.

Once this place was established and running well, I would want to then start opening up more spots like it in different areas, and keep them in communication with each other. Share resources, hold mutual conferences. Maybe start sending a bus around looking for people who would want to join up with this mode of living, and start expanding.

If everything went smoothly (which it probably wouldn't), there could be a new societal structure emerging that was overall better for making happy humans than the one we currently have in 20-30 years. At least that would be my hope.

2008-09-26

Emacs tidbit

I've been using emacs regularly for around one year now, and I am always running into reminders that I need to consistently learn more about what's available to you in emacs. It's frankly a bit hard to schedule getting stuff done in emacs with learning more about what's available through (or in) emacs, but the return value for learning a bit more about what you can do is very high - there are things that can make you magnitudes more productive just sitting around waiting to be found.

A small tidbit, from earlier today: kmacro-insert-counter inserts the number of times a macro has been called into the buffer.

I was debugging some methods, and had a bunch of similar calls that I wanted to log info about to files named in a sequential order (foo1.txt, foo2.txt). I just needed to do a diff of the output. I made a little macro that used kmacro-insert-counter. Wasn't the most robust debugging solution, but then again I wasn't in need of one at the time, just needed to see some data as quickly as possible.

There have been a few other times where I've wanted something like kmacro-insert-counter. It's not something that's useful (to me) on a very regular basis, but when it's handy, it's really handy. Emacs is chock-full of stuff like that, and if you're familiar with what's there, combining all the little convieniences into one big project-or-file-specific convienience is easy, and allows you to do non-trivial editing tasks much faster than I've been able to accomplish with other editors.

2008-09-24

CherryPy doesn't get enough love.

I tell you, it's true. CherryPy doesn't get nearly enough love on the web. Everyone hypes up django and RoR, but barely any mention of cherrypy.

Now, I'm not trying to rag on django, or RoR - they're both wonderful tools - however, I've found my match (so far) with cherrypy.

CherryPy really isn't a web framework - it's more of an HTTP framework. If you're writing a web-application, or website that calls for a framework, then it's fairly easy to pick and choose each part of what makes up a framework, and set it up how you like. Granted, it's normally possible to customize all (or a large portion of) the individual tools that a framework like django uses, but it seems to me that when a lot of people use a framework, they end up never exploring other options for doing what they need to do. Really though, the point about having to pick-and-choose what tools you use for templating, interacting with the database, etc is a minor one.

The real benefit that I get, as a developer, from using cherrypy is the ease with which I can perform iterative development with a minimum amount of learning a bunch of new stuff. Ruby on Rails can make iterative development pretty easy, but I have to learn:

  • The RoR directory structure.
  • How to use RoRs default templating system.
  • ActiveRecord
  • RoRs quirks.

That doesn't seem like much, but really it's quite a bit of stuff. If you've got what your building entirely planned out, already have the design done, and it's fairly large, it can be really nice to just have a place to drop all that stuff into.

That's rarely the case for me. Many times when I want to make a web-application, it's pretty small. Using RoR feels like overkill, there's so much stuff generated that I won't ever use. There's different configuration options for tons of different stuff, and so on.

As an example, I recently implemented a tool for downloading Ubuntu packages and their dependencies as a tarfile. It's about 150 lines of HTML, 80 lines of CSS, and 150 lines of python, plus a smattering of javascript making use of jquery. It doesn't touch a database at all, it's a simple app. It's simple enough that I didn't feel the need to use a templating system - the few methods that generate dynamic content do it through yield statements. Sure, having markup in method code is generally a bad thing, but it is a very small amount of markup and it makes it very easy to know exactly what's going on without having to look at a whole lot of files. This is only a good strategy for simple cases - if the method logic needs to get more complicated, or the markup needs to get more complicated, than the yield statements can (and should) be refactored out into templates.

CherryPy lets me do this. It doesn't care, and it makes it abundantly clear that it doesn't care how the "exposed" method creates what it will be sending back to the user. Need a templating system? Find one, learn how to use it, integrate it into your app.

My tool for downloading Ubuntu packages and their dependencies is one python file, plus the directory structure for html files, stylesheets, and javascript files. CherryPy has a server built into it, that has more than met my needs so far, and it's configuration is right there at the bottom of the file after "if __name__ == '__main__':".

When I first started fooling around with CherryPy, I was a bit confused. The online docs weren't that great, and finding info about configuring the server was difficult.

Then I opened up the code for CherryPy itself. It's well written. It's well documented. It's pythonic as all fuck. I don't need documentation, I can actually read and comprehend the code for CherryPy without much of a strain, without being familiar with the codebase. Oh my.

So in short, cherrypy allows me to:
  • Only do "web frameworky" stuff when I need or want to.
  • Not have to be familiar with how to turn the "web frameworky" stuff off in order to do the above
  • Iteratively develop my web-apps at a sane pace, building them as they proceed.
  • Always write a web-app that I know intimately.
  • Understand what's going on under the hood due to the quality of their source

And those are a few of the reasons that I have fallen in love with cherrypy.

2008-09-21

Cloned human bodies for harvesting would be awesome.

Charles Krauthammer recently wrote an article about the possibility of cloned human bodies, meant for organ harvesting looming on the horizon. The article is largely devoid of substance, basically amounting to not much more than fear of the unknown.

Let's take a look:

"These human bodies without any semblance of consciousness would not be considered persons, and thus it would be perfectly legal to keep them 'alive' as a future source of organs."

"Alive." Never have a pair of quotation marks loomed so ominously. Take the mouse-frog technology, apply it to humans, combine it with cloning, and you are become a god: with a single cell taken from, say, your finger, you produce a headless replica of yourself, a mutant twin, arguably lifeless, that becomes your own personal, precisely tissue-matched organ farm."


This sums up the argument against pursuing this - that we would be "playing god". I would argue that it's no more playing god than creating antibiotics is.

Furthermore, the quotation marks around "alive" are not ominous - they are there because the meat is just meat. It is not "alive" in the colloquial sense - there is no consciousness, no mind. There is no "soul", whatever that is. All it is is cloned meat.

I can see why the imagery of a body in a vat, growing organs waited to be supplanted into humans could strike someone as dark, or even foreboding, but I can not see a moral argument against it - at least not one that holds any weight.

As far as for what the intended argument is (in all likelihood) - that this will lead to immortality OH NOES, I don't see a problem with that. I'm willing to bet that most people will willingly choose to die after a while, and am further willing to bet that this won't grant immortality anyhow. Overpopulation? We're already overpopulated, and have been needing to look towards space colonization for a decade or so (at least) now. Humanity has a whole host of problems ahead of it, and although it could be argued that this cloning stuff may not be the best thing to focus on, it's far from humanities primary focus - and I would view the ability as a net positive, not negative.

I don't see this guy railing against any of the other methods that humans use to fight death.

Bah.

2008-09-18

People should have a basic understanding of the prevalent technologies.

Tim O'Reilly, recently gave a keynote that touches on a point that I've been thinking about for a while - there are a lot of software startups, and a lot of social software, but not too much focus (or perhaps I just haven't seen much of a focus) on people using or creating software (or technical skills in general) to really try to improve the lives of people around them.

Maybe I'm just not looking in the right spots.

There's a couple large points here, and it might get kinda rambly so bear with me (or just slap a TL:DR on it and ignore.)

Computers are arguably the most important things in most peoples lives, regardless of whether or not they realize it. We rely on computers, and more specifically networks, to drive a lot of our business - chances are, if you get a paycheck, there's a computer somewhere in that process. I'd guess that it's probably the case that your paycheck is reliant on a computer or set of computers.

However, most people do not have even a basic understanding of how computers work. It can be argued that most people don't have a need to, but I would disagree. Most people that I've met know how a car works, on a high level of abstraction - they know how to operate one, they know that there is an engine that works by burning fuel, and they probably know that the ignition of the fuel pushes a piston down. They probably know basically how the brakes work, etc. On the other hand, most people do not know basic things about how computers work. They do not know that there is basically a whole bunch of abstraction / translation layers that take streams of 1 and 0s and turn them into applications. They don't know how computers communicate over a network, even at a very high level of abstraction. They don't understand that the programming languages that people use to make applications are basically descriptions of methodology. They don't understand how the applications and services they use the most work.

Take google for instance. Google is the de facto search engine at this point in time, and it's what a lot of people (myself included much of the time) turn to first when trying to find something. If you have a very basic understanding of how google finds pages, it makes it a lot easier to search for things. If you know that what you want to search for tends to be words that you would expect to appear in the page you're looking for, and not necessarily the actual topic or specific thing that you're looking for, it's a lot easier to get good search results. Granted, google is very good at returning relevant results to people regardless of their understanding of how their search works - but the point still stands.

People need to understand this stuff, at least on a basic level, for a plethora of reasons.

Another example: I have had to explain to multiple people that you do not need to purchase a wireless internet package to get wireless internet. You can purchase whatever kind of internet service you like, and have it be a wireless connection, all it requires is that you have a wireless router. People are getting ripped off by ISPs selling wireless packages, it's silly.

Right now, we are in a wierd situation, at least in the US. The economy is bad and getting worse, and we have an (unfortunately) rather poorly educated populous (in my opinion). The education system is largely pretty horrible, and we have a culture that encourages people to not apply critical thought.

On the bright side, we have this internet technology that enables us to share knowledge faster and better than ever before. Almost anything that you want to learn about, you can learn about with the power of the internet. I know this, and probably so does anyone reading this, but the sheer vastness of the information available to people is largely unknown to the average person.

I'd guess that if people knew how much information was available to them (and on a larger scale, just how rewarding learning is), that the worlds - and specifically the U.S.s - situation would change for what I would consider to be "the better" fairly quickly. There is, at this point in time, practically infinite ways for people to collaborate with each other to do anything from learning something to providing for their basic living needs.

To attempt to get people interested in teaching themselves, and hopefully get people to start being more interested in what they can do to make their lives (and the lives of those around them) easier, I intend to start something of a "zine" - a self-published magazine. I'm going to collect some of the info freely available online, and do some writing myself, print it out, and go put in on people's doorsteps.

I figure the "first issue" will have some basic information on how computers work, how computers communicate over a network, some information about open source software and why it's a good thing, some information about Ubuntu linux, perhaps some info on how to tell if your ISP is throttling your data or modifying your pages. I encourage people to do the same if they think it's a good idea (or perhaps we could collaborate on content?). I'll have an email address set up that people can send an email to if they'd be interested (or entirely disinterested) in recieving further issues, and also include a request for articles on how to do something (really anything DIY) from anyone who's technically inclined.

I'm not sure if this will be effective at all, but it's better than doing nothing and it can't hurt.

2008-06-20

Part of the reason I prefer to work in linux

One of the most common complaints that I've heard from people about really learning their way around linux is that they don't like having to remember long cryptic command-line arguments. Granted, these days you can get by decently well without using the shell, but then again, things in the linux world are not always too well polished, there's a decent amount of variation between distros, etc.

One thing that's almost constant is the presence of BASH, and everything being able to be launched from a shell. Most things also print useful information to the shell, and you can use this to your advantage.

Here's a situation that I was recently in:

I'm doing development on two projects right now, the extendible-tetris thing, and a site for the art-collectiveish house I live in. The extendible-tetris thing has only been going on in the background, since I've been focusing on the site for the house (we make a lot of music and art,
want to put it online freely available and have a simple paypal donate/buy and get a nice DIY made CD/DVD combo, or some other art for cheap). Now for this house site, I have a tower running ubuntu server that's connected to a wireless router that has no access to the internet - it won't be viewable online until the first iteration of it is ready to go, and the other people in the house can use the development version and provide feedback, etc.

We also have an internet connection with it's own wireless network. Occasionally, I need to install something on the server, and I need to download some source packages, switch to the private network, upload them, ssh into it and compile / install. Sometimes I run into an unmet dependency (I was pretty thorough setting the server up, but you can't catch everything), and I need to do this multiple times. When I'm working on stuff, I'm mostly in emacs and the shell, and don't want to take my hands off the keyboard very often. There's a repetitive task, and I don't want to move my mouse to switch networks then sit and wait over and over. I also don't want to type out the iwconfig commands anymore than I have to.

So, I have this well-defined task that needs to be done many times - make sure I'm on the right network, upload a file to a server, then ssh into that server. Using the tools provided to me by BASH, I can turn this from myself performing many small commands manually, to myself performing one command manually that does all the rest for me:

[disclaimer: I am far from being a BASH-scripting guru. There are probably things that I should be doing differently. Feel free to point them out.]

First, I make a small script to report back the name of the wireless network I'm currently on:


#!/usr/bin/env bash

#wwhich - print out which wireless network we're currently connected to
iwconfig 2>/dev/null | sed -n -e 's/.*ESSID:"\([^"]*\)".*/\1/p'


That's a little nasty, but it works.

Next, we have a script to switch between two wireless networks:


#!/usr/bin/env bash

#wswitch - switch between two wireless networks.

#which essids we're dealing with
first="wnetwork1"
second="wnetwork2"


current=`wwhich`


if [ $first == $current ]
then
sudo iwconfig wlan0 essid $second
current=$second
else
sudo iwconfig wlan0 essid $first
current=$first
fi

#print out the current network
echo "$current"


This is not a general-solution script - it's for this specific problem. If I run into something like this again (where I need to be switching between two wireless networks), I can just change the names of the variables.

Next, we have the upload and ssh script:

#!/usr/bin/env bash

target="essid-name"
current=`wwich`
user="auser"
host="192.168.x.x"
dest=":~/incoming"

#make sure we're on the right wireless channel
if [ $target != $current ]
then
wswitch
fi

#make sure we call the right scp command
if [ -d $1 ]
then flag="-r"
else flag=""
fi
scp $flag $1 $user@$host$dest
ssh $user@$host


This will only work if you have ssh set up to use public keys. Which you probably do.

Now, if we can ignore my probably pretty shoddy bash-scripting skills, we get to the more major point: A task that previously took around 30 seconds - plus the time to upload - each time I needed to do it now takes around one second, plus the time to upload. You can write all kinds of time saving utilities for yourself, put them in a directory, and add that directory to your $PATH in ~/.profile. This is a large part of the reason why people like me like the shell so much, and prefer working in linux, or a unix-like environment - if I don't want to, I don't have to waste my time with repetitive tasks. I can automate them. If I felt like it, I could bind this to a keystroke.

Don't like having to remember strings of commands? Throw them in a script. You have the capability to automate just about anything on your system, so do it. Don't like having to remember certain paths? Export them into a variable in your ~/.profile. Et cetera.

With a powerful shell, in combination with good utilities, I can turn the tools that I use to accomplish things into more powerful, more general, or task-specific tools. It took me around 20 minutes to write the above scripts - and it probably only took me that long because I'm not extremely familiar with BASH-scripting, although I have recently started writing many more scripts. It will probably save me more than 20 minutes of time over the course of the next few weeks.

2008-04-29

So maybe it wasn't so simple after all.

Well, as I said previously, I did come up with a way to accomplish what I was trying to accomplish.

Basically, what I wanted was to be able to say: "This group of options under this tag are a logical set, and only one of them may be considered active at any given point in time"

This is what I converged upon:



function UniqueSelection(id, extras, allowToggle, childTag) {
if(!childTag)
childTag = 'li';

var parent = document.getElementById(id);
var items = parent.getElementsByTagName(childTag);
var currentItem = false;

function choose(choice) {
if(!currentItem) {
currentItem = items[choice];
currentItem.className = 'active';
}else{
if(currentItem != items[choice]) {
currentItem.className = 'inactive';
currentItem = items[choice];
}

if(allowToggle && currentItem.className == 'active') {
currentItem.className = 'inactive';
}else {
currentItem.className = 'active';
}

}

}

for(var i = 0; i < items.length; i++) {
items[i].onclick = (function(id, func) {
if (!func) {
func = function() {
return true;
};
}

return function() {
choose(id);
func();
};
})(items[i].id,
(extras ? extras[items[i].id] : false));
if(items[i].className == 'active') {
currentItem = items[i];
}
}


}


This version does exactly what I need it to, although the creation syntax is a little funky if you're not used to passing objects as parameters:


//to create just a list, no extra actions
justAList = new UniqueSelection('simple-list');

//to create a list where three elements have extra actions:
normalUse = new UniqueSelection('normal-list',
{ 'first-element': firstElementsFunc,
'second-element': secondElementsFunc,
'third-element' : thirdElementsFunc});


This version also doesn't loop through the child elements on every click - it just works with the current element, which means that the choice function shouldn't slow down on large lists.

I'm not sure if this is the javascripty way of accomplishing this, but it works for me. It's not exactly efficient as far as memory usage goes, but it could be a lot worse (and it works). I'm still learning javascript, and it hasn't quite seeped entirely into my brain yet, but it's getting closer.

2008-04-28

A simple way to manage tab-lists, and other unique selections.

So, in the current project I'm working on, I've run into a few situations where I want to have a list of options, only one of which is allowed to be "active" at any given point in time. Examples: tabbed interfaces, editing "modes" for the shape and grid editors that I'm working on (you can be in "deleting" mode or "inserting" mode or "setting center" mode, for instance).

Basically, all I needed was to be able to say "This list of stuff is only allowed to have one thing selected at once", while showing the active selection with css.

As a first attempt, I wrote the following little bit of javascript:

function UniqueSelection(id) {
function toggle() {
UniqueSelection.active.className = "inactive";
this.className = "active";
UniqueSelection.active = this;
}

var listItems = document.getElementById(id).getElementsByTagName('li');

for(var i = 0; i < listItems.length; i++) {
listItems[i].onclick = toggle;
if(listItems[i].className == 'active'){
UniqueSelection.active = listItems[i];
}
}
}


Which works, but has one big flaw: you can only have one UniqueSelection at a time, and is a pretty ugly solution anyhow.

The following code allows you to have as many UniqueSelection elements as you want, and is shorter, clearer code:


function UniqueSelection(id) {
var listItems = document.getElementById(id).getElementsByTagName('li');

function toggle() {
for(var i = 0; i < listItems.length; i++) {
listItems[i].className = 'inactive';
}
this.className = 'active';
}

for(var i = 0; i < listItems.length; i++) {
listItems[i].onclick = toggle;
}
}


This does have some downsides - for one, it might have a visible delay on long lists. For two, you can't have multiple class names on your 'li' elements. For my purposes, this is fine - and I think that if you're using ul's in a semantic manner, it shouldn't be a problem.

The code above does show some interesting things about javascripts scoping rules though.



Update:

With a couple more lines of code, we can allow for both lists where a selection must be unique and a selection must be active, and lists where a selection must be unique, but where the current selection can be turned off without making another one:


function UniqueSelection(id, allowToggle) {
var listItems = document.getElementById(id).getElementsByTagName('li');

function choose() {
for(var i = 0; i < listItems.length; i++) {
if(listItems[i] != this)
listItems[i].className = 'inactive';
}

if(allowToggle && this.className == 'active') {
this.className = 'inactive';
}else{
this.className = 'active';
}

}

for(var i = 0; i < listItems.length; i++) {
listItems[i].onclick = choose;
}
}




Update 2: The above function clobbers the onclick attribute, and in some cases I need it to not do so. Getting it to not clobber is turning out to be frustrating though. . .


Update 3: Got it working, through a bit of education and head-banging. The new code and an explanation of what was going on deserves it's own post though. Will write it up later.

2008-04-24

More editor UI improvements

Most of what I got done today was improvements to the different "modes" you can be in while editing shapes - by mode, I simply mean "adding blocks" "deleting blocks" or "setting the center of the shape". Worked on styling li items as buttons, realizing that it is very easy to use too much markup to describe something on the page, and remembering that to write solid javascript, you really need to code as if everything in the world is out to get you.

On that last point, it's always a good practice to code defensively, but I've noticed a greater need for it in javascript, due partially to the nature of the language, partially to differing implementations in different browsers, and partially due to the inconsistency of how different libraries implement their functionality. For instance, I need to pass data about shapes, game rules, and such back and forth between the client and server. I've been using JSON for that, and it works quite well - but the javascript file provided by json.org breaks prototype. The solution to this is to use the newest stable version of prototype, which has JSON support built in. Or you could always roll your own JSON encoder / decoder - it's not really all that complicated.

On the rails side, I've just been using YAML.load, since JSON tends to be valid YAML (god, not to be confused with YAML...), and I was running into some issues with getting rails' json support working correctly.

Another thing that bit me about javascript was NaN being typeof "number". This is documented, and pretty common among languages, and there's a isNaN test, but for some reason, I tend to never expect it. Bah.

2008-04-23

Improving the color picker.

Today, I improved the color-picker for the shape and removal-rule editors. The color-picker itself is very simple - just a collection of square divs that you can click on to change the color of the next blocks you click on in the shape grid.

Prior to today, I was just using a simple ROYGBV list, packing it into an array and rendering the divs server-side. I'm still rendering the divs server side, but I'm iterating through color values, stepping from 0 to 255 by 64. This provides a nicer range of colors to choose from.

Ideally, I'd like to implement a photoshop-style color chooser, or at least order the divs into blues, reds, and greens (I may do this here in a day or two) - but this can wait for a bit.

2008-04-22

Getting more familiar with CSS

Today I realized that I absolutely suck at using CSS. It's not something that I ever really spent a lot of time working with, and I've always had a bit of a hateful relationship with web-development.

For a long time, doing any sort of serious web development work was nothing but a pain in the ass - there were so many shitty hacks around browser inconsistencies that you could probably live off of the print-up of them for a few months. Recently, things have gotten quite a bit better, and frankly the only browser that really plays "bad" when it comes to standards is IE - and even it has gotten lots, lots better.

So anyhow, doing CSS work is not nearly as painful as it used to be, although for someone who is not a designer type (like me), it can be a bit hard to make a site look pretty, not to mention that there are a bunch of "accepted" ways of doing things that may not be really obvious, like using lis for tabs.

Three things helped me out a great deal - one was this talk by Douglas Bowman. While he didn't spend too much time talking about actual CSS code (it was assumed that you were already familiar with the workings of CSS), some of the points made were very good, even if they seem a bit obvious, like "Design your site in something else - pen & paper, photoshop, the gimp, whatever. Don't design your site using CSS because then you'll be limited to how much CSS you know, instead of having to learn more to get your site looking how you want it."

The second thing that helped me out a whole lot was YAML builder , which is a tool for designing multi-column layouts using YAML (not to be confused with YAML). While I won't be using YAML for my extendable tetris game, the tool was really nice for getting a look at how to properly structure an XHTML skeleton for doing a layout, as well as some CSS techniques.

One last useful thing I found for getting more familiar with CSS and how it's used was Eric's CSS Reset Reloaded, which basically sets everything to nothing, as far as CSS goes. Not only does this get rid of a good bit of cross-browser pain, it also forces you to manually set up, well everything - which is really useful for learning.

You see, I'm fine on implementing the back-end stuff for this site. The technical functionality of the web-app I'm working on really isn't that hard for me, and I can test most of it (using, you know . . . tests), however on the front end the usability and functionality of the site is more or less inherently tied to the presentation of the site - and you either have to know your way around CSS, or resort to using some table-layout monstrosity shit out by Dreamweaver that will be hell to maintain and ugly as satans balls to anyone who's looking at your source (you included). I refuse to take that second option.

Anyhow, end result was that my design for the shape editor got much cleaner, and a bit more modular - which is never a bad thing.

2008-04-21

An extendable tetris.

So, I've been working on a pet project of mine - a web-based, expendable tetris game. I want to allow people to create their own shapes, and their own rules for the removal of blocks from the game grid.

I'm doing in in Ruby on Rails, and so far I have an editor for the shapes, and will be working on the game mechanics more here in the next few days.

There's nothing live yet (I don't even have a domain for it, I may end up hosting it off of my own machine for a bit at the start...), so even if this sounds really interesting to you, too bad. If you are reading this, and would be interested in testing when I get something . . . testable done, just comment or drop me an email (it's on my profile page)

It's a good exercise in abstraction - there are a whole lot of games that are very similar to tetris. Blocks fall, stuck together in a shape. Sometimes blocks get removed from the screen. They may get removed when they fill a certain shape (in the case of classical tetris, one entire row), or maybe when a certain number of the same colored blocks come into contact with one another. Blocks might fall down after removal as if gravity was in play, they might not, etc.

Some things I'd like to implement:

* I'd like people to be able to mark existing shapes, or game rules for use in a game they are defining.

* I'd like people to be able to rate games.

* I'd like to be able to attach different attributes to games, or to shapes - for instance, a game where gravity was skewed a bit towards the left, making your piece drag. Or maybe adding a rotational velocity to certain shapes.

I haven't really been working on this for very long - I need to get a base amount of pluggable functionality implemented (which is a good bit of javascript and rails work), but once that's done the rest of implementation should move pretty fast. I guess I'll post updates as I move along here, since I don't really use this blog for all that much.

2008-04-17

This programmer still reads books.

Joel Spolsky recently wrote:

Programmers seem to have stopped reading books. The market for books on programming topics is miniscule compared to the number of working programmers.

I certainly can't speak for all programmers, but as for myself, and every programmer I know in real life, we are still reading books. However, we may be reading less books.

I would guess that up until a few years ago (more, depending on how you look at it), books were the only good way to get a start in programming, or in a new programming language. The information available online was simple not good enough to give you anything more than a cursory glance at the process of software development, much less on specific languages and frameworks. Internet speeds were slower, the push for open content wasn't in nearly as much of a fervor, and there were much fewer programmers.

These days, a lot of people are picking up a scripting language, or have a need to learn some basic programming skills, and (at least partly because of this), there is a lot of information readily available about such things online. Hell, there's an entire culture surrounding programming blogs (and sure, blogs in general).

Right now, if I want to get a feel for a new framework, or a new language, or for software engineering or computer science in general, there is a whole plethora of pretty high quality material available to me online for free. Books on these subjects are expensive, and I am nowhere near rich. However, if I use a language frequently enough, I often want a dead-tree book as reference material. For example, I have gotten very heavy use out of Javascript the Definitive Guide, Agile Web Development with Ruby on Rails, and Python in a Nutshell.

If I need to remember, or look up how to do something in one of these subjects, I go to these first.

Similarily, books like SICP, The Mythical Man Month, TAOCP, The Art of the Meta Object Protocol, - and many others, while not necessarily about any one programming language or framework, are filled with things that programmers tend to find interesting, and are worthy of being read if one is wanting to improve their skill as a programmer. Some of these great reads are
available to read online for free, some of them are not.

Please note that this shouldn't be read as critical of the upcoming stackoverflow.com. I think that it would be very nice to have a popular, high-quality replacement for abhorrent beasts like expertsexchange - however, I don't think that it'll be replacing books anytime soon for me, especially not in areas that are more general than specific programming languages and frameworks.

2008-02-11

Some things about linux I wish I knew a long time ago

So, I've been using linux for a while. If you want it to be, it's a constant learning process - always finding new tricks and shortcuts and so on.

Here is something that I wish I had known when I started using linux:

If you install a package on a .deb-based system, and want to know what files it installed, you can check with dpkg --contents /path/to/package. On Ubuntu, /path/to/package will normally be /var/cache/apt/archives/packagename. When this is useful, it is extremely useful.

Also, I wish that I would have done a man bash much earlier in my linux history. There's a lot of time-saving stuff in there.

2008-01-29

Reading code.

I think that reading other people's code has been the one thing that has
furthered my ability to program the most in the shortest timeframes.

I have learned something from every (non-trivial) collection of code
that I have read that was not written by myself.

Particularily, I feel that I have gained the most from deciphering
what I would consider to be bad code - it shows you what types of
patterns lead to writing unmaintainable code. Of course, the question
of what makes a particular program _bad_ or _poorly_written_ is a bit
subjective at best.

I would argue here that bad code is code that is
hard to understand, even with a firm knowledge of the language that it
has been written in, and an appropriate amount of time to brush up on
any domain-specific knowledge you may need to know to understand the code.

There are a few more subjective terms in the definition given here for
bad code, but I'd be delving into philosophy that doesn't really relate
to the point at hand. The point is that if I know language X well enough
to feel comfortable writing a fairly complex program in it, and I have a
few weeks (at the very most, for most things) to read up on domain-
specific knowledge, and I can't understand what someone else's code,
I consider it bad code.

It could be argued that there are cases in which someone could be thrown
off by the use of a design pattern that they haven't read yet, but I think that's
a bit of a bullshit argument. For one thing, if someone is really interested
in being able to express their programs better (in order to write better
programs, or in order to be able to write and manage complicated programs),
they will run into the concept of design patterns fairly quickly. For
another thing, if the code is well written, it will either still be
obvious what's going on. If the code is well-commented, there will be
easily searchable ideas to help the reader get a clue what's going on,
and the readers reaction will be something like "Oh, well that's a good
way to do that."

So saying someone could be thrown off by seeing use of a design pattern before
being familiar with it is true, but the probability of it being true decreases
as the readers experience increases (assuming that the reader is actively
studying the "art of programming"), and also decreases if the code is well-written.

I do not make these cases from code that I have written, but from code that
I have read, and understood. Code that was well-commented, especially in
code that dealt with domain-specific knowledge was incredibly helpful in
figuring out what was going on. Code that was structured in such a way that
methods did more or less one cohesive action, and objects represented one
cohesive group of data and the methods associated with it made the understanding
of code that had many complex relationships much easier to handle. Code that
had only one of these qualities was harder to understand, and code that
had none of these qualities was even harder to understand - sometimes I would
have to map out execution with a lot of logging, or with pencil and paper to
be able to obtain a grasp of how the system operated as a whole.

I should note that I would include variable and method names as being a
form of comment - the computer couldn't care less what characters make up
the variable or method name, they only serve as a reminder to yourself and to
other programmers of what the variable or methods purpose is.

Good code is just the opposite of bad code - it's very clear. Variables and
methods have meaningful names. Even without extensive knowledge of the domain
that the program is written for, it is possible to search online for the
specific knowledge needed to be able to make modifications to the source.

Writing good code is a lot of work - and it's not easy at first. It could be
argued that it's never easy. It is magnitudes harder than just writing code
"that works," at least for me, however I find that having a long design phase
before I start coding decreases the amount of work that it takes.

What I consider to be "the best" code I've read has never been something that
appeared that it was written off the top of someone's head. It always seemed
apparant that whoever had written it had taken into account that other people
would be reading it - possibly themselves at a later date. It also always seemed
like the way that the code worked, the ways that the object represented were
defined, and the ways in which they interacted with each other made sense.

Duh, I guess, and you can pick up on all these things by reading good code.

I said earlier that I thought that I had gained more from reading poorly written
code - and that's true. Poorly written code has shown me that even if you can
hold a problem entirely in your head when you write the code for it, you may not
be able to remember all the details of that problem when you go to look at it a
few months down the road. It's shown me that idioms that may be entirely clear
to me may not be clear to someone else - and vice versa.

Reading poorly written code (as well as well-written code, but less often) has
also pushed my knowledge of a language into the darker "relying on quirks" part
of it. For example:

Q: What happens if you cast the result of trying to take the sqrt of a negative
number to int in C++?

A: You get negative maxint minus one.

This may be really common knowledge among people who use C++ a lot. I haven't
used it a whole lot for years - I ran into this translating some C++ into python
for a client. The code was using this result in a less-than comparison, and
relied on this behaviour as a type of error-filtering. This is not the correct
way to handle this.

Anyhow, if you're looking to increase your ability to program, you should read
other people's code. Often. Regardless of if it's well or poorly
written. Actually, you should _understand_ other people's code - and that may
not involve just reading it. Don't have any code to read? Pull the source for an
open source app you use a lot, especially if you've had an idea that you think
would make it better. Modify it, and submit your contributions.

2008-01-02

Locking a section of text in emacs

Today, I was talking to a friend about things that would be useful for text editors. One feature that we thought was missing was the ability to select a region of text, and lock it so as to prevent accidental editing without unlocking it.

This was rather trivial to add to emacs:


(defun lock ()
"Make a section of text read-only, and add an overlay so
it's apparent"
(interactive)
(let ((start (region-beginning))
(end (region-end)))
(overlay-put (make-overlay start (+ 1 end)) 'face
'(:background "light slate gray"))
(put-text-property start end 'read-only t)))

(defun unlock ()
"Unlock a region of text, and remove its overlay"
(interactive)
(let ((inhibit-read-only t)
(start (region-beginning))
(end (region-end)))
(remove-overlays start (+ 1 end))
(remove-text-properties start end '(read-only))))


Just bind lock and unlock to some keys, and there you go - makes a region of text uneditable, and adds an overlay to it.