We need to follow the Amish example

Just a few weeks ago, the world heard the news of the tragic school shooting at an Amish school in rural Pennsylvania. A deranged man entered the schoolhouse, bound and gagged female hostages, brought along torture equipment, and shot 10 of them. 5 died, and the remaining 5 are believed to still be hospitalized.

Back in 1990, a deranged man committed a series of murders near the University of Florida campus in Gainesville. The story mentions 5 people that were killed.

Both were tragic situations. Both men killed people that had their whole lives in front of them. Both shook an entire community.

But look at how the communities responded. The Amish responded like this:

CNN reported a grandfather of one of the murdered Amish girls said of the killer on the day of the murder: “We must not think evil of this man.”

Jack Meyer, a member of the Brethren community living near the Amish in Lancaster County, explained: “I don’t think there’s anybody here that wants to do anything but forgive and not only reach out to those who have suffered a loss in that way but to reach out to the family of the man who committed these acts,” he told CNN.

The Amish have reached out to Roberts’ family. Dwight Lefever, a Roberts family spokesman said an Amish neighbor comforted the Roberts family hours after the shooting and extended forgiveness to them.

An article in a Canadian newspaper the National Post stated that the Amish have set up a charitable fund for the family of the shooter. (Wikipedia)

In addition, the Amish invited the Roberts family to attend the funerals for the Amish girls he killed.

Gainesville reacted this way:

Dianna Hoyt, Christa Hoyt’s stepmother, said Rolling’s execution has been eagerly awaited by the victims’ families. Some will be inside the prison to witness it. . .

Sadie Darnell, who was the police department’s media spokeswoman at the time and developed enduring friendships with the victims’ families, said Rolling’s execution still matters, even if it also provides him more of the notoriety he sought.

“Retribution . . . is important because it represents that our society is holding that person accountable,” said Darnell, now a candidate for Alachua County sheriff. (CNN)

We’ve all heard of murders that have taken place lately. Usually they are accompanied by calls by politicians, victim’s family, and sometimes even clergy to kill the perpetrator. In the days after 9/11, there were reports of anybody that looked Middle Eastern being attacked in several different places around the country.

I have never understood this great desire for revenge. How does that help anyone?

What the Amish did was right religiously and morally. They truly followed the New Testament call to love your enemies and forgive. It is not easy to follow all of Jesus’ teachings, and nobody said it would be. But they are doing it, and they have already begun healing. Reports are that the Roberts family has become friends with several of the Amish in the area, and they are working to help each other out after this horrible tragedy.

Even putting religion aside for a moment, the Amish actions are quite simply the right thing to do. By spreading love instead of hate, and friendship instead of revenge, they have succeeded in making sure that no cycle of violence starts there.

In contrast, 16 years later, the families of the victims in Florida still aren’t healing. They are still angry and bitter. They are still seeking revenge. They hope that their lives will get back to normal after the murderer is killed. But after 16 years of stewing about it, will they really? And what about the family of the murderer, whose lives certainly must have been a mess for the past 16 years? They will now lose a family member. Does anyone care about them, or will they now turn angry at society and possibly spread the pain more?

Imagine what would happen if so many more people around the world took the Amish perspective — to forgive those that wronged us. How long must it be before we can forgive? How far back do we spread our hate? Do we still hate those that were involved in 9/11, or can we forgive them? Do we still hate the Germans for what their ancestors did in World War II, or can we forgive them? Do we hate politicians with whom we strongly disagree, or think are liars? Do we still hate all those that have wronged us personally — someone that stole something from us or the sadistic boss?

Knives, electric chairs, and bombs do not buy reconciliation. They can not “win over” the hearts of others. They do not make our lives easier. Hate brings more hate, and more resentment.

Forgiveness is not easy. We all hope that we will never be involved in such a tragedies as these. But let us follow the example the Amish have shown — forgive for all things, big or small, important or not, painful or not.

Only then will we be at peace with ourselves, and only then will we have the chance to be at peace with our neighbors.

I use more than one computer

I use more than one computer, and quite a bit. I use three regularly, and two or three more on occasion.

But this seems to be a surprise to many programs.

I want to carry certain things with me from machine to machine, access them from anywhere, and have changes propogate across.

Things such as:

  • Bookmarks
  • newsrc files (to mark which Usenet articles are read)
  • mail (solved with my OfflineIMAP program)
  • A small set of files
  • Contacts
  • Calendar/scheduler (appointments)

Now, MacOS X seems to do some of this with their for-pay mac.com service. But I wonder why so few other apps do this out of the box?

The newsrc question is a particularly difficult one to crack, it seems. There are various schemes for synchronizing bookmarks, but none seem to work reliably.

Sigh.

I Hate Releasing Software

I’ve written a bunch of software. I like coding, I like debugging. I like getting e-mail from people that have used my software and are happy.

I don’t like actually having to make a release.

To do a good and proper release of a program, I’d be doing approximately these tasks:

  • Upload to Debian
  • Push to my darcs repo
  • Upload a tar.gz to my server
  • Update a webpage with the latest tar.gz
  • Announce the release to freshmeat
  • Announce the release to a mailing list
  • Update/post screenshots, if things have changed

So I have two wishes. First, I want a tool that maintains a website with software listings. Each program should have its own page, with a description, links to mailing lists, download links, links to the darcs repo, screenshots, etc. It should be simple but I’m too lazy to write it.

Secondly, there should be a tool that will do all of the above tasks (except the screenshots) for me. It should infer the name of the project and the version from the data in my working directory. It should be able to automate this while process without me having to lift a finger.

Sadly, no such thing seems to exist.

And, to date, I’ve been too lazy to write one. Does anyone know of such a thing?

More Goerzen News

On Saturday, my brother Peter was over to help us pack and move. While he was here, he told us that he got engaged to be married! Peter has known his fiancee ever since they were in Kindergarten together, when she was upset that he didn’t invite her to his all-boys birthday party.

We’re very excited for them and I know they’ll have more happiness than they can imagine in the years to come.

Disk encryption support in Etch

Well, I got my new MacBook Pro 15″ in yesterday. I’ll write something about that shortly. The main OS for this machine is not Mac OS X, though, but Debian.

I decided that, being a laptop, I would like to run dm-crypt on here. Much to my delight, the etch installers support dm-crypt out of the box.

Not only that, but they supported this setup out of the box, too:

  • Two partitions for Debian — one for /boot, everything else on the second one
  • The second partition is completely encrypted
  • Inside the encrypted container is an LVM physical volume
  • Inside the LVM physical volume are logical volumes for /, /home, /usr, /var, and swap
  • XFS is used for each filesystem

Not only that, but it set up proper boot sequence for all of this out of the box, too.

So I turn on the unit, enter the password for the encrypted partition, and then the system continues booting.

Nice. Very nice.

Kudos to the debian-installer and initramfs teams.

Renovation: Weeks 10-12

Well, it’s been awhile since I’ve posted photos of our renovation project. We’ve been very busy, and I’ll write about that sometime soon, too.

But anyway, I’ve now posted photos of weeks 10 – 12 of the renovation.

Some of the highlights include: new windows, a new roof, two new staircases, three old oil heaters removed from the attic (some still with oil in them), and a little joking around from the workers.

Click above to see all of the photos.

Here are two samples from this set. First, how the house looks from the oustide now:

And this one:

Someone found that old commode from the attic. They put it on the dirt pile, and put a bucket under it for good measure.

Nobody actually used it.

That we know of.

Two Stores I Like

There are a lot of places to buy stuff from online. Two favorites are cat5ecablguy and B&H Photo & Video.

First, cat5ecableguy. Well, despite the name, he sells cat3, cat5e, cat6, cable — both patch cables and bulk — as well as other things like speaker wire, jacks, coaxial cable, etc. He’s got quality products and almost always the cheapest around. It’s not unusual to see him selling things at about half the normal price.

I bought a lot of stuff from cat5ecableguy.com when we remodeled one room in our current house — bulk cable, keystone jacks, and keystone plates, mostly. We also buy from him at work — mostly patch cables there. He has prompt shipping and is great to work with. He’s even been helping me track down black CAT6 keystone jacks for our remodel project.

Second, B&H Photo. It seems like if you use a service like shopping.com or froogle to find good prices on things like cameras, TVs, etc., that there are a whole bunch of companies that advertise good prices but then call you to “confirm” an order, only to use high-pressure tactics to sell you way overpriced accessories. Some of them even go so far as to cancel orders for people that don’t purchase the accessories. Others just have bad prices or sell “grey market” merchandise (stuff intended for a non-US market that doesn’t have a valid US warranty) without mentioning it.

This is not B&H. B&H has a bunch of high-quality stuff, good prices (often not the absolute lowest, but certainly among the lowest, and usually the lowest trustworthy store), and good service. They have some large print catalogs you can request as well.

I was surprised to see recently that they’ve added pro audio to their lineup, so when I got a digitial audio recorder, I got it from them. It was a $500 item or so. They called me to confirm the order — on a *Sunday* morning no less — but with them, that really is all it is. “Did you place an order for xyz from us?” “Yes.” “OK, I’ve released it for shipping. Do you have any questions for us?” “No.” “OK, thanks for using B&H.”

I’m not quite sure why they call to confirm some orders, but I think it’s a fraud protection measure.

So anyway, I haven’t been paid to write these comments, and neither place even knows I’m doing this. I just wanted to pass along my experiences with two very nice, clueful, and honest retailers.

Another Haskell Solution to Lars’ Problem

Yesterday, I posted an 18-line solution to Lars’ language problem. One problem with it was that it was not very memory-efficient (or time-efficient, for that matter). In other words, it was optimized for elegance.

Here is a 22-line solution that is much more memory-efficient and works well with his “huge” test case. Note to Planet readers: Planet seems to corrupt code examples at times; click on the original story to see the correct code.

import System.Environment
import Data.List
import Data.Char
import qualified Data.Map as Map

custwords = filter (/= "") . lines . map (conv . toLower)
    where iswordchar x = isAlphaNum x && isAscii x
          conv x = if iswordchar x then x else '\n'

wordfreq inp = Map.toList $ foldl' updmap (Map.empty::Map.Map String Int) inp
    where updmap nm word = case Map.lookup word nm of
                             Nothing -> Map.insert word 1 nm
                             Just x -> (Map.insert word $! x + 1) nm

freqsort (w1, c1) (w2, c2) = if c1 == c2
                                 then compare w1 w2
                                 else compare c2 c1

showit (word, count) = show count ++ " " ++ word
main = do args <- getArgs
          interact $ unlines . map showit . take (read . head $ args) .
                     sortBy freqsort . wordfreq . custwords

The main change from the previous example to this one is using a Map to keep track of the frequency of each word.

A Haskell solution to Lars’ Problem

Thanks to a little glitch in planet, one of Lars’ posts from 2004 came to my attention. In it, he proposes a test for language benchmarking:

Read text from the standard input and count the number of times each word occurs. Convert letters to lower case. Order the words according to frequency, words with the same frequency should be ordered in ascending lexicographic order according to character code. Print out the top N words, where N is a decimal number given on the command line. Each output line must contain the count, a space, and the word (in lower case), and end in an ASCII LINE FEED character. Output must contain exactly N such output lines and no other output lines.

A word contains only ASCII letters A through Z and a through z (convert upper case to lower case) and ASCII digits 0 through 9 and is not empty. All other characters separate words and are ignored except to notice word boundaries. Word boundaries only occur at the beginning and end of the file and at non-word characters. You may not assume a maximum length for the word, line, or input file.

He provides a tarball with sample implementations in C, Python, and Shell.

His C code is 183 lines long, Python 57, and Shell 11. The specs for this test seem particularly suited for shell.

I wrote a version in Haskell, commented and formatted approximately the same as his Python version, but using an algorithm more like the shell version. It comes in at 18 lines. Here it is:

import System.Environment
import Data.List
import Data.Char

custwords = filter (/= "") . lines . map (conv . toLower)
    where iswordchar x = isAlphaNum x && isAscii x
          conv x = if iswordchar x then x else '\n'

wordfreq = map (\x -> (head x, length x)) . group . sort

freqsort (w1, c1) (w2, c2) = if c1 == c2
                                 then compare w1 w2
                                 else compare c2 c1

showit (word, count) = show count ++ " " ++ word
main = do args <- getArgs
          interact $ unlines . map showit . take (read . head $ args) .
                     sortBy freqsort . wordfreq . custwords

Taking a look at this, one thing that might strike you is the function composition in main. This takes the output from one function and feeds it into the next -- and the Haskell syntactic sugar for this makes it look a lot like pipes in the shell version. The interact call takes, as a parameter, a function that takes a string and returns a string. interact supplies stdin as the input and prints the output to stdout. Note that, since Haskell is lazily, this does not mean buffering up the entire input or output -- it is read and written on demand.

The rest of the functions are also standard in Haskell, and you can find them in the index to the library reference if you want to learn more.

I understand and agree that short code doesn't necessarily mean good code, but I think that Haskell provides a very elegant and expressive solution to many problems -- one that also happens to be remarkably concise.

Updated 9/4: Changed isLower to isAlphaNum to fix a bug, and removed unnecessary Data.Map import