Archive for September, 2007

Just Terrorism?

Back in August I wrote about the idea that in a democracy we all share responsibility for the actions of our government. Frank, one of my three loyal readers (and I do appreciate all of you), commented that this was a good way to rationalize to terrorism, and I agreed. Frank replied again to say that he found that to be unconscionable.

It’s an interesting issue which deserves some more thought, so I’m going to respond in a full blog posting. I think it’s very clear which conclusion we want to reach: we want to consider terrorism to be morally unacceptable. I still think that we have to keep the premise: in a democracy, we are all responsible for the actions of our government. We can’t disclaim our leaders simply because we voted for the other person. We are all part of the same society.

If our government invades another country, then I think the people in that country have a moral right to resist the invasion. Note that I’m not saying that they should resist, and I’m also not saying that our government must never invade another country. I’m just saying that they have a right to resist if they choose, just as we would have the right to resist an invasion of our country.

So if they have a right to resist, and if we all share moral responsibility for the actions of our government, then do they have the right to attack us directly, even if we are not ourselves invading, and even if we personally oppose the invasion? That is, do they have the right to launch a terrorist attack on the citizens of our country? After all, we share morally responsible for the invasion, and they have the moral right to resist that invasion.

The most obvious thing to springs to my mind here is Just War theory, which an old tradition rooted in early Christian thinkers, notably St. Augustine and St. Thomas Aquinas. Just War theory discusses both when it is morally permissible to start a war, and what conduct is morally permissible during war. The best book I’ve read on the subject is Just and Unjust Wars, by Michael Walzer. He examines some interesting cases like the French partisans during World War II. Were their acts of resistance, which in many are similar to the actions of the Iraqi resistance today, justified or justifiable?

Just War theory draws a clear distinction between civilians and military personnel. During wartime, attacking military personnel is permitted. Attacking civilians is not. So Just Ware theory is clear: terrorism is absolutely immoral, even if the people you are attacking carry a moral responsibility for the war.

Is Just War theory valid? It’s difficult to say. Warfare has changed considerably since the days the theory was developed, and has become to a degree the war of all against all. Can the actions of the people who willingly grow the food which is purchased from them and shipped to the soldiers be entirely innocent of the actions of the soldiers? I’m not sure the answer is wholly clear.

Still, the distinction between soldiers and civilians makes sense, and I’m willing to stick to it for now. So terrorism is morally unacceptable. Thank goodness: we have reached the desired conclusion.

It follows that the Islamist theorists who justify terrorist bombings by arguing that every Israeli is morally responsible are wrong. They are right in saying that every Israeli is at least partially responsible; they are wrong in saying that this justifies terrorism. There is no justification for terrorism.

Of course it also follows that attacks on soldiers are morally acceptable, and it follows further that we should not use the name “terrorism” to describe such attacks. For a time the U.S. press fell into the trap of describing bombs aimed at U.S. soldiers as terrorist attacks. More recently they have been referring to those bombs correctly as armed resistance to an invasion. Similarly the attack on the U.S. Marines in 1983 in Lebanon is sometimes incorrectly referred to as terrorism; that, too, was armed resistance, not terrorism.

Comments (23)

Tax Refunds

One thing Hofstadter discusses is reasons to be irrational. I was recently thinking about this in the context of tax refunds. In the U.S., if you underpay your taxes during the year by less than $1000 or so, you can just pay the difference on April 15 and all is well. (The total amount you may underpay and avoid a penalty depends on how much tax you paid last year. The rules are a bit complicated and I don’t remember them. Don’t take tax advice from some random blog.) So if you are fully rational about money, and you have a steady salary, you should calculate the witholding amount at the beginning of the year to ensure that you owe a small amount of money at the end of the year. If you don’t underpay–if you, in fact, overpay–then you are effectively giving the government an interest free loan of the amount of your overpayment. There is no reason to do that–if you want to give the government some money, just do it, don’t do it by giving them an interest free loan which they have to repay.

Nevertheless, most people do in fact overpay, and receive a refund when they file their tax return. Not only that, most people are happy when they get their refund. That seems crazy at first glance. Can it ever be rational?

The answer is yes, and it is clear once you realize that people are not unitary beings. We contain multitudes, and those component parts are not all aligned with each other. (Peter David’s version of Jamie Madrox, the Multiple Man, in X-Force comic books is an amusing example of this. Madrox can split himself into many different duplicates of himself, but those duplicates don’t necessarily agree on what to do.)

Rationality is a complex thing. Some people have a tendency to spend the money they have when they have it. If they buy something they don’t need, that will prevent them from saving to buy something expensive that they do need. People who know that they have this tendency can decide to force themselves to save by putting the money out of reach through various mechanisms, one of them them being income tax witholding. This will let them save up enough to purchase something expensive, which they would not otherwise be able to do.

That is: few of us are fully rational all the time–in fact, when considering the troika of money, food, and sex, scarcely anyone is fully rational about all of them. It is rational to use external mechanisms to compensate for your known irrationality.

If you like, you can think of this as using your long-term planning abilities to defeat your short-term instincts.

Comments (1)

I Am a Normal Loop

There is nothing here about linkers! OK, there is one thing: at some point, I hope soon, I will pull the linker postings together into an essay posted with my other essays (which I wrote before starting this blog). I’ll mention it here when I do that.

Now back to my previously scheduled blog, which focuses, like a laser, on whatever I happen to be thinking about.

I recently finished Douglas Hofstadter’s book “I Am a Strange Loop.” I enjoyed the book, although in many ways it was a less interesting, more personal, rework of “Godel, Escher, Bach.” Since that book came out more than twenty years ago, it is striking that he is still sounding the same themes.

The main new idea in this book was an emphasis on strange loops. Hofstadter tries to use strange loops as a way that syntax turns into semantics (here syntax means simple rules, semantics means meaning; physical chemistry is syntax, human emotion is semantics). The canonical example of a strange loop is (of course) Godel’s proof that Principia Mathematica (PM) is incomplete. The loop is that Godel discovered a way to model the rules of PM within PM itself. This is in a sense precisely what PM was designed to prevent, with its heirarchies of set classifications. When Godel was able to represent PM within itself, all those heirarchies fell apart.

Hofstadter would like to say that this loop turns the pure syntax of PM into semantics: simple symbol manipulation turns into the rules of PM. He argues that each of us has a strange loop of some sort within ourselves, which is what gives us our semantics.

I don’t personally find this sort of argument to be convincing. While in general I certainly agree with Hofstadter’s world-view, I find Godelian loops to be interesting exercises in formal logic, but I don’t think they tell us very much about our selves. It’s interesting to note that in this argument Hofstadter is in some ways not that far from Roger Penrose, although of course they reach completely opposite conclusions.

I think our semantics come from our adaptation to the physical world in which we live. This is the lesson of Daniel Dennett’s notion of the intentional stance. Some entities in our world are best explained by assuming that they have personal interests. Entities as complex as humans can not be usefully explained in any other way. That is semantics. Strange loops are an interesting game, not the root of who we are. (The degree to which semantics ties to morality is an interesting question I think I’ve discussed before; Hofstadter does not tackle it in his book.)

It follows from this that Hofstadter would argue that a computer program detached from the physical world can be fully conscious–it just has to have a strange loop somehow embedded within it. As I’ve noted before, I’m skeptical about the claim, although I’m willing to consider it.

Comments

Linkers part 20

This will be my last blog posting on linkers for the time being. Tomorrow my blog will return to its usual trivialities. People who are specifically interested in linker information are warned to stop reading with this post.

I’ll close the series with a short update on gold, the new linker I’ve been working on. It currently (September 25, 2007) can create executables. It can not create shared libraries or relocateable objects. It has very limited support for linker scripts–enough to read /usr/lib/libc.so on a GNU/Linux system. It doesn’t have any interesting new features at this point. It only supports x86. The focus to date has been entirely on speed. It is written to be multi-threaded, but the threading support has not been hooked in yet.

By way of example, when linking a 900M C++ executable, the GNU linker (version 2.16.91 20060118 on an Ubuntu based system) took 700 seconds of user time, 24 seconds of system time, and 16 minutes of wall time. gold took 7 seconds of user time, 3 seconds of system time, and 30 seconds of wall time. So while I can’t promise that it will stay as fast as all features are added, it’s in a pretty good position at the moment.

I’m the main developer on gold, but I’m not the only person working on it. A few other people are also making improvements.

The goal is to release gold as a free program, ideally as part of the GNU binutils. I want it to be more nearly feature complete before doing this, though. It needs to at least support -shared and -r. I doubt gold will ever support all of the features of the GNU linker. I doubt it will ever support the full GNU linker script language, although I do plan to support enough to link the Linux kernel.

Future plans for gold, once it actually works, include incremental linking and more far-reaching speed improvements.

Comments (6)

Linkers part 19

I’ve pretty much run out of linker topics. Unless I think of something new, I’ll make tomorrow’s post be the last one, for a total of 20.

__start and __stop Symbols

A quick note about another GNU linker extension. If the linker sees a section in the output file which can be part of a C variable name–the name contains only alphanumeric characters or underscore–the linker will automatically define symbols marking the start and stop of the section. Note that this is not true of most section names, as by convention most section names start with a period. But the name of a section can be any string; it doesn’t have to start with a period. And when that happens for section NAME, the GNU linker will define the symbols __start_NAME and __stop_NAME to the address of the beginning and the end of section, respectively.

This is convenient for collecting some information in several different object files, and then referring to it in the code. For example, the GNU C library uses this to keep a list of functions which may be called to free memory. The __start and __stop symbols are used to walk through the list.

In C code, these symbols should be declared as something like extern char __start_NAME[]. For an extern array the value of the symbol and the value of the variable are the same.

Byte Swapping

The new linker I am working on, gold, is written in C++. One of the attractions was to use template specialization to do efficient byte swapping. Any linker which can be used in a cross-compiler needs to be able to swap bytes when writing them out, in order to generate code for a big-endian system while running on a little-endian system, or vice-versa. The GNU linker always stores data into memory a byte at a time, which is unnecessary for a native linker. Measurements from a few years ago showed that this took about 5% of the linker’s CPU time. Since the native linker is by far the most common case, it is worth avoiding this penalty.

In C++, this can be done using templates and template specialization. The idea is to write a template for writing out the data. Then provide two specializations of the template, one for a linker of the same endianness and one for a linker of the opposite endianness. Then pick the one to use at compile time. The code looks this; I’m only showing the 16-bit case for simplicity.

// Endian simply indicates whether the host is big endian or not.

struct Endian
{
public:
// Used for template specializations.
static const bool host_big_endian = __BYTE_ORDER == __BIG_ENDIAN;
};

// Valtype_base is a template based on size (8, 16, 32, 64) which
// defines the type Valtype as the unsigned integer of the specified
// size.

template
struct Valtype_base;

template<>
struct Valtype_base<16>
{
typedef uint16_t Valtype;
};

// Convert_endian is a template based on size and on whether the host
// and target have the same endianness. It defines the type Valtype
// as Valtype_base does, and also defines a function convert_host
// which takes an argument of type Valtype and returns the same value,
// but swapped if the host and target have different endianness.

template
struct Convert_endian;

template
struct Convert_endian
{
typedef typename Valtype_base
::Valtype Valtype;

static inline Valtype
convert_host(Valtype v)
{ return v; }
};

template<>
struct Convert_endian<16, false>
{
typedef Valtype_base<16>::Valtype Valtype;

static inline Valtype
convert_host(Valtype v)
{ return bswap_16(v); }
};

// Convert is a template based on size and on whether the target is
// big endian. It defines Valtype and convert_host like
// Convert_endian. That is, it is just like Convert_endian except in
// the meaning of the second template parameter.

template
struct Convert
{
typedef typename Valtype_base::Valtype Valtype;

static inline Valtype
convert_host(Valtype v)
{
return Convert_endian
::convert_host(v);
}
};

// Swap is a template based on size and on whether the target is big
// endian. It defines the type Valtype and the functions readval and
// writeval. The functions read and write values of the appropriate
// size out of buffers, swapping them if necessary.

template
struct Swap
{
typedef typename Valtype_base::Valtype Valtype;

static inline Valtype
readval(const Valtype* wv)
{ return Convert::convert_host(*wv); }

static inline void
writeval(Valtype* wv, Valtype v)
{ *wv = Convert::convert_host(v); }
};

Now, for example, the linker reads a 16-bit big-endian value using Swap<16,true>::readval. This works because the linker always knows how much data to swap in, and it always knows whether it is reading big- or little-endian data.

Comments (3)

« Previous entries Next Page » Next Page »