Archive for May, 2007

Wet Bean Curd

Sunday, May 27th, 2007

This is the first in what may be a series of between 1 and dozens of articles about strange (to me) packaged foods. A lot of the items will come from the fabulous MT Supermarket in Austin.

My son Christopher, who often accompanies me to MT in order to nurture his addiction to mung bean cakes, saw this jar of “Wet Bean Curd” and insisted that I add it to our shopping cart. (Generally at MT I buy one or more packages of excellent shiitake mushrooms, Thai basil, possibly shallots when they have good ones, and random other supplies. Plus, bean cakes.) I don’t know what motivated him, but I said “Ok” because I had half an idea to do what I’m doing right now, and that seemed like as good a start as any.

Wet Bean Curd seems like an honest name for the product; compare it to American product names like Ho Ho’s or Ketchup even, a non-English word whose actual meaning nobody really knows or cares about. However, I feel that Wet Bean Curd should actually be called Salt With Spicy Wet Bean Curd in order to most accurately describe the contents of the jar. Yes, it’s wet – the bean curd and pepper shreds float seductively in a mucilaginous slurry. Yes, it’s bean curd, at least judging by texture. Bean curd itself of course tastes like almost nothing, instead appearing in foods to make sauces and seasonings edible as solid meat-like chunks. In this case, the bean curd has faithfully absorbed the taste and mysterious stickiness of a tank of particularly benighted bilge water. This is one of those foodstuffs whose production really confuses me. How can a whole factory full of people not realize how hideous this stuff is?

I’m jumping the gun a bit. We got the bottle home, and I was of course excited upon noticing that the Chan Moon Kee food packing house is ISO 9001 certified. After stowing all the other purchases, I opened the wet bean curd and snagged a chunk with a fork. The first impression was that it was really salty. The bean curd was slightly toothsome and not mushy; I suppose you could spread it on something if you wanted to, but I doubt that’s what the stuff is intended for. (I have no idea what it is intended for, and I had none even before tasting it.) Though it looked like there were a lot of pepper pieces in the mix, it wasn’t particularly spicy. In fact, the second through fifty-third impressions as I chewed on that chunk of bean curd were predominantly identical to the first: really salty. Oddly, salt is listed as the third ingredient, just ahead of wine (and I really don’t want to find out that there’s gooey wine to be had in Hong Kong).

I tried a second piece of wet bean curd. This time I tried to concentrate on other flavors. There was the spiciness, of a pretty tame sort without much pepper flavor. There was also a strange, slightly acrid tang to it, not pleasant in the least. Overall, therefore, I declare wet bean curd to be a bad-tasting mildly spicy substance that’s overpoweringly salty. Even if you like acrid weird-tasting spicy marinated bean curd, I can’t imagine that you’d like it dosed with ten times as much salt as anything like that should need.

I won’t be buying more of this stuff, but it’ll stand as a cautionary example here at the beginning of this series. It’s not safe to assume that just because something is in a jar, attractively labeled with an image of a wading bird, and placed for sale on a grocery store shelf that it’s worth eating. I accept that somebody might like wet bean curd, just as I accept that somebody out there must be drinking all the Tequiza being produced. I just don’t understand it.

ID3v1 tags via Erlang

Sunday, May 27th, 2007

I’ve been taking considerable doses of disorienting but only marginally effective phenylephrine-based cold medicine. This has made it hard to think about anything, yet I did manage to type in an Erlang program to find ID3v1 tags in MP3 files. This program represents about 0.5% of the work necessary to complete my vague goal of implementing a music server in Erlang, which is a pointless effort in any sense other than Erlang practice.

Here’s the routine that pulls a tag from a file:

load_id3v1(FileName) ->
  case file:open(FileName, [read, binary]) of
    {ok, Handle} ->
      Rv = case file:pread(Handle, {eof, -128}, 128) of
        eof -> missing;
        {ok, <<$T, $A, $G, ID3v1/binary>>} -> ID3v1;
        X -> {garbled, X}
    Whatever -> Whatever

All that does is read the last 128 bytes of the file and look for the ID3 “TAG” marker in the first three bytes. If it finds that, then it returns (as a binary) the remainder. The ability to work with what amounts to blocks of raw memory in an idiomatic fashion is one of the most practical aspects of Erlang. The syntax is a little painful.

The main matching expression in the function does its work with a single match to a binary pattern. The pattern lists out the three characters of the tag – in Erlang, the notation “$c” means the character code for character ‘c’. (Erlang seems a little quaint with respect to character encodings.) The default semantics of an integer value in a binary pattern like that is that they signify values to match in single bytes. (I could have written that “TAG” instead of $T, $A, $G, by the way.)

The tag contents are matched as whatever is sitting there in the 128-byte block after the tag. The unbound variable name “ID3v1” will be bound to that 125-byte region of memory, and its type will be binary. Of course, that match will only work when the last 128 bytes of a file actually does begin with “TAG”. If not, that matching expression would fail, and the “case” expression would fall through to the “X” pattern, which returns a lame error indicator.

That’s all pretty elementary stuff, but I notice that the binary data type doesn’t show up too often in Erlang blog posts I see.

To use that function for real, what I’d do in my fantasy Erlang server is build a couple of tables. One table would contain the actual filename, plus the tag attributes, plus probably a numeric key to make it easier to communicate the file identity back and forth to web clients. In a current Java implementation, I’ve found that the issue of maintaining the integrity of interesting file names – think Sigur Rós tracks – as they go from the file system, into Java (Unicode), out to the browser, and back, to be a real headache, even requiring explicitly adding ISO-8259-1 character encoding to my Ubuntu installation. The Java file handling libraries, in particular the code to return the contents of a directory, work in the C domain, so they can’t handle simply-encoded filenames without the platform being made to understand. Or something like that. The point is that nice identifiers would be easier to handle as the medium of exchange in a web app.

The second table would capture hierarchical grouping relationships, but I haven’t thought that through much.

To continue looking at interesting things one can do with binary stuff in Erlang, consider what would have to be done to use some of the ID3 attributes. The tag contents are broken up into 30-byte regions for artist name, album, track, and a comment. (Discussion of how pathetically lame the tag architecture is are irrelevant here.) Those are padded with null bytes, normally. Well if we want to turn those into Erlang strings, we need to avoid the nulls – just calling “binary_to_list” on one of those 30-byte blocks would give us a “string” with a bunch of nulls at the end.

We therefore need a “de_null” routine to get rid of those zero bytes:

de_null(B) -> de_null(B, []).
de_null(<<>>, RS) -> lists:reverse(RS);
de_null(<<0, _/binary>>, RS) -> lists:reverse(RS);
de_null(<<C:8/integer, Rest/binary>>, RS) -> de_null(Rest, [C | RS]).

That’s written in a pretty conventional Erlang tail-recursive loop. The routine checks the first byte of its binary argument, and when it’s a zero it returns the reverse of the list it’s accumulated (backwards) from all the previous bytes. This isn’t bad, as those bindings to successive values for that “Rest” variable don’t involve copying anything – it’s just moving the pointer through the binary. However, we could do this another way:

de_null(B) -> de_null(B, 0).
de_null(Binary, Offset) ->
  case Binary of
    <<Stuff:Offset/binary, 0, _/binary>> -> binary_to_list(Stuff);
    <<Stuff:Offset/binary, _:0/binary>> -> binary_to_list(Stuff);
    _ -> de_null(Binary, Offset + 1)

In this version, instead of accumulating a list, we’ll just keep a byte counter through the iterations. Each iteration checks to see whether one of two things is true: that there’s a zero byte at the given offset, or that we’ve run out of binary. It does this by using the counter as the size of the “head” of the binary block, with the notation “Stuff:Offset/binary”. That says that the variable “Stuff” should be bound to the binary subset of the block starting at the beginning and proceeding for “Offset” bytes.

In this case there’s no practical difference. Sometimes, however, the indexing approach can be a much more efficient alternative to using lists. Appending to the end of a list is expensive, while scooting an index forward by a byte is essentially free.

Tegetthoff Assignment

Friday, May 25th, 2007

Before going to bed last night, Christopher declared that in the morning we would search the internet for information on the Austro-Hungarian Tegetthoff class dreadnoughts. I acquiesced, because that seemed interesting; of course I had never even heard of the Austro-Hungarian Tegetthoff class dreadnoughts.

This morning I was reminded of the task. As it happens, the Tegetthoff class dreadnoughts are well-represented on the internet at the Austro-Hungarian Tegetthoff Class Dreadnoughts Ultimate Site, which seems fitting. If you’ve got a few minutes, I advocate reading the story of how the Viribus Unitis was sunk: it’s one of those stories that would sound too fake if it were fiction.

Hello I am a blogger

Thursday, May 24th, 2007

The sentence, “I am a blogger,” is to some extent in my head still equivalent to the sentence, “I am pretentious and stupid.” I will try to get over that.

I also want to update the stupid stock image up at the top with one of my own pointless images, but I don’t know how.