# 2018.11.12 Destroy Things

I think it's important to learn through destruction. I like to proble the edges of things, and one of the best ways of knowing where IS the edge is to go over it. So ... let's go over the edge.

First we need a nice fresh ubuntu:

awwaiid@zokei:~$docker run -it ubuntu bash root@1cf14a7465fd:/#  Now, this isn't a completely isolated machine or anything, but it'll do. Keep in mind that this is running as root on your machine (if you're running a Linux host at least, this is probably safer on osx), so you should be a little afraid. Fear will keep you on your toes! Let's cause a little destruction! Make sure you are INSIDE of this new ubuntu container, and then: root@1cf14a7465fd:/# rm -rf /  They always joke that you shouldn't do that. Turns out our lovely ubuntu is trying to help us not hurt ourselves, so we have to pass a special flag: root@1cf14a7465fd:/# rm -rf --no-preserve-root /  WHOA! Whole lot of errors. Many of them are very good things about how you can't remove stuff in /sys/devices because of it being a read-only filesystem (remember that running as root bit?). And now the fun begins. root@1cf14a7465fd:/# ls bash: ls: command not found  Oh right. "ls" is a command that is an executable program that lives at /bin/ls. Correction: LIVED. But no longer. That's ok ... tab completion still works! root@1cf14a7465fd:/# cd <tab><tab> dev/ etc/ proc/ sys/ root@1cf14a7465fd:/# cd etc root@1cf14a7465fd:/etc#  Great! So we can git directory lists. Let's look at some files root@1cf14a7465fd:/# cat <tab><tab> hostname hosts resolv.conf root@1cf14a7465fd:/# cat resolv.conf bash: cat: command not found  Oh right. No "cat" command either. What commands DO we have? Well, we have any bash built-in. And we have bash as a programming language with loops and all that. Now we start to get fancy. root@1cf14a7465fd:/# while read p; do echo$p; done < /etc/hostname
1cf14a7465fd


Nice. We can now look at the contents of files. But if we are ever going to rebuild our system we'll also need to write files. Easy!

root@1cf14a7465fd:/etc# echo 'echo "hello!"' > hello.sh
root@1cf14a7465fd:/etc# . /etc/hello.sh
hello!


We cheated a bit with that "." to "source" the file. I'm not sure how to make it executable, since we no longer have chmod. Maybe we'll try that next time.

# 2018.07.29 Multiverse Timetravel Accounting

I've been doing a spot of accounting at work over the last few months. This is clearly a failure of delegation and management on my part, but it has led to at least one deep observation that I mightn't have had otherwise.

## Accountants are secretly time travelers.

Perhaps that is a slight exaggeration. They don't ACTUALLY travel through time. But if you hang out with them a bit and observe their twisted time and verb conjugation ... well it's obvious that they would be right at home hopping around a branching multiverse.

For example, there we were at the end of June. Topic at hand: things that are going to happen in May, from the perspective of late April. Casual conversations include things like "If we put the new rule into place in late June, then when May hits we'll have to go all the way back to February to get the correct outcome". Mind bending! Daily conversation, without anyone blinking an eye.

Alternate timelines are discussed quite a bit also. They aren't quite stated this way, but basically they go along thinking in terms of events from timeline A, and then decide "No! Wait! We aren't in timeline A, we are in timeline B!!!!" and maybe freak out a little about how they now have to rewrite history to match the current reality or perhaps adjust the perception of the current reality to match the new history. Some of it even appears to be experimental, running simulations on previous events to try to see how it changes the present (well ... and the future).

One thing I'm glad of is the ethical standards to which time travelers.... er... accountants adhere. There is an ongoing insistence that no matter what timeline they find themselves in, they should reconcile with the past and ever move to a more obvious and simple future. Try not to change the facts of the past, but if you do please keep some integrity in the universe so it can have some degree of cohesion in the present.

Anyway. Take my advice. If you go adventuring around in your time machine, bring an accountant to keep track of what is going on.

• Is Google Making Us Stupid?
• I have a big stack of books that I've made ... fairly little progress on
• Maybe the internet is eating my brain!
• So now I will post links and bullets
• Base-4 fractions in Telugu
• Interesting explanation of the traditional Telugu fraction numbering. Also draws comparison to the traditional English measures
• Git remote branches and Git's missing terminology
• Presents a better understanding of git remote branches, highlighting that to really comprehend what's going on you must acknowledge the implicit local branch that is your cache of the upstream (such as origin/master)
• I'm a little worried that I'm going to end up linking half of MJD's blog posts. Oh well, they are great. Example, /dev/null Follies has a hilarious nerdy punchline.

# 2018.02.05 OddMuse Wiki Dockerized

I Dockerized this website yesterday! I had already built a cpanfile that declares the Perl5 dependencies of OddMuse, which made it easy. I'm also going to run this with the data directory directly bind-mounted.

First the Dockerfile:

FROM perl:latest

# Set up the deploy user
ARG uid=1000
ARG gid=1000
RUN echo groupadd -g $gid deploy RUN groupadd -g$gid deploy
RUN useradd --create-home -u $uid -g$gid -ms /bin/bash deploy

WORKDIR /app

COPY cpanfile .
RUN cpanm -qn --installdeps .

USER deploy


The bit of fancyness here is the deploy user setup. Since I'm mounting the project directory for data files, I'd like new files and edits to be done by my normal user. On my cloud-server, this is uid 1000, which is easy to set as the default. On my laptop I run as user 1001, so the file is parameterized for this case. When I run locally, I have to build my docker image with docker build --build-arg uid=$(id -u) --build-arg gid=$(id -g). Not as much fun.

Otherwise, this starts with the Perl5 base image and installs the CPAN dependencies.

Next, the docker-compose.yml

version: '3'

services:

web:
build: .
command: starman --workers=10 --max-requests=1 --access-log starman-access.log --error-log starman-error.log oddmuse.psgi
volumes:
- ".:/app"
ports:
- "5000" # For running locally

nginx-ssl-proxy:
image: danieldent/nginx-ssl-proxy
restart: always
environment:
UPSTREAM: web:5000
SERVERNAME: thelackthereof.org
EXTRANAMES: www.thelackthereof.org
ports:
- "80:80"
- "443:443"
volumes:
- "/etc/letsencrypt"
depends_on:
- web


The first service runs Starman (this is similar to Unicorn for you Ruby folk). It mounts the project directory as /app, and runs oddmuse.psgi. We declare port 5000 anyway for local debugging -- we can then run only this service and it'll come up on a randomly assigned port that connects to port 5000. Other services on this network can connect to "web:5000" even without this declaration.

Which brings us to the second fancy bit. The danieldent/nginx-ssl-proxy image is a super cool image that gives an nginx proxy with automatic letsencrypt setup! You declare the domain name and the proxy destination (web:5000 is our Starman), and assuming that domain really is pointing here, it will work with letsencrypt to verify ownership and make certificates. The certs are stored in a docker-managed volume, and are periodically renewed. This takes less than a minute, so even if the volume gets accidentally deleted we can easily get a new cert.

Now running "docker-compose up -d" starts nginx and starman running in the background. All that remains is getting this running on boot. Since the startup command can be run over and over, worst case you can put it in a cronjob that runs frequently :)

Comments on TLT - 2018.02.05 - OddMuse Wiki Dockerized

### 1 Comment.

This is perfect timing for me !

I did something close with mine using apache a few months ago but I am not satisfied with it.
I run it onto my SAN Synology box.

See Oddmuse page for details on my recipe and see if we can make it better.

-- XavierMaillard 2018-05-10 07:57 UTC

# TLT - 2018-11-12 - Destroy Things

I think it's important to learn through destruction. I like to proble the edges of things, and one of the best ways of knowing where IS the edge is to go over it. So ... let's go over the edge.

First we need a nice fresh ubuntu:

awwaiid@zokei:~$docker run -it ubuntu bash root@1cf14a7465fd:/# â  Now, this isn't a completely isolated machine or anything, but it'll do. Keep in mind that this is running as root on your machine (if you're running a Linux host at least, this is probably safer on osx), so you should be a little afraid. Fear will keep you on your toes! Let's cause a little destruction! Make sure you are INSIDE of this new ubuntu container, and then: root@1cf14a7465fd:/# rm -rf /  They always joke that you shouldn't do that. Turns out our lovely ubuntu is trying to help us not hurt ourselves, so we have to pass a special flag: root@1cf14a7465fd:/# rm -rf --no-preserve-root /  WHOA! Whole lot of errors. Many of them are very good things about how you can't remove stuff in /sys/devices because of it being a read-only filesystem (remember that running as root bit?). And now the fun begins. root@1cf14a7465fd:/# ls bash: ls: command not found  Oh right. "ls" is a command that is an executable program that lives at /bin/ls. Correction: LIVED. But no longer. That's ok ... tab completion still works! root@1cf14a7465fd:/# cd <tab><tab> dev/ etc/ proc/ sys/ root@1cf14a7465fd:/# cd etc root@1cf14a7465fd:/etc# â  Great! So we can git directory lists. Let's look at some files root@1cf14a7465fd:/# cat <tab><tab> hostname hosts resolv.conf root@1cf14a7465fd:/# cat resolv.conf bash: cat: command not found  Oh right. No "cat" command either. What commands DO we have? Well, we have any bash built-in. And we have bash as a programming language with loops and all that. Now we start to get fancy. root@1cf14a7465fd:/# while read p; do echo$p; done < /etc/hostname
1cf14a7465fd


Nice. We can now look at the contents of files. But if we are ever going to rebuild our system we'll also need to write files. Easy!

root@1cf14a7465fd:/etc# echo 'echo "hello!"' > hello.sh
root@1cf14a7465fd:/etc# . /etc/hello.sh
hello!


We cheated a bit with that "." to "source" the file. I'm not sure how to make it executable, since we no longer have chmod. Maybe we'll try that next time.

# 2017.07.08 Lignting Talk on Rakudo Colons

I gave a lightning talk at The Perl Conference about my collection of Perl6 Colons. Looks like Geoff gave me 34 extra seconds... not sure that I approve :)

Enjoy!

# 2017.05.21 Core Logic

There are many tools in my programming toolbox, but one that I've felt is missing is constraint and logic programming. I've done a spot of Prolog and played with some inference systems of various types ... but even when I run into something where I think it's the right hammer... I don't have a go-to tool.

I got The Reasoned Schemer a while back, hoping to use it to learn clojure's core.logic or similar, but the writing still KILLS me. Hate it so much. It is like the worst extreme sort of Socratic Method that I can imagine, literally everything has two columns of question and answer. But the QUESTIONS are obtuse! Working through it that way is not the sort of enlightenment that I'm going for ... I don't want to apply a unification algorithm on my understanding of logic programming with the contents of the book! The programming system might be "backwards" that way, but my way of learning isn't.

Anyway. One dumb thing that I had a hard time getting over was things ending in -o, like conso and emptyo. But tonight I had a breakthrough! See those 'o' things, according to the internets, are supposed to be sort of like question-marks except describing a goal. So now if I read the 'o' as '-objective' (as in, "goal") then they sound much better. cons-objective, empty-objective. Declaring the goal of the statement.

I guess I should go back and try reading The Reasoned Schemer with that in mind, and see if it makes me less angry :)

# 2017.04.10 VimWiki Gateway

I've been having lots of fun with https://github.com/vimwiki/vimwiki lately! I've mixed in a bit of encryptfs to have a private directory of notes. Sometime during boot, I set it up with:

sudo mount -t ecryptfs \
-o key=passphrase,ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_passthrough=no,ecryptfs_enable_filename_crypto=yes,ecryptfs_fnek_sig=1a9380706fdf5bce \
~/docs/private/vimwiki ~/notes


I haven't done much customization yet. But one thing I'm playing with now is making it easy to post notes from VimWiki directly onto my website.

# 2017.01.11 Slack Hash Store

Last night at the DC Perl Mongers meetup we collaboratively built a proof-of-concept for storing key/value pairs as messages in a slack channel, https://github.com/plicease/globalhash. This was made straightforward by great Slack API docs and WebService::Slack::WebApi. Example usage:

# writes "hello=world" into the #globalhash channel
$globalhash set hello world # reads the #globalhash channel for the most # recent value of hello and prints it$ globalhash get hello
world


There are of course a TON of things you could do from here. Some ideas:

• More features: list of keys, delete, complex values, binary values, value history
• Clean implementation and better usage/error messaging, docs
• Port to other languages -- perl6 and still using the perl5 module would be fun
• Register as a slack app that anyone can use, fix up OAuth or whatever

# 2016.09.23 All The Methods

A fun thing to do is to explore things using introspection/reflection. In Ruby and Perl6, for example, we can get a list of methods for a given object instance pretty easily:

# Ruby
"hello good people!".methods.each { |method| puts method.to_s }

# Perl6
for "hello good people!".^methods -> $method { say$method }


On the REPL (irb/pry or perl6) this is even shorter since it prints out lists of things by default, so you can do:

# Ruby
"hello good people!".methods

# Perl6
"hello good people!".^methods


One difference you see here is that Perl6 has a separate way to call meta-methods, whereas Ruby provides them directly. In some other languages you need to call into a separate reflection library and give it your object and what you want from it.

Cool!

This is a great and devious way to answer the question "what can I do with this object?". In Ruby's pry you can use the "ls" command like "ls foo" to get an even prettier version.

But you know... why stop there? Let's call the methods.

All of them.

In Perl6 that looks like:

sub all-the-methods($thing) { for$thing.^methods -> $method { say "{$method.name} => {$thing.clone.$method.gist}";
CATCH { default { say "{$method.name} => ERROR" } } } } all-the-methods <this is words>; all-the-methods "hello little fishies!";  Taking the list of methods, we loop over them and invoke them one at a time. Here we do ".clone" so that if it is a mutating function we'll work on a copy. Note that ".clone" is NOT a deep-copy, so while it works in my simple list and string examples it might not work so well for other things. The call to .gist gives us a nice printable version of the result. We invoke the method with no parameters, and many methods don't like that. So here we provide a CATCH block that just prints out a generic message -- it's inside the loop so after catching an error it'll just go to the next method. Here is some of the output: # <this is words> permutations => ((this is words) (this words is) (is this words) (is words this) (words this is) (words is this)) join => thisiswords pick => is roll => words reverse => (words is this) rotate => (is words this) append => ERROR # "hello little fishies!" ords => (104 101 108 108 111 32 108 105 116 116 108 101 32 102 105 115 104 105 101 115 33) wordcase => Hello Little Fishies! uc => HELLO LITTLE FISHIES! flip => !seihsif elttil olleh chop => hello little fishies contains => ERROR  Lots of the functions just result in 'ERROR', especially for those pesky methods that take some sort of parameter. A lot of these methods, however, work ok with no params and return some value. In Ruby this looks like: def all_the_methods(thing) thing.methods.each do |method| begin if method =~ /^pry|byebug|debugger$/
puts "#{method} => SKIPPING"
next
end
puts "#{method} => #{ thing.clone.send(method) }"
rescue
puts "#{method} => ERROR"
end
end
end

all_the_methods %w(this is words)
all_the_methods "hello little fishies!"


Here we had to explicitly skip the pry/byebug things, at least for my REPL execution, because those entered a subshell which isn't what I'm going for. Similar to Perl6 we also clone the object (also a shallow-clone) and had to handle exceptions, which are again almost entirely from methods that take more than zero parameters. In Ruby interpolated values automatically get .to_s called on them, so we don't need to do anything there.

One very notable thing is that operators in Ruby are methods directly on the object! This is nice for lots of reasons, including that you can easily override them. In Perl6 operators are standalone subs that do typed multi-dispatch (pattern matching) to decide what to execute, so the code isn't usually directly part of the class itself even if it ends up calling methods on the class or messing with the state.

Some of the output:

# %w(this is words)
shuffle! => ["words", "is", "this"]
include? => ERROR
permutation => #<Enumerator:0x00000002e48188>
combination => ERROR
sample => is
sort => ["is", "this", "words"]
count => 3
first => this
== => ERROR

# "hello little fishies!"
succ! => hello little fishiet!
upcase => HELLO LITTLE FISHIES!
downcase! =>
capitalize => Hello little fishies!
codepoints => [104, 101, 108, 108, 111, 32, 108, 105, 116, 116, 108, 101, 32, 102, 105, 115, 104, 105, 101, 115, 33]
reverse! => !seihsif elttil olleh
center => ERROR


Again most of the results are 'ERROR', especially where they expect more arguments. Another interesting thing is 'permutation', which returns an enumerator rather than a list, and isn't forced to evaluate upon rendering or anything. Also I notice here that 'downcase!' doesn't return the result of downcasing :)

BONUS

Since I'm going all polyglot here anyway, I was starting to wonder which methods were equivalent. I could read through and guess, but that's no fun. Instead I made an alternate version of the above that does two things -- it reverses the method-result relationship so that we get a list of methods that return a specific result. Then I also output in a more language-neutral JSON format to compare across languages, and and turn that into a list of methods and their result prefixed with the language name.

perl6-rotate ruby-rotate ruby-rotate! => [ "is", "words", "this" ]

perl6-words ruby-split => [ "hello", "little", "fishies!" ]

perl6-ords perl6-NFC perl6-NFD perl6-NFKC perl6-encode perl6-NFKD ruby-codepoints ruby-bytes => [
104, 101, 108, 108, 111, 32, 108, 105, 116, 116, 108, 101, 32, 102, 105, 115, 104, 105, 101, 115, 33
]

perl6-lines ruby-lines => [ "hello little fishies!" ]

perl6-reverse ruby-reverse! ruby-reverse => [ "words", "is", "this" ]

perl6-comb ruby-chars => [
"h", "e", "l", "l", "o", " ", "l", "i", "t", "t", "l", "e", " ",
"f", "i", "s", "h", "i", "e", "s", "!"
]

perl6-sort ruby-sort ruby-sort! => [ "is", "this", "words" ]

perl6-Slip perl6-values perl6-tree perl6-unique perl6-List perl6-Array
perl6-words perl6-squish perl6-item perl6-clone perl6-flat perl6-eager
perl6-Seq perl6-FLATTENABLE_LIST perl6-reification-target perl6-ZEN-KEY
perl6-ZEN-POS perl6-return-rw perl6-cache perl6-self perl6-lazy perl6-return
ruby-untaint ruby-unshift ruby-freeze ruby-dup ruby-compact ruby-uniq
ruby-taint ruby-itself ruby-to_ary ruby-untrust ruby-clone ruby-push
ruby-entries ruby-flatten ruby-to_a ruby-trust => [
"this", "is", "words"
]



That is a lot fewer than I expected! I had to run the perl6 with .methods(:all) to get ".sort", which was surprising. This probably misses others where my JSON encoding normalization trick doesn't work.

# 2016.09.05 Test Suite Debugging Time

One of the codebases I work on regularly has a large and slow test suite. So slow that it typically only runs in totality in a continuous-integration (ci) environment, and there it uses the parallel_tests gem to slice it into pieces and run in parallel. This gets it to run in like 30 minutes instead of 2.5 hours.

But I want to run the whole thing linearly sometimes, especially so I can make sure tests aren't conflicting with each other. So I created a new ci job that runs it linearly ... and got a fail that I didn't get otherwise. Took forever to figure it out!

This was about a worker that I call a "sweeper" -- it's job is to run once a day and make sure nothing was missed by other realtime jobs during the day. Here is a simplified version.

class SweeperWorker
INTERVAL = 25.hours.ago # Overlap the day by an hour
def perform
candidates.each(&:do_work) # something like that
end
def candidates
Thing.where('created_at > ?', INTERVAL)
end
end

# rspec
describe SweeperWorker do
let(:new_thing) { Thing.new(created_at: 5.hours.ago) }
let(:old_thing) { Thing.new(created_at: 26.hours.ago) }

it "does pick up the new thing" do
new_thing # force to exist
expect(SweeperWorker.new.candidates).to include(new_thing)
end

it "does not pick up the old thing" do
old_thing # force to exist
expect(SweeperWorker.new.candidates).not_to include(old_thing)
end
end


Not sure that is quite right, but you should get the idea.

The second example was failing -- both the "old thing" and the "new thing" were getting into the sweeper window -- but only when the test suite was run linearly. Run it in ci, no problem. Run just this test/file locally, no problem.

The suspect is thus "time" -- but where? I went down the wrong track for a while, looking into timezones. Rails vs MySQL on ci vs my machine and so on ... some of those things weren't quite matched up, but still. I ran the test over and over, adding more and more debugging so I could peer into the contents of variables and the DB. Everything looked fine -- all the timestamps were what I expect. So it must be the query itself that is somehow asking for a longer timespan.

Finally I got it! Right there in the first line of SweeperWorker:

INTERVAL = 25.hours.ago # Overlap the day by an hour


This constant is set when the class is loaded, and never changed! So by the time this test runs in the 2.5 hours of test time, "25 hours ago" is now "27.5 hours ago" -- so our "old" thing is in our window. The "25.hours.ago" certainly looks relative, but it is a calculation that outputs an absolute time which is then saved for later use.

Move that constant into the method as a variable and it is fixed. And now we can sing our victory song!

Lessons:

• Beware of calculated constants
• Make sure relative values are actually relative
• If the speed of execution (slow vs fast) changes the outcome, look for things that are more or less spread out in the timeline, such as constant definition.

# 2016.08.12 ICFP Contest 2016 - Origami Folding

## Challenge: Folding Origami

This year the ICFP will be held in Nara, Japan. The contest was organized by members of The University of Electro-Communications. I checked out their website since that sounded like a weird school name, and see that they are also hosting "The Joint Conference of the 8th International Conference on ESP in Asia & the 3rd International Symposium on Innovative Teaching and Research in ESP in Japan". Unfortunately "ESP" here is for "English for Specific Purposes" rather than the usual usage.

Unlike other years, the contest started at 00:00 UTC, which is 8:00pm Thursday, and lasted until 8:00pm Saturday. This was a nice schedule to start with, getting to roll into the contest right after work, but it did leave me jazzed up on Sunday night after it was over.

I was joined at my house by Mike, and Jason joined us remotely from Portland. We coordinated by google hangouts, irc, and github. Near the end I turned on the github-notification hook that posted to irc upon pushes, and should have done that a lot earlier.

First we read through the problem, which was very tricky to wrap our heads around as usual, despite it's somewhat minimalistic Japanese aesthetic. We drew on the whiteboards and drew on paper and folded some paper. Apparently I'm not supposed to use scissors to do origami, who knew?

The rough idea is that we are given the shadow, or "silhouette", of a folded origami flattened to 2D. We then need to reconstruct it by starting with an unfolded paper and then trying to fold it until we get the same shadow. During the lightning round we were given 101 problems of this form. After the lightning round we could submit new problems of our own invention and solve problems submitted by other contestants. We submit our solutions as we go and acquire points based on how well we solved a problem, how big in bytes was our solution, and how easy it was to solve (based on how many others solved it). They even provided a nice leaderboard.

I talked Mike into programming in Perl 6 :) . While he and Jason worked on understanding the rules of folding and solving a few problems by hand, I whipped up a problem parser using Perl 6 Grammars, which worked perfectly. I had fortunately practiced a bit before. I built a simple caching API layer to get problems from the contest server, just shelling out to curl basically.

After that I did a very basic visualization using Imager (via Inline::Perl5), which Mike then took over and worked on. Then (and we're talking Friday or Saturday) I started working on modeling folding of an origami. And then I got stuck.

I didn't realize it until I was taking a shower on Monday morning after the contest, but I was attempting to implement too general of a solution for part of it. The rough idea is to consider an origami as a bunch of polygons. You start off with one, and then when you fold it you end up with two, one of which you reflect along the fold line.

So I set out to chop up a polygon given a line, and unfortunately didn't think through my goal clearly enough -- I tried to split ANY polygon. That includes funky looking concave polygons that when you cut with a single line might split into a bunch of pieces. What I realized after the contest was that a single cut starting from a solid piece of paper can never end up that way -- there is no way to cut it into a funky shape! So I lost a lot of time there.

The other thing that cost time was reflection. We cast about for some off the shelf libraries, but got mad at them, so I just started to implement reflection myself. I even thought I had it working, but sometime early on Sunday I realized something was fishy. I switched to an off-the-shelf implementation via Math::Geometry::Planar and presto! Worked much better. Should have used that from the beginning.

Meanwhile Mike was both improving the visualization, especially around setting a useful viewport for shadows that had been moved far away from the axis origins. He also went through and generated images for the existing problem, which helped us pick out good test cases. Jason kept at it too, starting to hand-generate us some problems to submit once we got past the lightning round, and hand-solving some of the problems that were provided.

After visualizations were working, Mike connected the dots between problems and the origami modeling to calculate a score, making further use of the Planar library. This gave us the final ingredient we needed for automated exploration of simple folds in origami space.

Finally, late on Sunday, we got to where I wanted to be by Saturday morning. Given a problem we could start with an unfolded square and then randomly fold, keeping the improvements. Basic hill-climbing, in other words. I consider this stumbling across the finish line ... but we made it :)

# 2016.06.28 Not Quite Righte

Idea for a programming language: make experienced programmers twitch by forcing minor and common errors to be part of the language.

/* This is a comment /*
print "Hello, world!' /* Strings must have balanced quotes /*

if 5 + 2 = 4:
print 'Everything is awesome!"

for(var i; i < 1; ++) print i;

class Foo {
private method greeting [
print "Muahahaha'
]
}

foo.new.Greeting(


# 2016.05.12 DCRUG React.rb

I enjoyed presenting at DCRUG tonight on React.rb, which I've been playing with for the last few weeks. Good turnout too!

Resources:

# 2016.04.10 DCBPW, On Being Small

Welcome to the DC-Baltimore Perl Workshop!

This workshop started innocently enough. The year was 2010 -- October. We were at the Pittsburgh Perl Workshop when Brad Lhotsky said he wanted to host a similar workshop in the DC/Baltimore region. I told him no. But then he talked me and some others into it. During 2011 we worked out some details and at the 2011 Pittsburgh Perl Workshop we announced that the first DCBPW would be held April 14, 2012! We even made fliers!

Here we are six wonderful years later. We've had a few of the organizers step back over the years, mostly due to moving away, but we picked up a few others and have a core of dedicated volunteers that put this workshop together every year. We get support from The Perl Foundation and also get support from local businesses and communities. It has gone pretty well! And yet... sometimes I've felt unhappy.

You see, I started to get fantasies of grandeur.

I imagined a hundred people showing up! Two hundred! Each year this didn't happen I was a little sad. Perl dying? Community dying? What's going on that a region with probably a thousand perl developers only have 50 show up to a really awesome and cheap conference?

And then I realized -- This isn't a conference! It's a workshop.

What we have is a true "workshop". A set of people focused on learning new things, getting introduced to new ideas, and getting some hands-on time. We have organized pre-planned presentations, but we also have a lot of hallway time and variety. Then the second day is completely hands-on time. The signal-to-noise ratio is fantastic -- each attendee gets a chance to learn from their peers both formally and informally.

So yeah. It's small. That's not a bug, it's a feature :)

# 2016.03.05 Arlington RetroRuby 2016

Today I attended http://retroruby.org, a great un-conference in Arlington. I got my toehold in the local Ruby community at the Arlington meetup, and was happy to visit with lots of familiar people. I didn't meet any new people, though that was mostly because it was easy to spend time catching up.

Next time I want to jump in a bit stronger on the new-dev track, maybe walk through some hands-on exercises or do a group activity (Randori).

My favorite, besides talking to people, was the lightning talks. These have a bit more technical depth and include some code getting projected, which I love. I gave a quick this-thing-exists talk on http://reactrb.org.

In the hallway track I also got to preach a bit about Module Level Polyglot :)

# 2016.01.08 Perl 6 is Separate from All, Replacement for None

In response to the "Perl 5 and Perl 6 are mortal enemies" article.

We are definitely framing this whole thing wrong. We have two choices:

• Replacement: Perl 6 is, eventually, the replacement for Perl 5
• Separate: Perl 6 is an unfortunately named but completely separate language from Perl 5

Most people outside of Perl 5 and Perl 6 go with Replacement just by looking at the names. Various insiders switch at random between Replacement and Separate, and I think that is the core mistake. This article has a very important sentence:

"First, a postulate: given the language similarities, the people that will find it easiest to learn Perl 6 are today's Perl 5 developers."

In reality there are SO MANY differences between Perl 5 and Perl 6, it is NOT a good postulate!

This is it -- this is the mistake where we are getting both messages at once, and the rest of the article paints a dark picture of a world (unfortunately most likely the one we live in) in which crossing these messages happens. The mixed message is a net negative for both languages.

I suggest that if you take a random [Perl 5, Ruby, Python, PHP, Javascript, R] programmer, the Perl 5 programmer might actually have MORE trouble than others due to misleading overlap and jarring differences. A developer that uses a lot of Moose might have less issues... or again might end up with the differences shocking rather than enlightening. I actually think the Ruby developer will have the LEAST trouble learning Perl 6, building on tons of overlap (everything is an object!), a shared history (sure, /foo/ is a regex, drop it in. Couple sigils here and there never hurt anybody), and similar culture (TIMTOWTDI is a motto for both). But the Ruby developer won't expect things to be mostly the same between Perl 6 and Ruby, unlike a naive Perl 5 developer.

I recommend you each shape your language to do two things. First stick strongly with Separate, second focus on the Polyglot nature and audience:

Perl 6 is a new and interesting language. It happened to be created by the creator of Perl 5 and an overlapping community, and has an unfortunate name. It is a Practical Research Language, aiming to be both cutting edge and useful. It is of interest to all dynamic-language programmers, and is especially interesting for the polyglot: you'll see familiar bits from Haskell, Perl 5, Ruby, Python, CLOS, ... plus lots of original ideas. Things that you can use, or at the very least learn and take back to your work. You can use Perl 6 now to solve small tasks, and join at the ground floor to build up the ecosystem and culture towards solving larger and larger problems.

One of the cultural things that I think can set Perl 6 apart is in being Module Level Polyglot. From Perl 5 or Ruby you can invoke Python code (both have libraries to support this that I've used) -- but you'd be hard pressed to get that put into production at your work. But NOBODY should ever implement pyplot again! If we can make doing "use matplotlib::pyplot:from<Python>" a socially-acceptable thing in Perl 6, we might be able to convince other communities to do the same... and do something amazing: revolutionize sharing cross-language modules.

Perl 6 isn't the research language for Perl 5. It is a research language for ALL languages to learn from. Perl 6 is the Borg of Languages, pulling in concepts and features to create a glorious monster. Maybe the first assimilated was Perl 5, but it clearly didn't stop there. We need to let go of its roots. Embrace that Perl 6 is Separate from All, Replacement for None.

# 2015.10.18 My First Useful Perl6 Grammar

Tags: Perl6

In my recent talks about perl6, one thing that I keep neglecting is Grammars. Part of that is because I hadn't used them yet!

I was putting together a talk on some clojure code, and was getting mad at my slide software not syntax-highlighting with magical rainbow parenthesis. Clojure being a LISP-like, it lacks some visual clues for structure and is WAY easier to glance at (in my opinion) when parenthesis are highlighted. I have vim doing this for me... but no dice in my slides.

So! Slice up slides, run them through vim, stitch them back together, and presto!

Complete code is at https://github.com/awwaiid/pinpoint-code-color.

I use Pinpoint as my go-to slide software. Simple and easy both to develop a deck and to present it. Each slide is a header and a body done in some Pango markup (more or less simplified HTML). Here is a 3 slide deck:

#!/usr/bin/env pinpoint

# Defaults for all slides
[font=Sans 90]
[duration=50.00]
[fill]

--

Some other slide content.

-- [font=monospace 99] [code=sh]

\#!/bin/sh

\# A lovely cgi application

echo "Content-type: text/html"
echo
echo "Hello, world! Query:"
echo $QUERY_STRING -- [font=monospace 99] [code=python] \# Python WSGI def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) yield 'Hello, world!'  We'll do this in two parts. ### Part 1: The Grammar #!/usr/bin/env perl6 grammar Pinpoint::Grammar { token TOP { <header> <slide>+ } token header { .*? <?before ^^ "--" > } token slide { <slide-header> <slide-content> } token slide-header { ^^ "--" (\s* <slide-setting>)* $$\n } token slide-setting { '[' .+? ']' } token slide-content { .*? <?before ^^ "--" > || .* } };  Using 'grammar' is kinda like some funky cross between a regex and a class. That is -- everything is declared like a named regex, but the result is effectively a class that has a ".parse" method we can use. We're giving the whole grammar a name, and then declaring the file structure in the body. 'TOP' is the start of the parse, which will be an entire file for me. There is one special slide that is the header-slide, and then after that some content slides. Though each bit has a name, you do a lot of things just like other regexes -- so "<slide>+" means one-or-more slides. After that it just gets broken down further and further. Probably the trickiest bit is the <?before ^^ "--" > pattern, which we see a few times. This says that if we see a "--" on the start of it's own line, then we've gone too far. Slide content has the "||" to say if we NEVER find the "--" then we should instead continue to the end of the file. ### Part 2: The Processor Now that we have a handy dandy grammar, we'll just slurp in whatever file/stdin we are given, parse, and the traverse the parse tree. There is a way to do this with Action objects (another class with methods for each of these tokens), but I didn't do that. my match = Pinpoint::Grammar.parse(slurp()); print match<header>; for match<slide>.flat -> slide { my h = ~slide<slide-header>; h ~~ s/\s*$code\=(.*?)$//; print h; if ~slide<slide-header> ~~ /$code\=(.*?)$/ { my cmd = "code-htmlize 0"; my filter = shell cmd, :in, :out; filter.in.say(~slide<slide-content>); filter.in.close; say filter.out.slurp-rest; } else { print slide<slide-content>; } }  To make this easy, I print out the bits of the parse tree as I go. the 'h' is a chopped up version of a slide-header, removing my new and magical [code=foo] slide setting. Now that I'm looking at this, I see that I didn't actually traverse into the slide-setting list for each slide... I guess that would be better than the search/replace I'm doing here. A specific thing to note is that "~" is forcing string-context here, so "~slide<slide-header>" is taking the object for the slide-header node we are on and dumps it out as a string of the content. This makes sense, though I initially found the "~" usage a bit ugly. Once we get down to a slide that has a "[code=foo]" style setting in the header, instead of printing the slide content like we do otherwise we'll run it through an external shell command. The "code-htmlize" command is some other script I wrote that takes in code and a language and outputs an HTML-colorized version using vim. Here we do the equivalent of Open2, getting a filehandle for the input and output of the external command, printing to it's input, reading from its output. That's it! A pretty readable thing that parses and traverses my slide software file format, filtering the results as it goes. Add Comment # 2015.07.26 Exploring Clojure in the REPL Tags: Clojure, REPL When I first learned Linux, my friend taught me a few commands. How to to list files, how to change directories and see your current directory, how to run things, how to ask a program what parameters it takes, and how to look at a file (ls, cd, pwd, ./foo or /usr/bin/foo or foo, foo --help, cat foo or more foo). After that I just... ran a lot of stuff. I eventually discovered 'man' -- but going through /bin and running ALL the commands was really educational. Let's get some basic tools to do that with the Clojure REPL! The major things we want to do are find things (mostly functions), and then learn all about them individually. ## Finding Things So Clojure has namespaces, which are kinda like directories, using "." as a way to indicate nesting. Vars (and thereby named functions) are kinda like files. So the full "path" to a var looks like "clojure.string/split" where "clojure.string" is the namespace and "split" is the function. First let's get a list of all the loaded namespaces. The "ns-all" gives us this, but we want a nice sorted printout, so we'll add a bit of fancy. user=> (doseq [n (sort (map ns-name (all-ns)))] (println n)) ; ... trimmed ... clojure.core clojure.core.protocols clojure.inspector ; ... trimmed ... clojure.repl clojure.set clojure.stacktrace clojure.string clojure.template clojure.test clojure.tools.cli clojure.tools.nrepl ; ... trimmed ... user  Use "dir" to look at all the exposed vars from a namespace user=> (dir clojure.string) blank? capitalize escape join lower-case re-quote-replacement replace replace-first reverse split split-lines trim trim-newline triml trimr upper-case  Search for functions with "split" in their name. There is also "apropos" but it doesn't show namespaces -- "apropos-better" does, and "find-name" is an alias of that, so is better. user=> (find-name "split") (split-at split-with clojure.string/split clojure.string/split-lines net.cgrand.parsley.grammar/split-empty-prods)  You can also use a regex! Not sure how useful this is... but here we are getting all the functions that start with an "s" and in with a "t". user=> (find-name #"^s.*t") (set short sort sorted-set spit split-at struct clojure.set/select clojure.string/split clojure.test/set-test net.cgrand.sjacket/shift net.cgrand.sjacket/shift-right net.cgrand.sjacket/str-pt net.cgrand.sjacket/subedit)  ## Learning About Things Once you've found your function, you'll want to learn more about it and maybe give it a try. "doc" can be used to get the documentation associated with a function. This is pretty cool! It shows the full name of the function, its signature, and it's documentation. user=> (doc print) ------------------------- clojure.core/print ([& more]) Prints the object(s) to the output stream that is the current value of *out*. print and println produce output for human consumption.  Note that you can tab-complete user=> (doc print<tab> print print-ctor print-dup print-method print-simple print-str printf println println-str  If you don't know what you're looking for, you can also try find-doc. This will search both the name and the documentation itself for your string or regex. user=> (find-doc "split") ; ..... too long to include ;)  THE ULTIMATE: Get the source for a function! user=> (source print) (defn print "Prints the object(s) to the output stream that is the current value of *out*. print and println produce output for human consumption." {:added "1.0" :static true} [& more] (binding [*print-readably* nil] (apply pr more)))  Not everything is a function. Heck, sometimes you might not know what sort of thing you're looking at. But we can find out. user=> (type 5) java.lang.Long user=> (type 5.2) java.lang.Double user=> (type "hello") java.lang.String user=> (type 'hello) clojure.lang.Symbol user=> (type {:a 5, :b 6}) clojure.lang.PersistentArrayMap user=> (type [1 2 3]) clojure.lang.PersistentVector user=> (type type) clojure.coretype user=> (type dir) CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl/dir, compiling:(/tmp/form-init5987247545872948247.clj:1:1) user=> (type clojure.string/split) clojure.stringsplit user=> (defn say-hi [] (println "hi!")) #'user/say-hi user=> (type say-hi) usersay_hi  ## Getting GUI Clojure comes with clojure.inspector, which gives some Swing GUI for exporing data structures. user=> (use 'clojure.inspector) user=> (inspect-tree {:a 1 :b 2 :c [1 2 3 {:d 4 :e 5 :f [6 7 8]}]})  NOTE: I had to do this to get jdk-1.7 swing apps to display while using xmonad (and other tiling window managers I guess). I now dropped this in my ~/.zshrc. Uhg. export _JAVA_AWT_WM_NONREPARENTING=1  ## Doing Horrible Things So let's have some fun. First, let's get all the string function names. "dir-fn" is like dir, but returns the results instead of printing them. user=> (def string-funcs (clojure.repl/dir-fn 'clojure.string))  Let's turn them into their actual functions. user=> (def real-string-funcs (map #(resolve (symbol (str "clojure.string/" %))) string-funcs))  Given a function, here is how to tell how many parameters it takes (well... it might take more or less than this, but this will tell us how many params for the first definition. Good enough). user=> (defn arg-count [f] (count (first (:arglists (meta f)))))  Here is a handy thing that tells us if the given function can deal with a single arg. user=> (defn single-arg? [f] (= 1 (arg-count f)))  Now let's filter our string functions down to the ones that just take one argument. user=> (def one-arg-funcs (filter single-arg? real-string-funcs))  So. We if have a one-argument function in the clojure.string namespace, let's assume it takes a string and pass in a string to it :) . The "pr-str" bit is so that we can pretty-print this with escaped newlines and such later. user=> (defn one-arg-result [f] (pr-str (apply f ["Hello\nworld\n"])))  Now let's try this on all the one-argument string functions, printing out the function name and the result pretty like. user=> (map #(println (:name (meta %)) "\"Hello\\nworld\\n\" ->" (one-arg-result %)) one-arg-funcs) blank? "Hello\nworld\n" -> false capitalize "Hello\nworld\n" -> "Hello\nworld\n" join "Hello\nworld\n" -> "Hello\nworld\n" lower-case "Hello\nworld\n" -> "hello\nworld\n" re-quote-replacement "Hello\nworld\n" -> "Hello\nworld\n" reverse "Hello\nworld\n" -> "\ndlrow\nolleH" split-lines "Hello\nworld\n" -> ["Hello" "world"] trim "Hello\nworld\n" -> "Hello\nworld" trim-newline "Hello\nworld\n" -> "Hello\nworld" triml "Hello\nworld\n" -> "Hello\nworld\n" trimr "Hello\nworld\n" -> "Hello\nworld" upper-case "Hello\nworld\n" -> "HELLO\nWORLD\n"  Woo! Add Comment # 2015.06.04 Polyglot Bridges Here are the slides for Polyglot Bridges (pdf) lightning talk that I gave today at RubyNation. The most important bit: # Shell sudo apt-get install matplotlib gem install rubypython # pending a small patch for debian/ubuntu 64bit # Ruby; even works in the REPL! require 'rubypython' RubyPython.start plt = RubyPython.import('matplotlib.pyplot') plt.plot([1,2,4,6,28,50,234]) plt.ylabel('some numbers'); plt.show  Or in other words: pull in this rubypython gem, magically get all the python libs callable from Ruby. In this case, you get all the nice charts and graphs from pyplot. I originally played with this in Perl6/Rakudo Inline::Python, where it also works fantastically. I love the idea of one community NOT completely re-writing a library in their language when it can just be used "directly" instead. Add Comment # 2013.12.26 Overtone Adventures 4 Today I'm playing with Open Sound Control (OSC), which is more general-purpose than midi but kinda similar idea. I have an android app on my phone named Control which has a few existing UIs, in my case I'm playing with the multi-touch. I set it to have two touch inputs. In my Overtone REPL, I first set it up to listen for OSC events, and dump out whatever events it sees: (def server (osc-server 44100 "osc-clj")) (osc-listen server (fn [msg] (println msg)) :debug) ; Turn off with: (osc-rm-listener server :debug)  I got both my laptop and phone on the wifi (which allows peer-to-peer communication) and told the Control app to connect to my laptop server (192.168.0.15 port 44100, in this case). Now when I touch the screen I get a bunch of messages about the generated OSC events. They look like: {:src-port 45161, :src-host 192.168.0.25, :path /multi/1, :type-tag ff, :args (0.36825398 0.3961456)}  From this I see that the path I want to react to is "/multi/1" and "/multi/2". Dragging my fingers around, the args are the x and y coordinates normalized to (0..1). For now I'll just make it beep a bit when it gets an event. I'm hooking the first touch up so the X axis generates a frequency, and the second touch up so that the Y axis generates a frequency (just as a test), giving: (osc-handle server "/multi/1" (fn [msg] (let [ x (nth (:args msg) 0) y (nth (:args msg) 1)] (demo 0.1 (saw (+ 100 (* 100 x)))) ) )) (osc-handle server "/multi/2" (fn [msg] (let [ x (nth (:args msg) 0) y (nth (:args msg) 1)] (demo 0.1 (saw (+ 100 (* 100 y)))) ) ))  Each touch plays for 1/10th of a second, so if I drag around these overlap a bunch. In fact, if I drag around a lot then something gets backed up and the sound is delayed. Add Comment # 2013.12.24 Overtone Adventures 3 Good progress today -- I made a hack to get around that BUNCHES of midi issue. Needed that because when I would hit a single note on my jack-keyboard (virtual midi keyboard), I got a whole bunch of events. I'm guessing I was getting 64 of them. I also got Overtone Vim Integration working. Well technically I already had it working (had fireplace.vim installed, etc), I just didn't know it. Now I can start up the REPL in one terminal and start up vim in another. In vim do ":Require" and it finds the running REPL and hooks into it. I also added "nnoremap <F1> :Eval (stop)<cr>" to my .vimrc, so that I can jam on F1 to make the noise stop. Here is the file I've got now: (ns noise.core) (use 'overtone.live) (use 'overtone.inst.piano) (on-event [:midi :note-on] (fn [e] (let [note (:note e) vel (:velocity e) device-name (:name (:device e))] (if (= "VirMIDI [hw:1,0,1]" device-name) (piano note vel) () ) ) ) ::midi-keyboard-handler )  So that takes midi events specifically from that device (I picked one of my 64 virtual devices at random, seems to work) piped to the piano instrument. Next I'm going to make a new instrument of my own and hook that in! Add Comment # 2013.12.23 Overtone Adventures 2 Today I'm watching Overtone and ClojureScript which is a coding session of someone setting up an web UI to play Overtone stuff. Building a UI like this reminds me of the one-string guitar that I got at an art festival the other day. Clearly home-made, including an energy drink as the echo chamber. And very awesome. Also fun to see someone iterate through their development. Lots of interesting things in there, most of them I can read more or less but doesn't mean I could write them. One thing I noticed was (:use ...) to pull in instrument libs. I'll try that. The Cheat Sheet is interesting, but I don't know enough to actually use a lot of the things on there. Current mission is to get the instruments working. Ah! I need to do (use 'overtone.inst.piano) not (:use overtone.inst.piano). • Now (piano) plays a note! • (odoc note) shows that it takes a bunch of params • (piano 60), (piano 65), etc plays some nice piano notes • I looked up named parameteters in clojure. (piano :note 65) does what I want • Achievement unlocked ... I can now use all the intstruments on the cheat sheet! • Now when I do "(piano :note 60) (piano :note 65) (piano :note 69)" (still in REPL) it plays all three notes at once. Need to learn how to sequence things. • I think I'll go back to that workshop video • At 13:40 they talk about sequencing things • Play a piano note in 1 second (at (+ 1000 (now)) (piano)) • From their tutorial, I created: • (defn loop-beats [time] (at (+ 500 time) (kick)) (at (+ 1000 time) (open-hat)) (apply-at (+ 1500 time) loop-beats (+ 1500 time) [])) • (loop-beats (now)) • (stop) • I don't know exactly what that last [] is for. (odoc apply-at) says it is "argseq" but gives no explanation. • In general this is "temorial recursion" -- delays a bit before calling back • As far as I can tell this _does_ create new stack frames! Will eventually run out. I know this because I accidentally put the loop-beats recursion in parens which invoked it. • Following the tutorial, I transformed it to use a metronome: • (def metro (metronome 180)) • (defn loop-beats [m beat-num] (at (m (+ 0 beat-num)) (kick)) (at (m (+ 1 beat-num)) (open-hat)) (apply-at (m (+ 2 beat-num)) loop-beats m (+ 2 beat-num) [])) • Get it started: (loop-beats metro (metro)) • Change the temp live! (metro :bpm 200) • Stop it (stop) • Instruments take 'notes' (midi numbers), though some things take hz • Symbolic notes can be turned into midi numbers via (note :a4) • Can map a sequence of symbolic notes to midi numbers (map note [:e4 :d4 :c4]) • Now I can make a general purpose play-note-sequence function. I'll just make it play on the beat. (defn play-song [metro beat-num notes] (map-indexed (fn [index n] (at (metro (+ index beat-num)) (piano :note (note n))) ) notes) )  • (play-song metro (metro) [:e4 :d4 :c4 :d4 :e4 :e4 :e4 :a0 :d4 :d4 :d4 :a0 :e4 :e4 :e4 :a0])OK. Midi time! Looking at Overtone wiki MIDI page • Fired up jack-keyboard (software midi keyboard) since I'm not at home • Apparently software midi doesn't get immediately detected. "modprobe snd-virmidi" gave me something I can connect to in jack • Had to restart overtone • Now I have BUNCHES of midi connections when I do (midi-connected-devices) -- like 64 of them. Too many. Comments on TLT - 2013.12.23 - Overtone Adventures 2 ### 1 Comment. test comment -- awwaiid 2015-03-12 11:47 UTC Add Comment # 2013.12.22 Overtone Adventures 1 So I've gone through Overtone Getting Started a few times, and am up and running. Only trick at all is that I already have my own jackd wrapper script to get jack started. Just like the other times that I went through this tutorial, I get to this point and say "now what?" There are two different directions to explore. I have the REPL working, but it would be nice to be able to execute from a file and also do some interactive editing via Vim (or Emacs I suppose). The other path is to ... you know ... make some music (er... noise). So I go on a reading spree. Things I learn: • There is a neat Cheat Sheet. But I don't know how to work it. • Read a bit about Sequencing on the wiki. Learned: • You can grab samples from freesounds, like: (def kick (sample (freesound-path 2086))) • You can then play that with (kick). Fun! • Something that I read before -- you kinda schedule sounds out in the future a bit. Think I saw that on a video • The main README references some video tutorials, I'm going to check them out • skillsmatter clojurex unpanel • Nice! Shows some dubstep type noise to make during a 20 minute workshop • Mentions here as I've seen elsewhere: definst uses macros to send synths to supercollider, so only a specific set of things are OK in there (not arbitrary expressions) • Shows how to sequence things a bit Add Comment # 2013.02.06 DC-Baltimore Perl Workshop 2013 I just wrote up a call-for-people post about the DC-Baltimore Perl Workshop over at blogs.perl.org. I say it all there -- but in a nutshell, come and join us! :) Add Comment # 2012.09.09 The Flooding of Bath For Labor Day weekend (last week), Beth and I took off from work on Friday, rented a car, and headed out to Berkeley Springs, WV - aka "Bath". Nice drive up there, only a few hours away from DC. We've been around there before, and this time we decided to stay in-town so we could park our car and walk around more than we have in the past. We stayed on the top floor of a Bed & Breakfast downtown. Saturday was a rainy day. We wandered about, looked at some junk shops, had lunch, took a long nap. I kept waking up to booming rolling thunder, but felt safe and cozy. Once we were up and about there was this weird siren that kept going off (sounded like an air raid) -- the inn keeper told me that it was their fire department and all-purpose alarm, and that it's not a big deal. We headed to dinner and there was some noticeable water in gutters. But we only were walking a block down the road, so no real worries. The wait staff seemed a bit... off. Nervous and stressed, I'd say. We heard them start telling people who came in after us that they needed to order quickly because they were shutting down the kitchen. Specifically because of water building up behind their building and starting to come into the kitchen! No fun. So we finished quickly and boogied out of there. Water had gotten quite a bit deeper in the street... and as we were walking back to the B&B fire trucks started to park diagonally across the road, and firemen jumped out and started directing traffic away. They were shutting down the whole road! And no wonder... the water kept rising. Walking in, the innkeeper told us that we should go out back and consider moving our car. And... that was an understatement. I should have taken photos, but I was too busy deciding what to do. Water was up to the baseboards. I waded out -- water up to my knees! -- and moved the car. Water sloshed into the floorboards, and even though I moved the car to higher ground, I still had to go back and scoop water out. Ick! Well, water was quickly rising and was even threatening to broach the B&B porch itself, which holds their outdoor restaurant and wine bar. After hanging out a bit longer we decided it was best for us to just abandon this whole scene. We packed up and drove back to DC. As soon as we left the road cleared and the rain stopped. It was a nice drive back to DC, and we were back in our apartment by 10:00pm. Whew! Sunday was stressful returning of a water-damaged car... and we were very pleased to have Monday to just relax :) Here is the high-water mark in the park. The water "only" went up to my knees out on the street, but in the park it was quite a bit deeper. I unfortunately didn't get a before-photo of the pool... but it was a beautiful clean blue. They say that this was a 100-Year Flood! So I guess we shouldn't worry about going back to try again :) (Images courtesy of The Huffington Post, and herald-mail.com) Add Comment # 2012.08.28 Code Comments, Yo I've traditionally thought of code comments as having two audiences. One audience is me, or whomever will be taking over the code after me. This consists of notes or hints as to what I was thinking when I wrote something. Typically these are regular code comments, possibly right on the end of a line. The second audience is the users of my code. Usually this is other programmers, in the case of a library (as opposed to the consumer of a resulting UI, which I guess is a sort of third non-engineer audience who doesn't read _code_ comments). This second group is the one for which you typically use POD (or similar in other languages - javadoc). Increasingly, however, I have decided to act as though there is only one audience. When you separate code out the way I describe above, you immediately run into a question -- what do you do for a private method? You don't expect the users of your library to call it, and yet you might have some high-level usage guide that goes beyond what you might put in an inline comment. Same thing for private instance variables, or other internal helper functions. I've also noticed that I have two different sets of code that I write, and for each there is ultimately one audience. The first is at work. Here I am writing code that my peers will use. But my peers will also _maintain_ the code itself. Similarly, I also write code for open-source projects. For the most part my code here will be consumed - but if and when I do actually get contributions to the library, the contributors are the consumers first and contributors second. They are pretty much exactly like the people at my work. So I've settled on physically organizing my code into two sections, but using POD (or similar) for all of the usage or explanation-centric comments, and I treat my reader as a single audience. I put the public API methods all together, and notate them as a single section in my code, perhaps with a preamble with an example usage. I then put all of the private methods together, with a header that marks them as private -- but then I document them as if they were public. Because no matter what, from the perspective of the code IN my library, they ARE public. Add Comment # 2012.08.20 First Day in CS440 I'm watching the first video for the CSU CS440 Intro to AI class, taught by Chuck Anderson. Man... so far this looks great. In addition to delicious shout outs to Turing and Hume and so on, tossed out a reference to the XKCD take on some AI concepts. Did I mention that we are using a wiki rather than WebCT as our primary interaction point? hmm! I haven't seen the video for the CSU CS414 Object-Oriented Programming course. Add Comment # 2012.07.10 Hi Eliza Eliza: I am the psychotherapist. Please, describe your problems. Each time you are finished talking, type RET twice. Me: My friend Mike doesn't know who you are. Eliza: Why do you say that? Me: Because I mentioned you and he said that he hasn't heard of you. Asked me if you were some sort of reference. Eliza: Is it because you mentioned me and he said that he has not heard of I asked you if I was some sort of reference that you came to me? Me: Yes, exactly! Eliza: Earlier you said you mentioned me and he said that he has not heard of I asked you if I was some sort of reference? Me: Right. Because a lot of lore from the '80s came from you. Eliza: Does it bother you that a lot of lore from the '80s came from me? Me: No, I rather enjoy it. Eliza: Maybe your plans have something to do with this. Comments on TLT - 2012.07.10 - Hi Eliza ### 2 Comments. Clearly Eliza knows about my secret timemachine experiment! -- awwaiid 2012-07-11 11:33 UTC Funny, I was just reading some stuff about Eliza (and Parry) in an ancient AI book that gave all its example codes in BASIC. Fantastic stuff. -- BatmanAoD 2012-08-22 03:15 UTC Add Comment # 2011.10.11 PPW 2011 Wrap-Up This weekend I attended PPW2011 - I think this is my 3rd PPW, and my fourth perl conference in Pittsburgh (YAPC::NA 2009 was there). The theme this year was "DevOps", and I think maybe that was not quite to my taste (though does seem practical). I like talks that push my understanding and stretch my mind, whereas the talks tended toward solid best practices for corporate environments. I gave a talk on debugging, and I even feel that my own talk went that way a bit :) Favorite talks: That last one was a set of mini-talks by Mark-Jason Dominus, which included one of my all-time favorites, Debugging the de Bruijn Sequence. Highly recommended! Add Comment # 2011.08.07 DC Perl Mongers August 2011 Meeting Last Tuesday was our monthly DC Perl Mongers meeting. We dove right in, talking about how perl caches various values for a variable to be used in different contexts. So, for example, let's say you start off with a number, but then use it in string context, perl will cache both the string and the number. This can be shown using Devel::Peek like this: main:001:0> use Devel::Peek main:002:0> my x = "34" 34 main:003:0> Dump(x) SV = PV(0xb22d558) at 0xb237290 REFCNT = 2 FLAGS = (POK,pPOK) PV = 0xb249458 "34"\0 CUR = 2 LEN = 4  I often use Devel::REPL at meetings so that we can interactively explore things as a group, which is what I'm doing here. The first time we dump x, you can see it has a "PV" which holds the string "34". But after we use it in a number context, adding 17 to it, you can see that the dump shows both the original string version, and a new "IV" containing the integer version: main:004:0> x + 17 51 main:005:0> Dump(x) SV = PVIV(0xa0fe6b8) at 0xb237290 REFCNT = 2 FLAGS = (IOK,POK,pIOK,pPOK) IV = 34 PV = 0xb249458 "34"\0 CUR = 2 LEN = 4  So this, as far as I know, is mainly an efficiency hack that perl does, the theory being that if you used it once in string context or number context or whatever, maybe you'll do it again. Very quickly the question came up as to what happens when you change x, and how does perl know what cached values to trust. Well that's where the 'FLAGS' part of the SV dump comes in. It shows which of the cached values are OK to use. So when we increment x numerically: main:006:0> x++ 34 main:007:0> Dump(x) SV = PVIV(0xa0fe6b8) at 0xb237290 REFCNT = 2 FLAGS = (IOK,pIOK) IV = 35 PV = 0xb249458 "34"\0 CUR = 2 LEN = 4  The flags have been trimmed down. I don't remember what all the flags mean, but you can look at perlguts or other docs for that :) . Notice that the string version of the original "34" is still there! Perl doesn't waste time erasing it. Instead, if string context is used again a new cached value will overwrite the existing one. Well that was surely a good start to the meeting :) Add Comment # 2011.04.07 Funky Function Filters in Perl6 A while back I wrote about Funky Function Filters. Let me refresh your memory - we have a Python and a Ruby snippet and we translate it into Perl5. The code is a toy to show some fancy shmancy lambda (unnamed functions) usage. The idea is to take a list of functions, filter them, and then with the remaining ones show what happens with parameters from -10 to 10. Python example: for f in filter(lambda f: f(-1)>=f(1), [lambda x:x, lambda x:x**2, lambda x:x**3]): for x in range(-10, 11): print x, f(x)  Ruby translation: for f in [lambda { |x| x }, lambda { |x| x**2 }, lambda { |x| x**3 } ].select { |f| f.call(-1) >= f.call(1) } for x in -10..10 print x, f.call(x) end end  My perl5 translation: for my f (grep { _->(-1) >= _->(1) } ((sub{shift}, sub{(shift)**2}, sub{(shift)**3})) { for my x (-10..10) { print "x: ",f->(x),"\n"; } }  Today I thought I'd give a stab at a perl6 translation (using the 2011.01 Rakudo Star release). I started with a straightforward translation from the perl5, then switched to perl6 idioms. Perl6 translation: for (* ** 1, * ** 2, * ** 3).grep({ _.(-1) >= _.(1) }) -> f { for -10 .. 10 -> x { say "x: { f.(x) }" } }  The first line is a doozy! This is similar in some ways to the perl5 translation, though the grep now shows up on the righthand-side of the list like in Ruby. The biggest difference to me is in the list of lambdas: (* ** 1, * ** 2, * ** 3)  I mean... what does THAT mean?! Let's take the last one, "* ** 3". Translated into English: Whatever to-the-power-of 3  Wait wait... "whatever"? The Whatever-Star is a fancy thing from perl6 that took me a while to work out, and there may still be some nuances that I'm missing. In this context it magically makes a closure... er... lambda, that takes one parameter which it puts where you see the '*'. # Whatever-Star notation * ** 3 # Pointy-block notation -> x { x ** 3 } # Subref notation sub (x) { x ** 3 }  (Note: that last one should be SLURPY! But I don't know how to do that apparently) Enjoy... Whatever! Add Comment # 2011.03.13 Wishing on a Whatever Star The "Whatever-Star" was at first alarming to me! I first noticed it when I learned how to shuffle an entire list. The Whatever-Star can do some other stuff, too. But that's ok, we'll start with this. my @shuffled = < alice bob carol dave erik frank >.pick(*);  Now... in the past I've tried ".pick(1)" which gets me one name at random. Then ".pick(2)" will give me two, and not repeat. If I put in too many then it'll only give me back what it can, in this case all six names. But ".pick(*)" ... that doesn't even look valid! The documentation says (though I can't recall where) that it is the same as ".pick(Inf)". When I picked more than there were, it stopped when there was nothing to pick. So this makes sense... try to pick an infinite number and we'll just get them all. Nice. Still kinda weird about the '*' though. So then I, mistakenly, thought that maybe "pick" was special. Maybe they hooked the parser up so that it could, like, "know" that pick could be passed this '*', which I learned is named "Whatever". I couldn't have been closer to the truth! Except without the "special" bit. Time to do a bit of exploring! Let's try to figure out how this works without resorting to such tedious things as reading documentation, source code, or IRC, shall we? RTFM my eye. If pick is special, then I shouldn't be able to add something that behaves similarly. Wait, let's do this formal like. THEOREM: (1,2,3,4).pick(*) is somehow special, and can't be replicated without modifying the compiler. PROOF: Let's start by assuming that it is NOT special, and attempt to do a proof-by-contradiction (constructivists be damned¹). Then we should be able to create our own method that can behave specially when '*' is passed. First, what class is .pick(*) working on, anyway? Let's ask rakudo. > (1,2,3,4,5).WHAT Parcel()  Parcel. OK, whatever that is. So all we gotta do is slap a new method on there and see what we get. (google... google... irc... (yes, contrary to the overall anti-research basis. But it's ok because we're in parenthesis)). OK, here we go. > use MONKEY_TYPING; augment class Parcel { method yo(x) { say "I like to eat x." } } !class_init_384 > (1,2,3,4,5).yo('fishies') I like to eat fishies.  Well that was easy :) . Now for the BIG TEST! > (1,2,3,4,5).yo(*) I like to eat Whatever()<0xb2f5a7c>.  OMG it worked! So I actually get a parameter, and it is an instance of Whatever. Well then. THEOREM DISPROVED. I then decided to actually cast about for how things use this. Here's a great example, the Rakudo Any-list pick whatever implementation. You can see that they use multi-methods to easily deal with the Whatever case separately from other passed values. [1] I actually like constructivists, and welcome a constructive version of this non-proof. Add Comment # 2011.03.12 Filter Rocking Tags: Coffee, Music On my way to Safeway, I stopped in at Filter Coffee to see how they are doing. The nearby Safeway (The Secret Safeway) is closed, but this is still roughly on the way to The Soviet Safeway anyhow. A seat was open so down I plopped. First they played the entire Rage Against The Machine, Battle of Los Angeles album, and now we're on to the Ramones with Blitzkrieg Bop. Sounds like they're going to play this whole album too. Good music, good mocha. Where was I on my way to again? Add Comment # 2010.11.16 I Knew A Girl This song popped into my head today, and the muse took it all the way to a recording! Comments on TLT - 2010.11.16 - I Knew A Girl ### 3 Comments. Wonderful song, Brockers - I love it!! -- ailanie 2010-11-17 16:30 UTC Thanks! -- awwaiid 2010-12-07 03:52 UTC I really like that! Very nice! -- lungching 2011-02-02 03:25 UTC Add Comment # 2010.09.03 DC Perl Mongers Rakudo Star Pizza Party We're starting our usual monthly DC Perl Mongers meeting a bit early this Tuesday (September 7th) to have a little pizza and celebrate Rakudo-Star! Arrive at 6:30pm at the Starbucks at 18th and K Street NW (call me, Brock, if you miss us and need to be let in, number on the website) if you want food. But feel free to wander in any time thereafter, we usually stay as late as 10:00pm. We'll swoop down and look for people at the normal 7:30pm time too :) Other activities: • Bring your laptop! • Installing Rakudo-Star • Giving hands-on tutorials • Beginner and Advanced welcome! • Never been to DC.pm before? No problem, come have some free pizza! Please put your name on http://dc.pm.org/Rakudo-Star_Party (or email the mailing list, which can be found at http://dc.pm.org/) so we know how much food to get. If you have any questions, email the list or me directly -- awwaiid@gmail.com will do :) About Rakudo Star: "Rakudo Star" is a useful and usable distribution of Perl 6. Current releases are aimed at "early adopters" of Perl 6. We can tell you ALL about it when you arrive :) Add Comment # 2010.08.15 Chinese Spam Ever since I got my terminals and mutt all working well with international characters, I've been fascinated by the Chinese spam I get. First of all it looks neat to see in a terminal. But sometimes I throw it into google translate just to see what it is I'm getting spammed about, and every now and then it's mildly interesting. Take this for example: 任可一种管理绩效的产生，首先都是原于一种先进的管理理念。而任何一种先进的管理理念都必须有一种适合它的管理模式作为载体。人们似乎都很乐意去接受先进的理念，并且善于以最惊人的速度去传播。可是人们在践行的过程中得到的结果却是参差不齐。就象丰田的精益理念早就传遍了整个世界一样，而世界却始终未能复制出第二个“丰田”。这究竟是为什么呢？主要原因在于人们虽然已经接受了新的理念，却没有能够找到其精髓的所在。因此也就无法去设计一种适合自身需要的管理模式来作为载体 Which translates (probably very poorly since it is machine translation, but good enough for bloggin') to: Either a management performance can be produced, first of all are the original in an advanced management concept. The possession of any advanced Management philosophy that it must have a suitable management model as a carrier. People seem very willing to accept advanced ideas And good at the most to spread at an alarming rate. But people in the course of practice the results obtained is mixed. On Like Toyota's lean philosophy had already spread throughout the world as the world has never been able to replicate the second "Toyota." Is this why? Although the main reason is that people have accepted the new idea, but not able to find its essence Lies. Therefore will not be able to design a management model for their own needs as a carrier. As someone who has been involved with companies who adopt Lean-like philosophies, I couldn't agree more! Add Comment # 2010.08.01 OPW 2010 (er... Actually I meant to post this sometime back in like February 2010. Oh well!) I attended the Orlando Perl Workshop 2010 and had a lovely time. The talks I attended were: And... I got to see aligators! Well... things that looked like them anyway. (insert photo here) My whirlwind trip wasn't too stressful, as it turned out. I hung out mostly with Sartak and Miyagawa, and made lots of progress on Continuity::Adapt::PSGI. Lots of side-discussion on all sorts of things too, of course. It was a good weekend! Add Comment # 2010.07.10 Hotel Yorba I love this song so much, and it is as fun to play as I imagined. Add Comment # 2010.07.10 HTML-FormHandler, KiokuDB, and Continuity I saw some article about HTML::FormHandler, and decided I'd give it a try. I'm probably not really using it as intended... and I'm also not pushing this confluence of tech nearly as far as it can go. #!/usr/bin/perl use strict; use MooseX::Declare; use KiokuDB; use Continuity;  First we just pull in some libraries. We'll use MooseX::Declare for fun :) . Now let's make a lovely base class for our forms, to set up some good defaults an an updater. # Base class for all forms class Form extends HTML::FormHandler { has owner => (is => 'rw'); our form_count = 0; has '+name' => ( default => sub { return "f-" . form_count++ } ); has '+html_prefix' => ( default => 1 ); method update { if(self->validated) { my v = self->value; foreach my field (keys %v) { eval { # ignore validation issues :) self->owner->field(v->{field}) if self->owner->can(field); } } } } }  That stuff about the form name is so we can display multiple forms on a page, each with it's own unique name. The update method ties my form to my actual object. I ignore errors for now... though really that's losing a big part of what HTML::FormHandler provides. class BasicPersonForm extends Form with HTML::FormHandler::Render::Table { has '+field_list' => ( default => sub {[ name => 'Text', birthday => 'Text', save => { type => 'Submit', value => 'Save' }, ]}); }  Here I'm building on my Form base, making a form specific for my Person class. This is declaratively specifying which fields to show and in what order, along with a lovely save button. In theory I'll be able to expand this into subforms and compose them and so on. Though I'm roughly OK with listing inputs for the form, it annoys me to have to specify the types. That, at at least a basic level, should be readable from the fields to which this form is connected. So one thing I'm noodling is using the rendering and validation, but importing the types from the data class. I think the Form::Processor::Model::DBIC does this a bit. class Person { use MooseX::Types::DateTimeX qw( DateTime ); has name => ( is => 'rw', default => sub { '' } ); has birthday => ( is => 'rw', isa => DateTime, coerce => 1 ); method basic_form { BasicPersonForm->new( owner => self, init_object => self ) } }  My Person class is straightforward. I used the DateTimeX thingie to auto coerce stuff magically. And that basic_form method is just a helper to create a form for a given instance. sub main { my r = shift; my db = KiokuDB->connect( 'dbi:SQLite:phone.db', create => 1 ); my scope = db->new_scope; # This is a new person, pending some data my new_person = Person->new; while(1) { my @people = db->grep(sub { ref(_) eq 'Person' })->all; my @forms = map { _->basic_form } @people; foreach my form (@forms) { r->print(form->render); } r->print("<h3>Add person:</h3>"); my new_person_form = new_person->basic_form; r->print(new_person_form->render); r->next; my params = { r->params }; foreach my form (@forms) { form->process( params ); form->update; db->update( form->owner ); } new_person_form->process( params ); new_person_form->update; if(new_person->name) { db->insert( new_person ); # And now queue up another new one new_person = Person->new; } } }  This is a little Continuity app, so main gets called and passed r, which is the request handle. After setting up our KiokuDB (with SQLite backend), I enter an endless loop of showing the forms and the processing the results. Oh, and I create a special Person instance for holding a new person. In the loop, I grab all the people objects in the DB at once (this is a demo, so I skipped iterator/paging stuff), make a form for each, and then render the forms. I also render the new-person object in case they want to add a new one. Next I call 'r->next', which waits for the user to submit the forms. This is Continuity magic, which inverts the web app to make it more like an interactive command line prompt. You can kinda think of this line as "input = <STDIN>". Once that comes back I put the submitted data into a variable and use it to update each of the forms (and updating each back into the database). Finally I check to see if they submitted data for the New-Person, and if there is anything I insert it into the DB. # Get things going Continuity->new->loop;  Last but not least, we start the Continuity loop, which starts looking for requests and calling main() for each new session. So I found this all pretty interesting, and it overlaps with some of my other object-rendering experiments. I could probably add to this for pulling field metadata from objects into forms and organizing subforms and so on. Maybe next time :) Add Comment # 2010.06.04 Mercurial Bisect So at work we're switching over to Mercurial (hg), and I'm trying out some of the more advanced features. One which I've been looking forward to for a while is 'bisect' (which git and others have also). The idea is straightforward. I have a unit test that fails. I know that it worked like a month ago or something. Someone committed something between then and now that made it fail. But what was it? Bisect will systematically help find it -- start in the middle, and if it was good there go back half of the remaining time. If bad, go forward. In just a few chops like this it will narrow down to the exact commit that caused an issue. This works well in Mercurial (and Git) because it is really really fast to revert to a previous version of your code. By far the longest part of the process in the process was executing the unit test itself! Here are the steps I went through. I'm using Mercurial 4.3, by the way. bwilcox@wickedwitch:~/dev-rel172 hg bisect -r First I "reset" the bisect. That just means, let's begin! bwilcox@wickedwitch:~/dev-rel172 hg bisect -b Now I marked the current revision as "bad", since my test fails. bwilcox@wickedwitch:~/dev-rel172 hg bisect -g 51303 Testing changeset 51497:3f631045f30d (196 changesets remaining, ~7 tests) 124 files updated, 0 files merged, 26 files removed, 0 files unresolved  I looked back at history before I started this and decided that this test definitely passed at revision 51303 -- that was just before our last release and all the tests passed. So here I'm saying that I know for _sure_ that it was "good" at revision 51303. Now comes the fun part. bwilcox@wickedwitch:~/dev-rel172 hg bisect -c 'bin/test_suite.pl bin/t/default/pnr_phase1/14-task_acquisition_approval.t | grep PASS' Changeset 51497:3f631045f30d: bad Result: PASS Changeset 51404:8b0f3381e3f5: good Changeset 51449:f3b668e05928: bad Changeset 51415:ebc770d284d3: bad Result: PASS Changeset 51409:dfd5706dc765: good Result: PASS Changeset 51412:e33660e38ea0: good Result: PASS Changeset 51413:d1390b75856f: good Changeset 51414:d39f58b490ab: bad The first bad revision is: changeset: 51414:d39f58b490ab user: chiggins date: Tue May 18 21:34:51 2010 +0000 summary: RT: https://rt.liquidation.com/Ticket/Display.html?id=733702  In case it isn't clear, the command that I ran is: hg bisect -c 'bin/test_suite.pl bin/t/default/pnr_phase1/14-task_acquisition_approval.t | grep PASS'  This instructs Mercurial to keep going, and use my test_suite.pl command to decide whether a particular revision is "good" or "bad". The "-c" parameter runs what you give it and looks at the exit status to decide if it is good or bad. It just so happens that the "grep" command returns exit status depending on whether it found something :) . So I'm grepping for the "PASS" that comes at the end of a standard perl test suite to indicate that the current revision is good. And then off it runs! Test... bad. Test... good. Test... bad. And so on, narrowing it down to the exact revision which was the first to fail the test! From there I took a look at that revision, and immediately saw what the problem was. Easily fixed, and now my test suite passes with a clean bill of health. Aw hells yes. Comments on TLT - 2010.06.04 - Mercurial Bisect ### 2 Comments. Hmmm, the documentation on mercurials wiki seems to be out of date. http://mercurial.selenic.com/wiki/BisectExtension?action=show When you run the test through -c is that using a static script from the initial revision or does that test need to be in all the revisions, possibly altering the script if it was changed in a previous revision? I would think it uses a static script, in which case it would mean that you don't necessarily have to have the test in the 'good' revision but can create it after the fact. -- lungching 2010-06-09 12:32 UTC In the example I provided, my test case is actually located inside of my repository. Thus each execution is indeed running the version of the test from the currently selected revision. In this case I like that, because the test itself might have broken and I'd like to detect that case. If, however, you need a static test, you can just point to something outside of your repository and it should work the way you describe. -- awwaiid 2010-06-09 16:11 UTC Add Comment # 2010.02.07 Cultured Perl Tags: Perl You might have stumbled upon some IBM developerWorks articles titled "Cultured Perl" while googling for random things. I think it's awesome and that it isn't linked to enough. Just a few weeks ago the latest article came out, Cultured Perl: Storage management on Amazon S3, which is well written and up-to-date with the latest technologies. Thank you, Cultured Perl! Add Comment # 2009.12.16 Better Creox Example So I was right, I completely messed up the previous example and it wasn't electrified by Creox at all. But I've rectified this situation, and for your listening pleasure (pain?), here is a smaller snippet of just the guitar part of the song, before-and-after. Original acoustic guitar (mp3 file) Electrified by Creox (mp3 file) Add Comment # 2009.12.06 Music Play I was playing with Creox the other day, which can make an acoustic guitar sound electric (amongst other things). I recorded a quick song... but it doesn't sound nearly as electric when I listen to it now as it did when I first recorded it (and now I wonder if I even had my Jack settings right for recording what I was hearing...). But it did end up with a fun crackly sound on the voice I think. Listen for yourself: "Oh my baby" (mp3 file) And it gave me an excuse to add an mp3 player plugin :) Comments on TLT - 2009.12.06 - Music Play ### 2 Comments. But you added a flash mp3 player! -- e2thex 2010-06-04 21:37 UTC Eh? Is that good or bad? I'll add an HTML5 player someday :) -- awwaiid 2010-06-07 12:17 UTC Add Comment # 2009.11.15 The Internets Make Programming Easy In the class I'm taking (Intro to Data Mining) we get to implement a classifier. Alas... we must use either C++ or Java. I haven't programmed in either for quite a few years, and even with further pursuit I'm not allowed to use OCaml. That's OK! Best to stretch my mind out a bit. I'm afraid I'm getting rusty at being multi-lingual in my old age anyway, so this is good exercise. First thing first, I have to read in the training data. But best start with the basic Hello World even before that. Google... I figure I'll start with the basics, and now I have: #include <iostream> using namespace std; int main() { cout << "Hello World!" << endl; return 0; }  I don't even remember doing that std namespace thing last time I programmed in C++. Oh well. It runs! So from there I just keep searching and adding... ... and just like magic I am now reading the file, parsing it, and counting the frequency of items. Ahh the hive mind! Here's the result... it's messy and unstructured but damn... it works! // Compile: g++ -o demo main.cpp #include <iostream> #include <fstream> #include <vector> #include <boost/algorithm/string.hpp> #include <map> using namespace std; typedef map<string, int> ItemSet; int main() { cout << "Hello World!" << endl; ifstream fin("data/train1.txt"); // ifstream fin("data/small_train.txt"); string s; vector< vector<string> > d; ItemSet itemset; while(getline(fin,s)) { vector<string> row; // cout << "Read from file: " << s << endl; boost::split(row, s, boost::is_space()); d.push_back(row); } vector< vector<string> >::iterator d_iter; vector<string>::iterator row_iter; for(d_iter = d.begin(); d_iter != d.end(); d_iter++) { cout << "[ "; for(row_iter = d_iter->.begin(); row_iter != d_iter->end(); row_iter++) { cout << *row_iter << " "; itemset[*row_iter]++; } cout << "]" << endl; } cout << "Itemset:" << endl; ItemSet::iterator itemset_iter; for(itemset_iter = itemset.begin(); itemset_iter != itemset.end(); itemset_iter++) { cout << itemset_iter->first << " : " << itemset_iter->second << endl; } return 0; }  I'll keep going like this for a bit, but then I'll start organizing into actual objects and such. There is a good chance that I'll switch data structures, or perhaps not even bother keeping all this in memory. Most likely I'm also violating some other C++ socio-political norms. Fun! Comments on TLT - 2009.11.15 - The Internets Make Programming Easy ### 2 Comments. The good ol C++. Btw, What's the g++ i see at the starting comment line of yr coding? -- melaleuca malaysia 2010-06-08 13:52 UTC I'm using the gcc toolchain, which is an opensouce compiler suite. g++ is the name of their C++ compiler. So... are you a real person, or just a very context aware advertisement? Your question is specific enough that I think I'll leave your name/link in any case :) -- awwaiid 2010-06-09 00:52 UTC Add Comment # 2009.08.25 Trace With State I've got to get this idea written down so that I can go back to doing other things... it is too distracting as-is. In a nutshell -- more or less Devel::Trace except that at each step you record all of the lexical (global?) state. Then you can not only see the full execution history of your program, but the value of every variable at every point. Now of course from the idea comes all of these questions -- do we store all that or just some of it (just what changes). Do we only keep local lexical scope at each step since the rest can be reconstructed? How do we record this... do we summarize it somehow? And so on. But ignoring all that... the next idea that comes to my mind is to toss this into CGI::Inspect as a module, so that you can use the GUI browse not just the current lexical state (there is already a plugin for that), but also the complete historical state as well. I got the idea from the Omniscient Debugger, but I'd actually seen it before in its more highly evolved form in the OCaml Debugger. The OCaml Debugger doesn't have to actually save all that state though, since in a lovely functional language you can actually just reconstruct the previous state (I believe). Still. (If you're still reading and want something even MORE insane, then your homework is to use Nothingmuch's delimited continuations in perl and make it so that you can actually resume any of the historical states). Code might eventually show up at http://thelackthereof.org/projects/perl/Devel-TraceState or perhaps Devel-TraceState. Add Comment # 2009.08.25 Now I Have A Real Blog I was just exploring the latest and greatest Oddmuse modules, and see that someone made it easy to embed youtube/google videos. So now I feel like I have a real blog and I can post the random crap that everyone else does! To prove it, here is a totally awesome song my friends turned me on to: Add Comment # 2009.05.08 Pause My Music Tags: perl, linux, music Oh how I love linux... perl... scriptability. I have a fun little command line music player named Polly. It is pretty minimalist, really just starting whatever player I like with whatever preferences I like on a whole directory tree of files. One thing that is annoying is that I have to switch over to the terminal and it ^Z to pause and then do 'fg' to play. So I finally decided to write a simple pause toggle script. I approached this in the most brute force way I could... I just take the list of all my media players and send a massive STOP (effectively ^Z) command to all to pause, and then a massive CONT (effectively 'fg') to all to continue. To determine if I want to pause or continue, I just look to see if I have any paused player processes. my @commands = qw( ogg123 mpg123 mplayer vlc sidplay2 ); my cmd = join '\|', @commands; if(ps a -o state,cmd | grep 'cmd' | grep ^T) { map { killall -SIGCONT _ 2>/dev/null } @commands; } else { map { killall -SIGSTOP _ 2>/dev/null } @commands; }  Add Comment # 2008.11.29 DNA Memory Scott linked an article from new scientist, Memories may be stored on your DNA, which relates with what has been on my mind lately. I was reading about some hardware evolution experiments while at the bookstore the other day. They were using a FPGA to create (evolve) a sine wave generator, if I recall correctly. The end result of the first run worked perfectly, but had some bizzare attributes -- it programmed a section of the gate array but didn't wire that section to the rest. When the unconnected section was turned off, the circut no longer worked. It also didn't work when the same design was put onto an identical FPGA. As far as the experimenters could tell, the evolved solution depended upon some subtle property of that specific FPGA chip. In other words: GP solutions cheat like hell. They will use absolutely any available subtle or side-effect aspects of environmental conditions to push themselves to the next rung on the fitness ladder. An important lesson that I've taken from GP is that artificial / automatic program generation mostly results in programs that make almost no sense from a human programmer perspective, at least partly because of all this cheating. The solutions produced by GP are mostly twisted convoluted things which mostly don't look like they work at all, let alone solve anything. When a human abstracts things, it ends up taking a much more layered structure, with the meat of the problem usually ending up on the highest layer. Automatic techniques do not succumb to such niceties. Speaking of human abstraction, I recently stumbled upon the Discordia page of Mark-Jason Dominus which makes a keen observation with fascinating attributes - "In a well-designed computer program, No two components are alike, or even similar." Conceptually, that is, all similar aspects of a program are abstracted. Good programs are themselves not like the beautiful fractals of recursion that lay in the mind of their creator or the algorithms that they represent. You could perhaps think of them as the compressed version -- the most informationally dense form of the logic, information theory might say. Now take it full circle... from the biological inspired computation back to biology. Biological evolution cheats just like artificial evolution does. At first glance we see all this lovely DNA-level abstraction... but as they dig in they find all sorts of trickery that operates on all levels low and high. Like throwing in some assembly (or even better, some binary executable blobs) into the middle of my blog software. The re-use of DNA (or perhaps the coating on DNA was it?) as memory storage in the brain is completely typical. If the designers were indeed intelligent, they sure didn't plan on doing any maintenance. Comments on TLT - 2008.11.29 - DNA Memory ### 2 Comments. Thanks for adding links! -- awwaiid 2009-06-13 04:00 UTC You're very welcome. I hope that clears it up for future readers. -- Mortal 2009-06-13 22:08 UTC Add Comment # 2008.10.21 Slow Android Development It's been over 4 hours since Android was released... but still no port to the Neo. Pft. Add Comment # 2008.07.24 OSCON Lighnting Talk At the last minute I ended up giving a Lightning talk at OSCON 2008 (in the Perl track). I showed my Devel::REPL + Continuity debugging tool. Here are my notes: Lightning Talk OSCON 2008 Brock Wilcox awwaiid@thelackthereof.org See also: * Continuity * Continuity::REPL * Devel::REPL * Carp::REPL * PadWalker # .... These were then run in the REPL .... # counter.pl at: # http://thelackthereof.org/projects/perl/Continuity-Monitor/eg/counter.pl use PadWalker 'peek_my'; my h = peek_my 23; { h->{'counter'} } = 77; # Then... sub new_prompt { my (request) = @_; request->print("Muahahaha!"); return old_prompt(@_); } *old_prompt = *prompt; *prompt = *new_prompt;  Add Comment # 2008.07.08 Walkabout Some of my family came to visit this weekend, and we did a bunch of sight-seeing. Here are the distance estimates, this is definitely a lower-bound of the amount we walked. I tried to include walks that I know everyone did, and left off a bunch of random trips to the store. Distances are in miles. ## Day 1 - Zoo and Fireworks • 3.1998 to and through zoo • 0.3037 from dupont metro to apartment • 3.6359 to fireworks and back TOTAL: 7.14 ## Day 2 - Smithsonian and Folk Festival • 0.3037 from dupont metro to apartment • 1.9614 Smithsonian and folk festival • 0.3037 from dupont metro to apartment • 1.0309 to play music and back TOTAL: 3.6 ## Day 3 - National Cathedral and Arlington Cemetary • 0.2353 apartment to bus stop • 0.7487 at cathedral • 0.6753 at Arlington Cemetary • 0.3037 from dupont metro to apartment TOTAL: 1.96 ## Day 4 - Library of Congress and Memorials • 0.8012 at library of congress • 3.3956 at memorials TOTAL: 4.2 GRAND TOTAL: 16.9 miles I'm guessing that adding in more detail could easily add another mile or more. In the end I bet we walked about 20 miles in all. When you trade a car for your feet, make sure you have good shoes! Comments on TLT - 2008.07.08 - Walkabout ### 1 Comment. great walkabout notes! --- btw, if in DC area and want a walking companion any time, don't hesitate to ping me (though I'm mostly into jogging) ... (confession: main purpose of this is to test the Comment Count feature) ^z -- Mark Zimmermann 2008-08-11 11:53 UTC Add Comment # 2008.06.30 More Photo Goodness I got another new camera! The last two didn't work out for very long, but this one has promise. I won it at our recent Corporate Bowling event... it was clearly my best score ever at 167. I got second place and thus the camera. Woot! This first image is one of Sophia's flowers. Sophia is the rose bush that Beth got from my family in condolence of her appendectomy. After almost killing her (Sophia, that is), I've nursed her back to health and we've been rewarded with new blooms. Other than random events and trips, one thing I'd like more photos of is my balcony garden. Time lapse or something fun. I sit there and stare at the thing enough... I may as well share the green joy with the world! Lets see... what what other sorts of boring photos do people put on their blogs... CATS! I must have some of those somewhere around here... Comments on TLT - 2008.06.30 - More Photo Goodness ### 1 Comment. Nice Potato Plants :-) -- ailanie 2008-07-10 18:49 UTC Add Comment # 2008.05.12 Tree Style Tabs I've been using the Tree Style Tabs Firefox extension for a few months now, and love it! Having vertical tabs has always been fabulous, ever since I first encountered them in Galeon. The chrome-css hack that I have been using for the last few years in Firefox stopped working in Firefox 3 (beta), so I went exploring and am very glad I did. Not only does the Tree Style Tabs extension give my my vertical tabs, it also gives me (surprise surprise) a tree of them! Each has it's own browsing history, and subtrees can be collapsed and reordered and all that wonderful goo. Just now I was playing around with the settings and thought I'd try the auto-hide feature. I'm not sure I'll keep it because there is a slight flicker that bothers me... but it is neat none-the-less! The tab bar is hidden, and then when I mouse or keyboard activate it the bar appears translucently on top of the page. It might need some kinks worked out (or perhaps there is some other cause for the flickering), but I think I like it! Highly recommended. Add Comment # 2008.03.30 Making Music I love to create and build -- lately I've made a few songs! My friends like to play guitar and sing, and I play the harmonica and am learning guitar. So here are my recent creations (all with the help or in conjunction with friends): Only the middle one has a recording posted so far, but I'll get recordings of the others sooner or later. More to come I hope :) Comments on TLT - 2008.03.30 - Making Music ### 1 Comment. Test Comment -- awwaiid 2008-05-26 22:26 UTC Add Comment # 2008.01.02 Events vs Actions in UI Code Happy New Year! I've been grappling with a concept for a long time now (years), and thought I'd put it down here to cast about for insight. Here is one way to handle UI events: page->add_action(add_new => 'Add New Entry'); page->display; # displays template, waits for input action = page->get_action; if(action eq 'add_new') { add_new_entry(); }  Here is another: page->add_action('Add New Entry' => sub { add_new_entry(); }); page->display; # displays template, waits for input, runs callbacks  The first is quite imperative. Show the page. Give me the result. Examine the result. Act. The second is much more declarative. I declare that were such an action to occur, this is what you should execute. The second is the way that Seaside handles things. I'm not quite sure why I'm reluctant to adopt this method... perhaps simply my lack of experience with this construct is to blame. I think it's some sort of voice in the back of my head that doesn't like it because it is a bit too much like desktop GUI callbacks. But why should that be a bad thing? It seems to work just fine for those applications. I think I'm thinking about this too much. Add Comment # 2007.11.30 MySQL Row Level Security Tonight I am doing a bit of work on the EPFarms User Panel and Effin, our financial database. The Panel is a Continuity application running under FastCGI and suexec. The security model is different from most other web applications I've done, we use suexec to run the application as the individual Eggplant Farms user. Philosophically, running the panel as the user is an extension of our overall security model, which is to build as directly upon the unix security model as we can. The interesting aspect of this is that, since the panel is running without any special privileges, the user could modify or replace the panel and still have all the same security access. They also have all the same access from the command line. Sharing dynamic data with the user, such as their current account balance, is a bit tricky. We also need the ability for the user to modify some of their own metadata. Our current plan is to create command line tools that allow them user-specific access to our data, which is stored in MySQL. Another way, the one that I'm going to switch to after tonight's research, is to utilize some new features of MySQL 5. We'll use views to emulate row-level security, and MySQL's own column-level security to allow them to directly read, and as appropriate write, to our database. Though it's always handy to have a command line interface, the extra intermediary was a bit cumbersome. Here's how to do it. Lets say we have a single userinfo table, which just holds their username, unix id, full name, and emergency contact info. And heck, let's insert a few rows. create table userinfo ( userinfo_id int primary key auto_increment, unixid int, username varchar(100), fullname varchar(100), contact varchar(100) ); insert into userinfo set unixid = 1001, username = 'awwaiid', fullname = 'Brock', contact = 'a@b.org'; insert into userinfo set unixid = 1001, username = 'aardvarq', fullname = 'David', contact = 'x@y.org';  Now we create a view, limiting to the current logged in user with the USER() function. create view userview_userinfo as select * from userinfo where username = SUBSTRING_INDEX(USER(),'@',1);  Finally we grant some access to user 'awwaiid' (though really we could grant access to '%' if we were so inclined). grant select on userview_userinfo to 'awwaiid' grant update (fullname, contact) on userview_userinfo to 'awwaiid'  Now when I log in as awwaiid I have access to my own rows, and can update my full name and contact info. The panel application logs into the database as the user, accessing and editing their data in a much more direct fashion than the command-line-wrapper method. Comments on TLT - 2007.11.30 - MySQL Row Level Security ### 1 Comment. This is Grrrrreat! - Tony the Tiger -- Anonymous 2008-07-01 15:16 UTC Add Comment # 2007.10.16 Pittsburgh Perl Workshop Review This last weekend was the 2007 Pittsburgh Perl Workshop, where I gave a talk on Continuity. Though it was my first Perl conference, going to other nerd events had prepared me for what it would be like. Even so I thought it was fantastic -- you just gotta love those Perl People! I talked to several people about Continuity, so hopefully I'll be getting some regular users and feedback. I found a bug in the most recent release, and have decided to roll back the installer... so I need to get another release out there. One fun thing is an improvement I made to the Continuity wiki - I got the wiki-to-darcs (both-way) gateway going. I knows specifically about POD rendering , so it looks good as a webpage. See the Continuity::Mapper page as an example. If you edit the page, the cnage actually gets checked into darcs and then I can choose to pull it into my main branch. I still need to create a cron job to keep it up-to-date, but otherwise it seems to work swimingly. So now I don't have to have my documentation in two different places! Add Comment # 2007.10.05 Added Darcs RSS Feeds I've cleaned up and expanded my RSS feeds a bit. So now I have three main feeds: The first is a better URL for the feed of this blog. The second is a feed for the whole wiki (I'm probably the only one who cares about that one). The third... that's the fun one! I took the darcs2rss script from the internets and made some slight modifications. Then I constructed a program that goes through my projects directory and looks for all of the Darcs repositories, generating a feed for each one. As a bonus, it also takes the most recent entries from all the individual projects and creates an ALL feed, which is the third feed above. So subscribe to that feed and you'll be absurdly informed of what I'm up to, code-wise. For the feed of individual projects, look in http://thelackthereof.org/darcs-rss/feed/. On my TODO list is to make the feeds link to an online diff, as that seems like most human-friendly thing to do. Add Comment # 2007.08.24 Random Tips Today while reading some random article I noticed someone doing strace -p 12345  Which is to say, attach strace to the running process numbered 12345. So cool! I've always like strace, but apparently didn't take enough time to read the manger to learn this usage. I'm slowly reading Meta Math! by Gregory Chaitin and am enjoying it very much. Today he proved that there cannot be a purely algorithmic way to prove a given program is as simplified as possible. From that a simple proof of the halting problem will follow, I believe. His writing is very enthusiastic and inspiring, drawing attention to some of the most fascinating parts of mathematics. Plus he loves to use exclamation marks! The tone reminds me of Feynman. So here's the tip: don't try to find an algorithm to provably simplify any given program to it's most minimal form, because it won't work out very well. Stick with a heuristic approach. A few days ago our apartment building's fire alarm went off before work. I decided that it might be a good exercise to take the kitties with us, even though the odds of it being a real fire rather than a false alarm were extremely low. After managing to shove Mia into the carrier we decided there was no way they'd both go in there. So I grabbed Miko and put her harness on and proceeded to carry her out into the hallway. The blaring alarm in the hall wasn't the sort of thing that Miko wanted to be involved with, so when I stepped out with her in my arms I quickly learned how little control I actually had over her. It was like an invisible wall in my doorway that she refused to go beyond, and in this case it meant she had to go through me to get back inside. The scratches on my arm and neck are actually almost gone now, but the tip stands: if you are going to rescue a cat from a pretend fire, do your best to find a box to shove her in and try very hard to avoid carrying her out in a more direct fashion! Your .vimrc file can have conditional sections based on environment variables, such as HOSTNAME. With that in mind I've been able to create a unified .vimrc to use both at home and work. The only real difference is that at home I generally avoid all tabs, whereas at work tabs are the standard for indenting. " Working at LSI ... they like tabs if (HOSTNAME == "wickedwitch") set sw=2 " Width to shift and indent things set ts=2 " Set tabsize to 2 (to view other people's crap) set noet " Use tabs. Even though tabs are the devil. match errorMsg /[^\t]\zs\t\+/ endif  When doing the T9word mode on cellphones the '1' key will do punctuation. Plus they often have smilies in their dictionary! And finally a tip inspired by a recent Paul Graham essay. When reading code you don't see all the pieces that were left out. Therefore, without knowledge of this non-present code, you will understand code you read less than code you write. This applies to creative mediums well beyond code. Add Comment # 2007.08.08 Hey... I Just Heard About That The other day Liz showed me a new book that she got, Drawing on the Right Side of the Brain. Pretty interesting book discussing how to take what you see in the world and put it down on paper. Then today O'Reilly sent me a link to their new website based off of their new book, Beautiful Code. I've looked at this book at Border's and want it... it seems really cool. Well on their website they have articles about code, and one called Design Sense by Michael Feathers mentions the drawing book that Liz has. This follows a general observation I've seen: when you are first exposed to an idea or fact, the odds of you recognising it around you significantly (exponentially?) increase. I learn about this book and I pick it's title out of the article. You learn a new word and then see it a dozen times in two days. I figure it's either of two things. First, the thing is suddenly popular. Maybe Liz saw her book on TV and the author saw it too, which made him think of it. The second way is pattern matching. Once you've noticed the new word, picking it out becomes natural. Add Comment # 2007.07.15 Chomping and Editing Just posted the sketch for two new Projects. The first is Chompie, which I've actually got a proof-of-concept going for. It chops up your program until it is as small as it'll go while still passing (or failing!) some test. The idea is to help debugging, for example -- it could spit out the exact code that fails some test in a specific way. The second is the one I'm more excited about as far as an actual impact on my life -- Oddmuse Editfile is a simple oddmuse plugin which will let me, among other things, put some of my source code directly into wikiland. Changes from the wiki will be checked into darcs for review. It is documentation-centric, so that I can put things into POD and they'll show up nice and neat on my wikis. This weekend is the ICFP Contest 2007! Jason Woys and I will be doing it, with some others maybe dropping in. They've got a pretty good teaser going on in the blog linked to from http://www.icfpcontest.org/... looks like it's going to be super fun :) I even took the day off Friday. Add Comment # 2007.06.20 In The District One day a week and a half ago Beth and I up and moved! Well... I suppose it took a little more planning than just that, but that's what it feels like. We are now living out our dreams in Washington, DC. I've started a new job over at liquidation.com which is pretty cool so far. An all Perl shop, which is what I was going for. Unfortunately the timing of the move has caused me to miss YAPC::NA Yet Again :(. Lets see... our kitties are doing well. In fact, Mia seems to be happier here. Perhaps the very long trip convinced her that life is worth living! Though I don't think they liked traveling they did it quite well -- meowed a bit and then slept all day while we drove. Pictures coming soon. Comments on TLT - 2007.06.20 - In The District ### 1 Comment. Congrats on your new job. Are you still going to be able to maintain epfarms.org. -- fb 2007-07-01 09:45 UTC Add Comment # 2007.04.11 Note to Self... er... Google Calendar A few years ago, while doing some contract work, I created a simple yet effective way to monitor my time. The idea was taken from some other command line junkie, but I simpliefied it a bit. I dropped a command called "L" into my ~/bin directory that looks like this: #!/bin/sh if [ -n "*" ] then echo "date '+%Y%m%d%H%M%S' *" >> ~/tlt/private/log/LOG-HOSTNAME else (for i in ~/tlt/private/log/LOG-* ; do tail -20 i ; done) | sort | tail -20 | perl -pe 's/^(....)(..)(..)(..)(..)(..)/1.2.3 4:5/' fi  Well... in truth this is what it evolved into. The command has two modes, logging and tailing. In logging mode, it takes the rest of the line, adds a timestamp, and shoves it in a logfile. In the tail mode it shows you the tail of all available log files (they are created on a per-host basis), sorted and formatted for human consumption. This creates a quite grep-able log of the things I do. Typical usage: L just got into work L the server went down again L dont forget to go to the store tonight  Speaking of not forgetting things, I'm trying to use Google Calendar in conjunction with Beth (using a shared calendar) to keep track of our schedule. It has a pretty good UI, and Beth uses gmail all the time anyway. I created a separate calendar to take some random notes. You can see where this is going... can't you? Looking at Net::Google::Calendar, the whole thing is quite easy. First I converted the 'L' script to perl (or, partially converted it). Then I added just a bit more to get: #!/usr/bin/perl use strict; use Net::Google::Calendar; use Net::Google::Calendar::Entry; my host = hostname; chop host; if(@ARGV) { my text = "@ARGV"; # First we add it to the local LOG file my ts = date '+%Y%m%d%H%M%S'; chop ts; echo "ts text" >> ~/tlt/private/log/LOG-host; # Now lets add it to the google calendar my username = 'awwaiid@gmail.com'; my password = 'awwaiidxxx'; my cal = Net::Google::Calendar->new; unless(cal->login(username, password)) { print "Error: @\n"; die; } # Gotta select the 'Notes' calendar for (cal->get_calendars) { cal->set_calendar(_) if (_->title eq 'Notes'); } # Set up the entry my entry = Net::Google::Calendar::Entry->new(); entry->title(text); entry->location(host); entry->transparency('transparent'); entry->when(DateTime->now, DateTime->now() + DateTime::Duration->new( minutes => 1 ) ); # And finally, add it cal->add_entry(entry); } else { print (for i in ~/tlt/private/log/LOG-* ; do tail -20 \i ; done) | sort | tail -20 | perl -pe 's/^(....)(..)(..)(..)(..)(..)/\1.\2.\3 \4:\5/'; }  ... and now I can use my good old 'L' command from any random terminal, and if it is properly connected to the internet then it'll post up my note. Of course that brings up the point that I might not have internet available (like on my laptop or something)... but I'll leave other forms of syncing as an excercise for the reader. Comments on TLT - 2007.04.11 - Note to Self... er... Google Calendar ### 4 Comments. This is a really cool concept Brock! -- AJ 2007-04-12 18:22 UTC Nice captcha.  use POSIX 'strftime'; strftime("%Y%m%d%H%M%S"); -- theorbtwo 2007-04-23 23:06 UTC Thanks (for both the compliment and the code). I guess that's what happens when things start out as a one line shell script and turn into something slightly bigger... -- awwaiid 2007-04-24 05:13 UTC BTW, that works better as strftime("%Y%m%d%H%M%S",localtime) (it demands the time argument). -- awwaiid 2007-09-07 15:20 UTC Add Comment # 2007.03.18 Cheap Camera and Kitties While at Walgreens I spotted a super cheap USB digital camera (I was supposed to be buying something else) and I couldn't resist... so I am now the proud owner of a 16mb camera! It is one of those keychain things, though I'm probably going to remove the keychain mount. I haven't mentioned them before, but Beth and I now have two cats, Mia and Miko. Mia is 2 years old, and Miko is 7-months (pictured here pertched in the window). Both are interesting kitties, pretty vocal and active. We got Mia at Christmas to keep the bunny entertained, but when the bunny died (and after we got over the initial sadness) we bought Miko to keep Mia company. You can tell that we're new cat owners... because we thought they'd be instant pals. Dropping the box filled with Miko in the middle of the room and opening the lid resulted in instant hissing and running rather than instant friendship... but after a week or two they tolerated each other and after a month they now play and groom together. When I'm programming (I work from home a day or two each week) the cats love to hang out with me in the labratory. Mia will sometimes get in my lap, but mostly sleeps on Beth's desk. Miko, on the other hand, gets on my lap or on the back of my chair and then uses my arms as balancing beams to get to what she must imagine is super fun -- the keyboard. She only seems to like it because I am touching it and, more importantly, because that is where my hands are and therefore where she can be to be petted. Miko is not a very good programmer. Vim, my editor of choice, happens to bind just about every single key on the keyboard to some devestating editor feature -- dGwq and half my program is gone :) I've always thought that these entries needed more photos. So maybe I'll be able to get a few using this camera. I can take 20 at a time like the above -- high resolution mode! Someday I'll actually go buy a real camera instead of borrowing other people's all the time... they're getting so cheap now for a good quality. Comments on TLT - 2007.03.18 - Cheap Camera and Kitties ### 1 Comment. Sweet! That's the same camera I had (10 little grey thing that takes 1 AAA battery). I had a lto of fun with it before I lost it. It'll take short movies, and I've posted a number of mine on http://slowass.net/~scott/ and in the photos directory, which I can't remember where I left as everything here is sorta in limbo. Congrats, and yes, more photos! Oh, and I think it has 16megabits of RAM, or 2 megabytes. Those EE types are trixie. They used to do that video game carts. -scott -- scrottie 2007-04-03 20:52 UTC Add Comment # 2007.01.17 AD Auth on Oracle Portal Using Password Filters We're becoming quite the Oracle shop at work. The accounting package we recently purchased actually encompasses a lot more than just ledgers -- it helps us track things such as individual projects. And it comes with all sorts of Oracle goodies, including Oracle Portal. One thing that I'm working toward is a single username and password for everything. Programs will all ultimately depend on the Active Directory authentication for this, and most things already do (such as our [[DJabberd_AD_Authen?]] setup). The Oracle Portal is one spot where this will be very useful... but after trying to integrate AD with Oracle's LDAP directly and failing (turns out there are some required pieces which our Oracle install lacks), I decided on a different route. In comes the idea of using Microsoft's Password Filters. MS introduced a customizeable hook into their password-change chain so that more or less strict passwords can be enforced. So the "trick" is to insert an item into this filter chain which doesn't filter, but instead takes the new password and goes off changing the user's password in other systems. A back-door on purpose! After thrashing around with my own C version of some C++ examples of doing this (mostly I had trouble with the unicode->ANSI conversion... so spoiled by Perl...), I finally remembered PasswdHK, a generic hook that just calls an external program. Perfect! Tie that up with a little perl, wrapped and ready to distribute with PAR (which I had to modify a bit. I need to wrap up my mod and send it upstream...). Like magic, when users are set up or change their password they get all their Oracle Portal goodness. Add Comment # 2007.01.14 Son Of Suckerfish and IE I've been working on the release of the new website for my work at SWCA Environmental Consultants, which has been a long time in the making. During the development of the site they wanted drop-downs for navigation (against my clearly stated opinion :) ), and I selected Son of Suckerfish for the technique. Son of Suckerfish (or a near variant) is the nicest drop-down setup I've seen so far. It works with pure CSS on Firefox and other stardards compliant-ish browsers. One of the things it depends on is come css on the :hover attribute of a LI tag, which IE doesn't support. So there is a very small amount of Javascript for this case. Generally a very clean and simple solution for HTML dropdowns. Implementing it worked out perfectly, and I tested it out in all the major browsers without issue. A few months go by and, I admit, testing on IE6 fell by the wayside a bit... at some point it stopped working very well for that platform. The drop-downs were going away much to soon... as if the onMouseOut code was being executed too fast (in-between menu items). sfHover = function() { var sfEls = document.getElementById("nav").getElementsByTagName("LI"); for (var i=0; i<sfEls.length; i++) { sfEls[i].onmouseover=function() { this.className+=" sfhover"; } sfEls[i].onmouseout=function() { // **** WAS THIS **** // this.className=this.className.replace(new RegExp(" sfhover\\b"), ""); // **** Changed to this setTimeout setup **** var t = this; setTimeout(function() { t.className=t.className.replace(new RegExp(" sfhover\\b"), ""); }, 10); } } } if (window.attachEvent) window.attachEvent("onload", sfHover)  Which has worked well so far... though I wouldn't be surprised if I could find a better way. I don't like the way I assigned 't = this', seems like there should be a better way to do that. Plus, I wouldn't be surprised if it is a very minor memory leak. The timeout gives the mouse a chance to roll onto the next menu item, which adds yet another 'sfhover' class to the li tag. When the timeout is triggered, it only removes one. The whole thing flickers in my current ies4linux setup, but looks fine in vmware. On another note, I discovered that ies4linux has alpha IE7 support! Just install one of these betas (I'm using 2.5-beta4) with '--beta-install-ie7'. Comments on TLT - 2007.01.14 - Son Of Suckerfish and IE ### 2 Comments. Brilliant. I had the exact same problem and this fixed it. Thanks for posting this! -- Dan 2007-06-19 17:38 UTC You're welcome! -- awwaiid 2007-06-19 20:42 UTC Add Comment # 2006.11.25 Detecting Reload and Back Browser Actions Detecting when a user uses their Reload or Back buttons in a web application isn't very difficult, and the payoff in useability can be quite large. One of the most-heard complaints about web applications is back-button brokenness. ## Disable Caching This first step towards detecting a press of the back-button is to disable client side caching. When a browser caches the page, the back-button will merely display the cached version and the server is never notified. When the user then uses the cached page, the application and the user can become confused about what data is being manipulated. While adding meta tags to HTML is helpful, the best way to stop caching is right in the HTTP headers. I like to add:  Cache-Control: private, no-store, no-cache Pragma: no-cache Expires: 0 which gets the job done. I've also seen the Expires: header set to some date in the distant past, which also works. ## Assign PageID To Each Output Once you have caching disabled, you should next assign a unique Page Identifier (PageID) to each page the application outputs. I generally try to make this as short as possible, and generally use Hexidecimal or Base-64 to fit the ID in less characters. Also attach this PageID to each input back into the program. Add it as a GET parameter on each link, and as a hidden input for each form. It is ugly but necessary. This will allow us to know which page generated which program input -- in other words, which page the user was looking at when they send a given request. Each PageID should be added to the session information so that we can track what pages have already been displayed. ## Use PageID to Detect Reload / Back With the PageID mechanism in place you have enough information to detect browser Reload and Back Button actions. Now, with every input sent by the user to the application, the PageID will indicate whether the user is requesting a page they've already seen. If the recieved PageID is the one we just sent out, then the user pressed Reload. If the recieved PageID was generated before the most recent one, then the user pressed the Back button (or otherwise returned to an old page). ## Avoiding The Re-Post Prompt One thing that I've annoyingly run into is the result of a user pressing the Back button after submitting a form via POST. Most browsers, following the standards and being ever so helpful, prompt to ask whether the data should be re-POSTed. This is because, well, generally it is a bad idea to re-POST data. We, however, don't mind so much since it can be detected. After a bit of research, it seems the best method to overcome this prompt is by doing a redirect right after the POST using the 303 HTTP Status. The 303 Status means "See Other" and does just what we want -- it redirects the user transparently without prompting them or caching the redirect. This status code was created for just this purpose as part of HTTP 1.1 -- if you are working with a pre-1.1 browser you may want to send Status 302 instead. ## The Downside Having a PageID as part of the GET or URL in each request is ugly. Worse (or perhaps as an elaboration on the truth behind the first statement), it is a meaningless number for users and can only cause them pain. When the user bookmarks or copy/pastes the URL the PageID goes along too, forever attached. This is very anti-REST, but of course this whole thing technique is pretty anti-REST :) Make sure your application does the Right Thing for requests with unrecognised PageIDs, and expires the PageIDs (removes them from the list of used PageIDs) quickly. Add Comment # 2006.11.19 Oddmuse Module Tinkering While looking at the Chicago Hackation wiki I noticed that they had this lovely sidebar which listed the incoming-links for a page. That seemd pretty cool, so I created the Oddmuse Ref Links module which does just that in the Oddmuse sidebar. Seems nice for visitors (or even myself) to get a more structured view of the pages, or at least the immediate neighborhood of pages. That worked well on my wiki pages, but didn't do much for my blog-like pages (such as this one). So I stopped putting it off and implemented an Oddmuse Search Tags module. Now I include a line of tags on any page, and each tag is turned into a link that searches for other pages with the same tag. Very straightforward and minimal implementation of tagging, I say. Just a few more features and it might be hard to tell that this isn't Just Another Blog! Add Comment # 2006.10.21 Tempe Alien Landing Base Construction The City of Tempe seems to do a good job of keeping the town a thriving place, full of interesting events and sites. They have an advantage with the main ASU campus bringing lots of active youth -- but they like to push the envelope by doing things like daming the dried salt river and re-filling it to make their very own Teme Town Lake. Right off the lake they've been building (or at least, they must have signed the permit) a very large and pointy building: ... which I can only imagine is a giant alien transit facility. The City, after consulting with a panel of futurist experts, declaired "We, for one, welcome our alien overlord tourists." At leat that's what I thought. Beth thought it was some sort of giant slaughter-house. Perhaps, I reply, to slaughter the alien invaders! Alas, I finally get around to looking it up, and it seems to be nothing more than the new Tempe Center for the Arts. Art gallery, meeting area, and the main event -- a giant theatre. Because even giant alien overlords need art! Comments on TLT - 2006.10.21 - Tempe Alien Landing Base Construction ### 3 Comments. You so completely fail. You know the subject of this post is actually "People of Earth!". -- mouset 2006-10-21 23:05 UTC Excellent timing, my friend. I just saw that today and wondered what it was. I was so distracted when I got over the bridge on Mill and to a red light, that I started to make a right-on-red turn and had gone one foot when the light turned green and all of the pedestrians darted out into the intersection. I slammed on my brakes immediately, but everyone honked or yelled at me, and probably didn't realize that I had started going before they did. The center for the arts is a really unusual sight. I, like you, am surprised I hadn't heard of it or seen drawings of it beforehand. I also notice a couple of giant cranes I didn't see earlier about halfway between University and Rio Salado. Downtown Tempe sure is growing quickly. -- Ben 2006-10-22 00:33 UTC You're right mandies! I fail, fail, fail... *sob* Thanks Ben! It freaks me out all the time too. I had put off looking it up for too long. -- awwaiid 2006-10-22 15:57 UTC Add Comment # 2006.10.19 AJAX Long-Pull (almost HTTP Push) I've been doing some fun things with Continuity in conjunction with scott to prepare for Desert Code Camp. The latest is combining XmlHttpRequest with Continuity in a new way, simulating HTTP Push. It's really easy, actually. I put together a chat application which you can see in the Continuity Examples Directory. When you first go to the page, it immediately sends a background GET request back to the server, which actually opens a second session. That session then blocks, waiting for a variable to change to indicate that there are new messages. So I have this code which watches for new chat messages: sub pushstream { my (req) = @_; while(1) { print STDERR "**** Waiting for message ****\n"; my w = Coro::Event->var(var => \got_message, poll => 'w'); w->next->cancel; # Block, waiting for an update print STDERR "**** GOT MESSAGE, SENDING ****\n"; my log = join "<br>", @messages; req->print(log); req->next; # Once the client is ready, they'll ask for more } }  Then, when the mainloop gets a new message, it just sets got_message = 1 and all the watchers are triggered, giving all the clients the new message. For fun, I opened up four webbrowsers (FF, IE6, Opera, and Konqueror) and recorded a chat between all four -- Four Browser AJAX Long-Pull (fake Push) Demo. This is not really very robust -- but it should only take a few properly placed timeouts to fix that. I hear proxies can wreak havoc on this method too, so keep that in mind. Add Comment # 2006.08.28 Multi-Column Table Keys A little over a year ago I re-wrote the db-oop layer of my work project. The previous system was a bit much for me, and my replacement simplified things significantly (though surely at a run-time cost, but not noticeable to users). Unfortunately I was designing pretty much all of the tables that the application used. I say unfortunately because it means that all of the tables were arranged in a way that I might generally arrange things -- each table had a single column primary key. Well now we're moving to a new database system with which the app must interface. Besides gutting most of my app, it means that I now get to deal with tables which have two or more columns used to determinte a unique row. Such a simple assumtion as a single-column primary key permiates the implementation much more deeply than I had originally guessed! I've got it working pretty well now, but at first it felt a bit overwhelming to have to tear apart this code on which everything depends and which hasn't needed to be touched for so long. Add Comment # 2006.08.22 Continuity ASCII Art Drawing up some ASCII art diagrams of the internal Continuity control flow, these are my two best variations so far. First is a bit too tall:  +---------+ +---------+ +--------+ | Browser | <--> | Adaptor | ---> | Mapper | +---------+ +---------+ +--------+ ^ | | | +--------------------+ | | | | +-------------+-------------+ | | | | | V V V | +---------+ +---------+ +---------+ | | Session | | Session | | Session | | | Request | | Request | | Request | | | Queue | | Queue | | Queue | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | V | | V | | V | | | | | | | | | +---------+ +---------+ +---------+ | | | | | V V V | +---------+ +---------+ +---------+ | | Current | | Current | | Current | | | Request | | Request | | Request | | +---------+ +---------+ +---------+ | | | | | V V V | +------+ +------+ +------+ | | Your | | Your | | Your | | | Code | | Code | | Code | | +------+ +------+ +------+ | | | | | V V V +--------+-------------+-------------+  Too tall because it doesn't quite fit on a 24/25 line high terminal. Here is my revised version, which not only fits but is also more accurate in the relationship to the "Your Code" nodes.  +---------+ +---------+ +--------+ | Browser | <--> | Adaptor | --> | Mapper | +---------+ +---------+ +--------+ ^ | | | +---------------------+ | | +-------------------+---------+----------+ | | | | | V V V | +---------+ +---------+ +---------+ | | Session | | Session | | Session | | | Request | | Request | | Request | | | Queue | | Queue | | Queue | | | | | | | | | | | | | V | | V | | V | | +---------+ +---------+ +---------+ | | | | | V V V | +-----+ +------+ +-----+ +------+ +-----+ +------+ | | Cur |<->| Your | | Cur |<->| Your | | Cur |<->| Your | | | Req | | Code | | Req | | Code | | Req | | Code | | +-----+ +------+ +-----+ +------+ +-----+ +------+ | | | | | V V V +-----+--------------------+--------------------+ ("Cur Req" == "Current Request") Add Comment # 2006.07.30 Cygwin Rocks Oh how I love you Cygwin... let me count the ways. Doing various system and programming contortions using the GUI is numbifying, and moreso when I am trying to work far away from the machine to-be-manipulated. Usually it ends up along the V lines -- VPN, VNC, and maybe some Vort Vorwarding. I found myself in that situation this weekend, but had a bit of foresight on Friday and averted the pain quite a bit. A couple things make Cygwin fantastic. First and foremost is getting all my tools back. I can cat and tail and vim and bash to my hearts content. Throw in a little Perl and I'm a happy duck. Working with Oracle currently, so I even get to use sqlplus command-line goodness and pipe it SQL and all sorts of mean and nasty things. Great for when you are still on the machine. But the coolest, most fabulous, most wonderousiful thing of all... sshd, running as a windows service. Here I am sitting at home, SSH-ed in to my Evil Windows Server. I get a bash prompt and go to town, practically forgetting that I'm on a Windows machine at all. Comments on TLT - 2006.07.30 - Cygwin Rocks ### 1 Comment. If you like cygwin, you'll love poderosa. Check it out. -- q 2007-06-11 21:16 UTC Add Comment # 2006.07.19 Vegetable Thin Lament (as sent to the Nabisco World Website) Dear Vegetable Thins Creators, While I very much enjoy your crackers, I do have one thought on the matter. With each box I purchase I await the initial opening with a bit of anxiety. You see, each box is different in its degree of crunchyness. The good boxes, the boxes I am overjoyed to open, contain dark crisp satisfying crackers. The ones that I am not so thrilled about... perhaps not cooked quite so long they contain lightly colored and slightly greasey crackers which seem to get stale faster (perhaps because I don't eat them quickly enough!). I am often tempted to throw them in the oven to finish their cooking process! So, if there is any choice in the matter, as a customer I implore you to tend towards the dark side! Beth thinks they are more likely to respond if I send it to them via snail-mail, but we'll soon find out. Add Comment # 2006.07.06 Mairix Mail Search After needing to find some old email and getting tired of waiting for grepmail to complete its search, I went out and found a mail indexor. The one I settled on is called Mairix, and so far so good. Here is my setup. First, I have the configuration file for Mairix. My mail is in ~/mail/YYYY/MM/mboxfile (where mboxfile has a name based on what mailing list or whatnot it contains). So my .mairixrc looks like: base=/home/awwaiid/mail mbox=20*... mfolder=search database=/home/awwaiid/.mairix_database  ... which is to say, index all of my mail, and when I do a search put the results into the '/home/awwaiid/mail/search' folder. Oh, and store your DB in .mairix_database. Next, I wrote a script called search-mail, which I'll use as a wrapper to be more mutt friendly. Also it will allow me to switch which mail indexor I use if the need arises. Plus I will probably add features and shortcuts here. Here is search-mail so far: #!/usr/bin/perl use strict; print "Enter search terms: "; my search = <STDIN>; chomp search; system("/usr/bin/mairix search > /dev/null &");  And yes, I could have done that with a bash script. But what fun is that? Finally, there is the line that I've added to my .muttrc which lets me do searches from mutt. It is: macro index \eM "\ <enter-command>unset wait_key\n\ <shell-escape>/home/awwaiid/bin/search-mail\n\ <change-folder-readonly>=search\n\ <enter-command>set wait_key\n\ " "Super Search for messages"  This command is hooked into <esc>M right now, though I'll surely change that to something much easier. It runs mail-search, which prompts for the search terms and then forks the search. Then I am put into the folder in read-only mode so I don't accidentally delete things (though that might not be necessary or good). Oh yes, and I dropped the simple command "mairix" into my cron to update the index. The thing runs quite fast and is very fun! I should index all my data for quick searching! (Beagle, why must you foresake me?) Add Comment # 2006.06.28 Renew All I just got a late notice from the Phoenix Public Library. Being overdue on my library books, movies, and anything similar is a long family tradition handed down from generation to generation. One of the only things that could keep Mom from taking us to the library is not being able to find enough spare change to pay for the fines. Let us then overcome our nature through the use of technology. The library has an online renewal tool. Therefore... WWW::Mechanize to the rescue! #!/usr/bin/perl -w use strict; use WWW::Mechanize; my card = 'XXX'; # Your real 14-digit card number goes here! my lastname = 'wilcox'; my agent = WWW::Mechanize->new( autocheck => 1 ); agent->get('http://www.phoenixpubliclibrary.org/login.jsp'); agent->form_number(3); agent->current_form->value('libcard', card); agent->current_form->value('lastname', lastname); agent->submit(); agent->submit(); agent->follow(qr((?-xism:Renew\sAll))); print agent->content; agent->follow(qr((?-xism:Exit)));  Stick that in your pipe and smoke it. Or maybe stick it in your cron job. I actually used WWW::Mechanize::Shell to generate this, which I highly recommend. This solution isn't robust at all though... I don't check to make sure that any of my web requests actually worked or that they are going to the correct place. That's left as an excercise for the reader :) Add Comment # 2006.06.27 DJabberd AD Authen On Tuesdays I work from home for SWCA (my current employer). This gives me a chance to do code without being interrupted every 15 minutes by random things. Lately I've been working on the code behind our website re-design, which is pretty interesting. Today, however, I took an hour or two to set up a better Jabber server. Up until now we've been using the more or less "default" jabber server provided by jabber.org. It is horrible to configure... I can generally figure out how to make things work, but couldn't for the life of me get conferencing going. Then bright and early this morning I gave DJabberd another try. A previous half-hearted attempt had failed, but this time it worked wonderfully! I started with SixApart's example server, and then tweaked from there. It authenticates off of our Active Directory, and automatically adds all users who have logged in once to everyone else's buddy list. Now I only need to get the SSL certs working. So I'm now doing Active Directory authentication in a couple places. I've made use of the Authen::Simple::ActiveDirectory module, which is fantastic. Authentication is as easy as: use Authen::Simple::ActiveDirectory; # ... given plaintext user and pass ... my auth = Authen::Simple::ActiveDirectory->new( host => 'phxserver.swcacorp.com', principal => 'swcacorp.com' ); if(auth->authenticate(user,pass)) { cb->accept; } else { cb->reject; }  Perhaps even cooler is that the minimal interface to Authen::Simple makes it simple to swap out other authentication methods. Add Comment # 2006.05.05 DOM Template Fantasy I have this fantasy. You may have heard it before, it's pretty common. One day I'm designing this website for some people. Actually, I'm not designing it, I'm coding it -- I'm doing all the dynamic programming stuff. My partner in crime is a Designer (mainly graphic design, but also HTML, no programming) named Sarah, and she is doing the actual design. Together we talk to the client and she sketches some things that they like and I talk about the newest headlines showing up on their homepage, and so on. Sarah goes off and starts doing her thing and I set up a server and get my tools together and even build up an ugly prototype. Then Sarah brings over her HTML and graphics and such. Here is where the fantasy kicks in. Pay attention. She brings over her stuff and gives it to me. She points at the screen and says "See that? That's where your headlines go". Lets digress a bit. Many people in my position would, at this point, take her HTML file, rename it .php (or similar), rip out the HTML where she pointed and replace it with some inline code. Hopefully they wouldn't put database accesses and such there, but if nothing else they have maybe a loop that prints out each element in an array wrapped in some HTML tags. OK, un-digress. Pay attention again. I look at her HTML and see that the tag she points at is already labeled with an ID, #headlines. I need to grab the headlines from a database, but I already did that and now have them in an array. I close the HTML file she gave me. Back in my code I add this... # ... doc already defined ... # ... @headlines already defined ... rules = [ '#headlines' => sub { my tag = shift; # Turn the headline array into an HTML unordered list @headlines = map { "<li>_</li>" } @headlines; my headlines = "<ul>@headlines</ul>"; tag->replace_content(headlines); }, ]; doc->apply(rules);  ...and attain the desired affect. The headlines are turned into an HTML list and replace the content of the named tag. Later that day the client calls and tells us that they want the headlines on five other pages. Sarah makes the change, and gives me the HTML. I do nothing. Sarah has this cool navigation bar she set up for them... but it is tedious to add it to each page and even more tedious to differentiate each snippet so that the currently-viewed page is highlighted. "No problem", I tell her. "Give me one page with the navigation bar as you like it," I say. A few more twitches of the keyboard and I make all the pages inherit the key piece of HTML. For highlighting the current page, I do something like: my rules = [ '#navbar a' => sub { my (node) = @_; my href = node->attr('href'); href =~ s/^.*?\.com//; # Chop off the http://bleh.com/ part if(real_path =~ /href/) { # If this link is like this path node->add_class('selected'); # We highlight this link } }, ];  Sarah never looks at my code. She doesn't have to see it, doesn't have to dodge it or carefully copy/paste it in her WYSIWYG designer. I don't have to cry over < turned into &lt;. She removes some of the headlines, I do nothing. She adds a link to the navigation menu, I do nothing. It's not much of a fantasy because I've already implemented it. Taking inspiration from behaviour.js, along with the wonders that CPAN provides (namely HTML::TreeBuilder) it is not a very difficult task. Others, in fact, are already using DOM manipulation for templating systems (TAL and its relatives, HTML::Seamstress)... but none quite this way. Comments on TLT - 2006.05.05 - DOM Template Fantasy ### 2 Comments. That's beautiful. -- ab 2006-05-06 05:41 UTC Pretty slick! -- Anonymous 2006-05-06 14:02 UTC Add Comment # 2006.04.18 Sinking Into OCaml Continuations Madness A while back it was announced on the OCaml mailing list that someone had created a userland delimited continuations library for OCaml. I love OCaml, and I love Continuations... so I thought I'd give it a try. Ultimately going for the HTTP re-inversion trick, of course. Little did I know what sort of a rabbit hole I was going down with Delimited Continuations. On the surface it doesn't seem that that big of a deal -- they're a lot like "normal" continuations (using call/cc or whatnot), except better. Instead of secretly being a function invocation that never returns, they are secretly a continuation that does. At least thats what I've told myself. Unfortunately my brain doesn't like the explanations I've come accross so far. It makes perfect sense when I stand back a bit, but once I start trying to pound this keyboard to produce some code nothing seems to make sense. The best introduction I found so far is a composable continuations tutorial on the Community Scheme Wiki. Some heavier readings (such as A Monadic Framework for Delimited Continuations, on which the OCaml library is based) are a bit too fast-paced. Individual sentences are fine... but taken as a whole I'm not getting it. Part of the problem is that when building Continuity (or its predecessor, Contize), I have actually been using coroutines rather than continuations, which simplify the situation a bit. So I haven't had to really deal with scheme's call/cc, let alone the various delimited versions such as shift/reset. If it seems to you that I'm talking jibberish, perhaps you feel my pain. I am making a bit of progress though. With the above tutorial and a few other searches the concepts are slowly starting to sink in. Eventually I will be able to explain it all through lovely diagrams of call-stack manipulations. Basically thats all these texts are missing -- nice simple diagrams. Comments on TLT - 2006.04.18 - Sinking Into OCaml Continuations Madness ### 2 Comments. Hi, I sent you an email about your OGPF project. I just thought I'd leave a comment to notify you here because I've had terrible luck with emailing people about genetic programming issues thus far (you'd be surprised at how terrible researchers are at responding to emails from people who actually bother to carefully read their papers!). Cheers! Warren Henning -- warren 2006-04-30 04:01 UTC I responded to your email but haven't heard back from you :) -- awwaiid 2006-05-02 22:36 UTC Add Comment # 2006.04.05 Thank God For Backups Its a good thing that I do my Unison Backup Setup... because today I need it. I awoke at 5:00AM to the pinging sound my computer makes when I get an email to my INBOX (past spamassasin and not a mailing list). Normally I can't hear the sound, but I must've had my speakers turned up to 11. Did I say "the sound"? Properly, I should say "the ping ping ping Ping PING PING PING" that kept penetrating deep into my head and driving me INSANE. Thats what I meant. Dragging myself out of slumber, I lurched into the computer room and stared at my screen. Some sort of harddrive issue had caused my root partition to be remounted as read-only (generally better than writing more and more data to a broken disk). The sound, aparently, comes before an email is successfully written. It plays the sound, tries to write and failes, then decides to try fetching mail again. Oh joy! So my root drive is screwy. Not sure if it is dead yet, we'll see. For about 15 dreadful minutes I thought maybe I had actually lost my secondary drive, which holds all of my media-data and isn't backed up (because its a bit harder to back up 200 gigs than it is to back up 2 gigs). No problems though. The fsck on my root drive eliminated random libraries.... I was able to boot all the way into X, which quite surprised me, but after that random things didn't work. Add Comment # 2006.03.17 Unison Backup Setup I use Unison to keep my important files synchronized between machines. This is a description of how I have it arranged and to some degree automated. I put all my important files into a directory called 'tlt'. This happens to exactly correspond with the root http directory of my website. Most things in the directory are fine to be on the web, but things that shouldn't be published are locked through file permissions and .htaccess files. I put this 'tlt' directory into my home directory: • /home/awwaiid/ • tlt/ - my main directory, and the root of my website • private/ - holds private files • mail/ - holds my mail • dotfiles/ - holds my homedir .config files • projects/ - all my own code projects • docs/ - Various documents I then symlink a few key directories and files from my home directory into this folder. So, for example: • /home/awwaiid/mail -> /home/awwaiid/tlt/private/mail • /home/awwaiid/.muttrc -> /home/awwaiid/tlt/private/dotfiles/.muttrc • /home/awwaiid/projects/ -> /home/awwaiid/tlt/projects/ And so on. So to get all my settings from one machine to another, I just need to get a copy of this 'tlt' directory and make a few key symlinks. To backup all my stuff I must back up this tlt directory. This is where unison comes in. Unison is kinda like rsync, except smarter. It keeps a database on each machine so that it can remember what the directories looked like during the most recent synchronization. So if you delete a file on one machine it knows, and if you delete it on one machine and modify it on another it can tell that there is a conflict which you must resolve by hand. After you've synchronized two hosts, resolving all conflicts, you have an identical set of files on each host. We use the notation host1->host2 meaning a synchronization between host1 and host2 initiated from host1. I have three machines on which I want an up-to-date copy of 'tlt'. They are my own computer (Feline), my website host (Mirabel), and my laptop (Jill). Generally I will sync Feline->Mirabel and Jill->Mirabel, but I could do other combinations (and often do Jill->Feline). Lets say I am using Feline and want to sync with Mirabel. If you simply run 'unison' it will interactively prompt you for the local and remote directory you wish to synchronize, and step you through the initial sync. It'll remember too, and when you re-run it will sync what it can and ask you about conflicts. Try it a couple times, its fun. It stores its settings in preference files inside of ~/.unison/. Here is the preference file I use for Feline->Mirabel. # Unison preferences file # Located at feline:/home/awwaiid/.unison/mirabel.prf # It knows how to sync feline->mirabel root = /home/awwaiid/tlt/ root = ssh://awwaiid@epfarms.net//home/awwaiid/tlt ignore = Path dev ignore = Path tmp rshargs = -C  OK, here's another tip -- most of the time there aren't any conflicts. So there is a flag for unison which lets it run in batch mode. Guess what it is? awwaiid@feline:~ unison -batch mirabel  This runs unison, from feline to mirabel, syncing my 'tlt' directory on each and skipping any conflicts and giving a report. This is exactly what we need for cron! Here is my entry in my own crontab on feline, along with some stuff to send me shorter email reports: 10 3 * * * unison -batch -terse -contactquietly mirabel 2>&1  Every now and then I will run unison without the -batch flag to resolve any outstanding conflicts. A conflict might happen if I edit a file on my laptop (jill) and on my desktop (feline) without bothering to synchronize inbetween. Resolution mode will let me see a diff and select which one I want to keep (or run a merge tool or or abort the sync or whatever I like). I tend to sync Jill by hand. Actually I have two other machines which automatically get synced, but that is just more of the same. (An up-to-date version of this will be kept at Unison Backup Setup.) Add Comment # 2006.03.05 Turing Award Innovation Lag A few days ago I noticed that Peter Nuar was given the 2005 Turing Award. I thought to myself "self, doesn't that name sound familiar?" "I believe it does," I replied. That is Peter Naur of Backus-Naur Form. That, in conjunction with his greater work on Agol 60, is why he got the award. Backus got his award in 1977, for inventing FORTRAN (which is, shall we say, significant). But why the lag between the work and the award? It's not like we just now noticed that BNF and Algol have been a huge contribution to software technology. Looking at the list I saw some others... Alan Kay wasn't recognised until 2003 for his early 1970's work; the RSA guys were recognised in 2002 for work from 1977. Maybe its not a big deal -- it could be that it just takes a while to recognise the work. The early awards were given for more recent works because there weren't any older works. Maybe the Turing Award itself is lagging in quality or direction. But what if our rate of innovation has slowed? A rough look suggests that towards the beginning of the award it took up to 20 years between contribution and recognition. The more recent awards took more like 30 years. Such a small data set to be sure, but it does make me ponder. Add Comment # 2006.03.03 Funky Function Filters Guido van Rossum Re-Posted a plea for advertisement of Python. Some of the Python folks are feeling the Ruby squeeze and feel like their leader might be able to make some noise. Anyway, in the course of the conversation Guido asked what the Ruby equivalent for this would be: for f in filter(lambda f: f(-1)>=f(1), [lambda x:x, lambda x:x**2, lambda x:x**3]): for x in range(-10, 11): print x, f(x)  Which is, of course, a completely useless piece of code demonstrating some lambda functionality. Someone posted the response: for f in [lambda { |x| x }, lambda { |x| x**2 }, lambda { |x| x**3 } ].select { |f| f.call(-1) >= f.call(1) } for x in -10..10 print x, f.call(x) end end  Which is quite similar. I thought I'd give it my hand for Perl5, which looks like this: for f (grep {_->(-1)>=_->(1)} ( (sub{shift},sub{(shift)**2},sub{(shift)**3}) { for x (-10,10) { print x," ",f->(x),"\n"; } }  Pretty ugly, if I do say so myself. The uglyness comes directly from the lack of a simple named parameter mechanism. The Python and Ruby versions look, like I said, very similar. All three are identical in algorithm... but for once it looks like Perl doesn't do so well on terseness. Now I have to figure out what this looks like in Perl6... Comments on TLT - 2006.03.03 - Funky Function Filters ### 4 Comments. Perl6 will have a "prove guido wrong" operator. -- mid 2006-03-04 01:00 UTC haha. I wonder what unicode character it will be... maybe a circle-bar (anti-) symbol. Or maybe ☠. -- awwaiid 2006-03-04 04:21 UTC Try embedding a Scheme/Lisp interpreter. This will allow one to try extensions while keeping the core language simple. Neat Wiki, BTW Cheers, Bob -- bobmc.net 2006-03-05 00:03 UTC Thanks for the wiki compliment, Bob! Maybe I should just try programming everything in LISP/scheme in the first place :) -- awwaiid 2006-03-05 21:13 UTC Add Comment # 2006.02.25 Bad Brock I'm sorry Livejournal People! I accidentally flooded your friends lists (all 4 of you) because I changed the naming scheme for the feed. I was afraid this might happen... stupid interweb. I'm sorry! Comments on TLT - 2006.02.25 - Bad Brock ### 3 Comments. I just want to make sure that my comments are still working... -- awwaiid 2006-03-01 02:37 UTC And you did it again! :p Game for tonight or tomorrow? I'll give a call after my class. -- mandies 2006-06-22 17:13 UTC Actuall this was stupid LJ's fault... or perhaps mine for not updating quickly enough. They eventually purged their records and then refreshed them, I'm guessing. -- awwaiid 2006-06-23 00:18 UTC Add Comment # 2006.02.24 Blogified I've Blogified my site! Probably needs some tuning yet, but now when you go the the front-page you get a very blog-oriented view of things. My rough plan is to do what adam mentioned in an offhanded remark -- turn some things which I might ordinarily put into wiki pages into blog entries, and do some editing. So I'll probably be doing some fine-tuning. Speaking of which, I've done some slight touch-ups on the Phoenix.PM website. Looks quite a bit better already, and I'll add some more things soon. I haven't heard back from Ticketmaster about doing a presentation for us; I contacted them on Tuesday and expected to hear back by Wednesday, but no such luck. Monday I go to SLC for work, listening in on a meeting full of important people. Specifically monitoring the conversation to learn about secret web site and web application requirements that nobody knows to tell me about. Comments on TLT - 2006.02.24 - Blogified ### 4 Comments. Excellent timing! I finally started using an RSS reader. For now it's Safari. I tried Google Reader but there is no option to change the default which opens things in new windows. I suppose I could get a Firefox extension that just puts pop up windows in the same window, or even write some GreaseMonkey code to get it to work. But for now it's Safari. The only thing I really use Safari is for the RSS reader (I use Firefox for general web surfing). I still think there's got to be a better way out there for keeping track of news. -- Ben 2006-02-25 05:46 UTC You're teh dork. :) -- mousetrout 2006-02-25 06:05 UTC I know I'm a dork... I just can't help myself! Just wait till you come back to my page someday and see that I now have a gradient background in my header! Ben, I haven't found much of a good rss reader either. Lately I've been using email2rss to keep track of changes on my wiki's (which all have RSS feeds)... but this is only effective because there aren't all that many changes. -- awwaiid 2006-02-25 07:10 UTC Oh... and you'll REALLY know I'm a dork when someday you use Firefox 1.5 and see that I have two-column css turned on for journal entries! I'm not even sure I like it... its so strange... -- awwaiid 2006-02-25 07:14 UTC Add Comment # TLT - 2006.02.11 Hanging out in San Francico with Adam. Specifically I'm here attending CodeCon, which has been very enjoyable. It hasn't quite gotten me to suddenly produce tons of amazing code, but it has definately been generally inspiring. And theres one more day! Add Comment # TLT - 2006.01.26 I wrote my first useful stand-alone javascript thingie! I've always wanted a combo drop-down in HTML... and for one project I'm currently working on it was especially appropriate. Yet again I set out accross the web to look for the perfect fit, but didn't find what I wanted. But I've been doing this whole Javascript thing quite a bit lately, so I thought I'd give it a whirl. Using behaviour.js to attach events cleanly, I whipped up my very own DHTML Combo. Then I realized that it didn't work quite right. Simple problem really. My combo is literally a textbox and a listbox. The listbox is normally hidden, but when the textbox gets focus I display the listbox. Then if you mess with the listbox it gets focus. Problem: when the list gets focus, the textbox loses focus first. Normally when the textbox loses focus I want to hide the list again. But not if they are actually trying to maniplate the list! No problem though, I did a quick little setTimeout timer to reverse the events. Now when the textbox loses focus it waits a bit and then checks to see if the list is the thing that got the focus. If not it hides the list. Seems to work pretty well. Using ies4linux to test (wine+ie all downloaded magically and working rocks) it even works in IE! Maybe I should put it on JSAN. Add Comment # TLT - 2006.01.12 A brief description of my journey (so far) through continuation-land in Perl. I talk about wanting continuations, faking them, using real ones, despairing at their non-first-class nature, and finally how I am coming out of my depression to create work-arounds. For the un-initiated let me give you the quick of it. A standard (CGI-style) web application is restarted for every single request that the user makes. Users of the app don't realize this, all they see is page 1 followed by page 2 and so on. But behind the scenes, each click the user makes that goes to the application must contain not only the click, but enough context so that the app knows that this user is on step 3. The application must use tricks to manage its own high-level state between user interactions. This is a bad thing. Or at least annoying. At the end of each state of the application it must explicitly decide what its next state will be. Its like having to having to program with GOTO instead of function calls. Continuations change all that. While I won't go into the details here, using continuations switches things around from the programmer's point of view. Its like you suddenly have a new function, display_html_and_wait_for_input(). Your program never exits, just like a desktop application. I didn't come up with this idea, google around a bit for further details. I wanted this for Perl. But Perl doesn't have continuations. The closest we have is Coro, which I was initially reluctant to use. Mostly because I wanted serializeable continuations... continuations which can be turned into a string and stuck into a file, which would enable me to run in a pure CGI environment. It seemed like a good idea at the time (and still is, but one I can live without). Rolling this goal around in my head for a while, I finally created Contize, a fake-continuation engine for Perl objects. Let me explain the thought process that got me there: An essential aspect of continuations is the ability to pick up where you left off. So if I exit my continuation on line 127 in the middle of a for-loop, when I resume the continuation I want to be on line 128. Can't just GOTO that line though -- all the local variables need to be exactly the same as before. So I'll cheat. I create an object which intercepts each and every method invocation of my application, saving the result. Later I re-run the code, and when I get to a method I've already visited, I just return the cached value instead of actually running the method. Its like I am recording the session, and then playing it back to get back to where I was previously. The sessions can be serialized, and anything that can be serialized can be duplicated, hence we have magical fake first-class continuations! But they are a bit inefficient and have a few side-effects. I've created a few full applications using this technique. The method works, and the overhead isn't actually that bad. The applications are very database heavy, and the database queries tends to be the limiting factor when it comes to performance. Still, loading and storing all the cached method call results does have an affect, and the longer the application runs the larger the impact (hey -- if nothing else it has to "play back" more and more code each time). After using Contize for about two years, I've gotten so used to the side-effects of the technique that I don't notice the work-arounds. But they are there. One example is that most of the code has to be side-effect free. If I do a database interaction I must put it into its own method so that it gets cached and then not run each time the application is invoked. Sometimes this is a bit unnatural. Another side-effect is due to the specific implementation. Contize, you see, caches things on an object-by-object basis. So if two objects call each other back and forth funky things happen. This could be fixed by making a global cache, but other complications would persist. Ever envious of scheme and other languages with built-in continuations, the appeal of using real, efficient, side-effect-free continuations continued to grow. One day I spent two hours on a bug that ended up being because of one of these side-effects. This pushed me over the edge. With Scott's encouragement, I finally began working in earnest on a real continuation server using Coro, which I call Continuity. The project was progressing nicely for a while. Continuity has its own HTTP server and several example apps. Scott and I were working on clean APIs for application developers, and planning other features. A fast real continuation server for Perl. Until one day I realized that these wondrous real continuations aren't first-class. First-class continuations allow us to copy an existing continuations, and all of the state that it contains. So, for example, we could create a copy at every point in the navigation of our web-app. Then the back button and browser forking is magically fixed! We just restore one of these saved continuations. No such luck with Coro. Coro does not provide real, first-class, continuations. It has a module, Coro::Cont, which gives "continuations", but these are really just a simplified interface into coroutines. Namely, I can't create a copy of a running continuation, no matter how I try. Has to do with duplicating the C stack. For a long time I was in denial, but now I've accepted it... unless I re-write Perl's core (hello Perl6!), I won't be getting first-class continuations anytime soon. I then became quite depressed. When people ask you why you are feeling down, and you explain to them that it's because Perl doesn't have first-class continuations... well people who know me pat me on the shoulders and say "I'm sorry to hear that man" and frown in sympathy of sorts. People who don't look at me like I'm a weirdo. Maybe I am. Scott tried to cheer me up. He encouraged me to get on with my life -- to work with what I've got and to get some other things done. There is still a lot to do on the whole toolkit. Perl6 will have continuations, and maybe they will be first-class. So we just need to be patient. Realize where we are, be OK with that, and then move forward. Still, in order to create advanced yet usable applications I need to somehow manage the back button and browser forking now. So with the accepted state of affairs, I began to work on other methods to make things work the way I'd like. I'm still working on them, but there has been some progress. First comes the back button. A few people have suggested that the solution to the back button is to just disable it altogether. While this has been some temptation, I resist. Sure, there are times when the back button makes no sense, and then it should be disabled. But often I can think of something useful for it to do. But I digress. One answer has come in the way of Javascript and that whole AJAX craze. See, I can use Javascript to detect that I am viewing a cached page, and then do a background request to the server to let it know what is going on. The server can give back some stuff and I can use DHTML to display the result. In many ways I think that forked windows are more important than the Back button. We have multitasking operating systems, why not have multitasking applications? In fact, being able to fork a web application is one thing that sets it apart from, and perhaps above, desktop applications. Examining many different items at once in an online store, for example, is completely natural and useful. The solution to the forking-browser problem comes from the REST folks. People fork the browser by opening links in new windows/tabs. All that is needed is to make sure all the links like this can be deep-linked -- when they open it in a new window I will actually start a new continuation. Open it in the same window and I continue the existing continuation. And with that Continuity getting closer to where I want it. This piece of the web application toolkit, at least. Still have some more pieces to add. Comments on TLT - 2006.01.12 ### 3 Comments. I really enjoyed this post. I think it's good to look at what developers should have to worry about and what they should be able to leave to the framework. I think programming for the back button every time is a pretty good idea. A lot of usability problems are caused by people going back to a page that was generated from an old state. I have this problem on Reddit. As you may or may not have noticed yet, whether or not a page has been viewed by a logged-in user is stored on the server, and regardless of what computer you're on, the links you've already seen are the visted (purple) color. The CSS, though, says to show the link the color the server tells it to, regardless of whether the browser says it's visited. Apparently, they either left out this detail, or they decided that since multiple users could be using a computer, they didn't want the chance that something would come up as read if someone *else* read it. This presents a problem when the back button is pressed - since the page is what it was before you clicked it, and was not reloaded, it displays the just-visited link in blue. This whole problem could be avoided, if the web developer saw the back button as a "command", GO BACK TO PAGE X, given to his/her application. I'm wondering what the usable implementation of this is. If a user sees a page already come up, he will make judgements on it and start trying to click before it even updates itself. I don't think anything could be done to have the browser detect "back" and clear the page before the user sees the old page. I thought about this, and it seems the hack for the browser might be to send all of the initial pages visibly empty with JavaScript to get and render the page. Then when they click back, they'll be presented with an empty page, until it goes back to the server, and the server tells the client what to display. This has both pros and cons: Pros: - Continuations work well (Biggie) - Users aren't presented with old data (Biggie) - When users are pressing back many successive times, they don't have to wait for the browser to render the page Cons: - Back is slower - More programming Issues: - What message do they get when they go to a page that no longer matters, such as a piece of data they just deleted? Do they get sent to the main page? Does it say "Record not found"? I'm for the latter. Can you think of any other examples of why the back button is useful, while at the same time presents many usability problems, which could be rectified by the server side handling "back"? I think there's a lot to be learned from this, philosophically. When you click back in the browser, you're going back to the previous navigation state. This is not always the same as going back to the previous program state. When you want to go to the previous program state, it's Undo. -- ben_atkin 2006-01-15 22:42 UTC There are two continuation-based Web frameworks I am aware of. The first is Seaside, written in Smalltalk, and the powere behind Dabble DB. The other is Wee, written in Ruby. Both languages have built in continuations. -- james 2006-02-25 00:50 UTC Hi James. There are several more out there -- for ruby (using built-in continuations), for java (using hacked-in continuations), and I'm sure others. And my own Continuity library (not quite a framework) allows continuation web programming in Perl using Coro. -- awwaiid 2006-02-25 08:44 UTC Add Comment # TLT - 2005.12.30 I've been reading Reddit quite a bit lately. Its another popularity-based list if user submitted links, basically. They seem to have a pretty good vote-based algorithm for floating interesting things to the top of their list. Though I'm a bit worried. Sometimes I feel that their list is too good. One thing that has been floating near the top recently is Reflections on Trusting Trust by Ken Thompson. I don't think I've mentioned it before, but this talk is damn cool, and one that I've enjoyed sharing with others. Yet here it is, right on the Reddit frontpage, for all the world to see! First of all, how am I supposed to judge how cool people are based on their knowledge of such arcane things when everyone can find them posted so widely? Secondly, how can I share this sort of super-cool thing with folks on a person-by-person basis if everyone already knows?! On the flip side are all the interesting things floating out there that I know nothing about. Maybe I'm finally getting in to this whole blog-o-rss thing or something. Comments on TLT - 2005.12.30 ### 2 Comments. Since that article is not in the top section, it was probably up for a short amount of time. I wonder how many Reddit users go there every day (I do). It may have only linked a handful of people to that essay. I like Reddit a lot. Since finding the site, I've got over my Slashdot habit. I find that the entries are of much higher quality than Slashdot. -- ben_atkin 2006-01-11 08:59 UTC One obvious thing about reddit that I've realized since then is that it has a much more volitile pulse. That is -- right now there are cool articles because most readers and voters are fans of interesting things (especially LISP). I'm not sure the site will be able to sustain its overal interesting nature if the audience grows or changes. -- awwaiid 2006-01-11 14:41 UTC Add Comment # TLT - 2005.11.19 I've been thinking about DabbleDB quite a bit lately -- Avi Bryant's approach to solving the super-spreadsheet problem. That is, the problem that small organizations often run into when utilizing spreadsheets. They start out good, but they don't scale to more complex relational data. Of course, the solution that is typically pointed at is a database. The solution is correct, but unfortunately databases are harder to do, and even more difficult to do them Right, than spreadsheets. So in a nutshell dabble seeks to make databases easy. Looking at their product it does some obvious things, making it easy to build a database. But I keep trying to figure out what does (or could, I haven't used it myself yet) make their product better than others. I believe that the answer is near-transparent refactoring. They make it easy to incrementally transform more free-form data into typed and structured data. So if you have a field with just a few different things you put in it, they make it easy to suck this out into a related table. Good idea :) Add Comment # TLT - 2005.11.05 Lately on all the mailing lists and articles I note people doing langauge comparisons and leaving Perl out. This is quite frustrating, because often Perl exemplifies whatever it is they are discussing. Gar! I'm tempted to start replying each time I see that. Maybe I'll make a new username dontforgetperl or something specifically for that trolling. They are guilty of this a lot on slashdot (of course), but also over at Lambda The Ultimate. Eh... I'm just bitter. Comments on TLT - 2005.11.05 ### 2 Comments. But, perl just sucks ^_^. j/k (sort of). -- ealar 2005-11-06 22:22 UTC YOU'RE EVIL. Seriously, what sucks about Perl? I'm just not seeing it. And in the examples I mention, its not like they are talking about things which Perl isn't good at or something... gar I say! -- awwaiid 2005-11-07 00:06 UTC Add Comment # TLT - 2005.11.04 Went over and hung out with Scott (of Phoenix.PM) a bit, working with him on Continuity. Then came back and tinkered a bit. Now the server can support multiple apps and users at once! And my inventory demo is a full CRUD app. Its amazing what just a few lines of code can do. Last night I went to the PLUG Developer's Meeting. Its close enough to here that I'll try to go more often. More experienced, professional types there, as opposed to at AzPHP and Phoenix.PM where we have a larger variety. Hard to say that for sure, of course. Beth and I got a new pet! Woozle! Woozle is a Guinea Pig (looks like the one on the right a bit). So far Coco and Woozle don't care about each other much (though Coco is a bit territorial, and Woozle wants to escape from anything that moves in a misguided effort to return to his cage, not realizing that the only way back is to actually let me catch him). WOOZLE! Add Comment # TLT - 2005.10.29 I recently read a notable piece from Slashdot, Does Visual Studio Rot the Mind?. This was a talk given to the NYC's .NET Developer's Group by Charles Petzold, author of several Windows developer books. The style of the talk was entertaining in general, but the topic also caught my attention. Basically Petzold presenting a philosophical critique of Windows programming in Visual Studio, though the critique reaches more deeply into technology as a whole than just that. The point he makes is that the tools we use to help us program put pressure on our programming style. So, for example, IntelliSense forces us to program bottom-up, defining all our methods and variables before we use them. Because if we don't, it yells at us when trying to do auto-completion that such-and-such method is not defined. "It’s not that IntelliSense is teaching us to program like a machine; it’s just that IntelliSense would be much happier if we did." The topics his talk touches overlap quite a bit with things I've been contemplating relating to Continuity, which is why I bring it up. I don't use Visual Studio at all, but its clear that Visual Studio is not the only technology that tunes our approach to things. One example is a much-touted feature of Ruby On Rails -- code skeleton generation (a topic also mentioned in Petzold's talk). RoR has some handy tools which generate skeleton code for chunks of your class. This goes along with the general philosophy that if you are using RoR then you will be doing things the RoR way, and that's that. That's not the approach I'm going to take. When I sat in at the AzPHP meeting last month, one question asked was "what is the difference between a framework and a library?" My response was the simplistic "Your program calls library code, whereas a framework calls your program's code instead." In other words, you use a library's API, and structure your program however you wish. But in a framework, you must conform to an API that the framework uses. There's a big difference there in your freedom to structure your program however you like. Another example of the tools you use influencing how you use them. This whole thing might seem like a "duh", but I do have a point. Libraries influence your coding style less than frameworks. Using Continuation-based Web Programming we get to invert the control of the HTTP session, letting us code how we wish. What I'd like to do with Continuity is continue that trend though higher levels of application design. Add Comment # TLT - 2005.10.06 Wow, I missed a whole month! I don't actually have anything useful to say... but I'm saying it anyway. What shall I talk about? I hear that google is joining forces with Sun to push distribution of the google toolbar and the JVM. The following image comes to mind: You load google.com... and discover that it is now enhanced by being implemented as a large java applet! Comments on TLT - 2005.10.06 ### 1 Comment. That would be interesting. My first thought was that people who distribute Java applications are going to find it even harder to convince people to install the JVM. -- Ben 2005-10-08 20:18 UTC Add Comment # TLT - 2005.08.17 Had a nice visit with Levi last thursday and then Garrett on Friday. Then on Saturday (while returning Garrett to the Hiller House) I visited family all day, something I'd been meaning to do for a while now. Still knocking stuff off at work, had a tutorial session yesterday and this monday the entire phoenix office will start using the timesheet prog. Today I've been working on the export directly into the accounting system. All sorts of fun. Though I am on the verge of connecting my ODB and SetDB projects :) Now that Beth and I are in our new appartment I feel much more at-home. Not that living with the inlaws was bad or anything, its just nice to have our own space and all our stuff set up. Got the internet, goes at about 6mbit. And the Vonage phone. And got our desks all set up. The craziest thing: Rabbits love stairs! Coco will climb the stairs, run a lap around the office, and then shoot back down to the livingroom. It is sooo cute. He likes the new apt too, aparently. Add Comment # TLT - 2005.08.05 Two things happened at work today. First off, and most importantly, I was productive. I have been in a rut lately, you see, running myself in circles but not getting any significant amount of progress out of it. Today I pushed through and am meeting milestones again. I think that I was kinda stressed about getting the new apartment (which we are in now) and such, so that was surely a factor. Soon Beth and I will have the office set up, and I can then tinker from home. Second thing, perhaps disturbing -- I've decided not to sweat the javascript requirement in my SWCA applications. Generally I avoid js whenever I can, and can get away with it pretty much everywhere. Unfortunately some of these "getting away with it" techniques increasingly fall within the range of "hacks". One abuse, for example, is in links. See -- you have this complex form with lots of inputs which is the user frequents. The site navigation bar, however, is always visible and at any point they can click to go to another section. Unfortunately with a plain link any input they _just_did_ is lost. Easy enough... I just replace all the plain links with buttons! Throw a little CSS on there and they won't even know the difference. Unless, that is, they use safari. Safari's (and Konqueror's) Human Interface Guidelines dictate that buttons should look like buttons, not links. So I can't kill their borders or shape. So sad. Point being that I gave up and added some lovely onClick js to some normal links to make them submit() the form. Now they look and act like the links they are. I'll have to get some photos up of our new place, its pretty nice. Liz and Jason are visiting this weekend, and my youngest brothers Levi and Garrett will be visiting sometime soon as well. So we moved in just in time :) Comments on TLT - 2005.08.05 ### 2 Comments. So, where ARE you guys? If I remember correctly, when we ran into you and Beth at Daily Bread before we left, it sounded like Beth was going to take master's classes at ASU... so are you back down in the Valley again, or what? I love reading your journal entries, now that I've found you, and while I don't have a CLUE what you're talking about computer-wise, I enjoy reading about what you're both up to... Life... turning... turning back... re-turning. Carole S. -- Anonymous 2005-08-15 22:26 UTC Thanks Carole! I just sent you an email :) -- awwaiid 2005-08-17 23:48 UTC Add Comment # TLT - 2005.07.22 Today I invented an interesting analog to CSS selectors -- I apply the selector concept to code blocks and attributes instead of HTML. Specifically it is meant to be used in GUI components. See Code Selectors for some semblence of what I'm talking about. Comments on TLT - 2005.07.22 ### 2 Comments. The idea similiar to dynamic scope, as I understand it. Dynamic scope is very unpopular in languages these days but I guess Lisp has it. I've only read about it, but I understand it's very useful for some applications. -- evan from lj 2005-09-11 06:32 UTC Perl has dynamic scope too ('local'). After thinking about it for a moment I understand what you mean. Definately not the same though... like with dynamically scoped variables these would be set based on the call (or composition) chain, but how they are set is much more complicated and at the same time a bit less messy. More complicated because it could be 'somewhere in my call chain, f() was invoked' (doesn't have to be the immediate caller really). Less messy because function f() doesn't have to do anything to set it up, and none of the other functions in the call chain are poluted by this variable. Thanks for the connection though... I hadn't noticed it. -- awwaiid 2005-09-12 02:03 UTC Add Comment # TLT - 2005.07.11 Reading The Turing Test (ISBN 0262692937 (alternate, search)), I have been filled with insights. The book is a collection of essays, including a few from Turing himself, concerning the Turing Test and more generally criteria for intelligence as a whole. I highly recommend the book if you are interested in that sort of thing even in the slightest. Insight of the moment: Lets say that we have a machine which can pass the Turing test. What makes us thing we could convince it to actually participate? I imagine a funny little skit in which the machine and its creator have a conversation, in which the machine refuses to play the game, feeling it beneath itself and hurt that it wasn't obvious already how intelligent it was. Finally the machine creator puts the machine into the test against its wishes. The machine, being "funny", begins the conversation with "Hello. I am ELIZA. How can I help you?". Add Comment # TLT - 2005.07.08 You know how if you say a word over and over and over again sometimes it starts to sound very strange to the ears... altering the word into some sort of alien sound? Lately I've had a similar issue with my mouse pointer. When you place your pointer over a link, instead of an arrow or a text-cursor (the I-shaped thingie), you get a funny little hand pointing at the link. I noticed this hand icon when I first saw it, and thought it was ugly and stupid. Then, over the course of years of having it there, doing its thing, I forgot all about my weird feelings toward the pointy hand. Since I've been doing so much web stuff recently I once again noticed the pointer. I've also been switching back and forth between Mac, Windows, and X, which has probably made it more apparent. All of a sudden I feel transported back in time to when this whole "pointer" idea was crazyness... and having more than one pointer was just revolutionary. Cursors used to turn all sorts of shapes, really, much less subtle than now. My favorite is/was the bomb from xkill. Even so, I bet lots of people have the same reaction as I initially had and am now having daily. Whats with the pointy little hand? Comments on TLT - 2005.07.08 ### 1 Comment. I do believe it is to signify your cursor is over a link (for those pages it's hard to tell)? =p No idea really. -- Anonymous 2005-07-08 18:45 UTC Add Comment # TLT - 2005.07.06 You may have heard that NASA recently executed its Deep Impact mission in which it collided a spaceship ("Impactor" -- about the size of a coffee table) into a comet. At first I thought to myself hm, that's interesting. Then today I was reading an article on it which mentioned that this is the first time a man-made object has crashed into a comet. Suddenly the full irony of the situation hit... I mean... WE SMASHED A SPACESHIP INTO A COMET TO SEE WHAT WOULD HAPPEN!? NASA is damn cool. I can just see those guys sitting around a table discussing this six years ago. The intern in the corner was like "I have an idea..." Soon we won't be the ones fearing space debris. Rather, the space debris will be the ones fearing us. Add Comment # TLT - 2005.06.26 David and I are having all sorts of fun working on a cops-and-robbers game for the ICFP Contest 2005. Just thought I'd share. Add Comment # TLT - 2005.06.17 Moment of silence for Hammie We had him put down this morning, he had been suffering from heart failure. He was a magnificent Great Dane. A gentle giant. He was loved dearly and will be missed very much. Comments on TLT - 2005.06.17 ### 3 Comments. Oh no. This actually made me cry. I haven't seen him in ages, but he was definitely loved. Give Beth and her mom a hug for me. -- mandies 2005-06-18 00:54 UTC I will -- awwaiid 2005-06-20 00:11 UTC Brock and Beth, I was SO sorry to read about the loss of the Dane. I have oftened wondered why it is so painful to lose our animal "people" and I have decided that it's one of the ways the Universe keeps us humans REAL when we tend to close ourselves off from that in our objective realities... I feel your sorrow. Carole Seeley -- Anonymous 2005-08-15 21:44 UTC Add Comment # TLT - 2005.06.09 Check out The Fridge. Feel free to contribute your deep poetry and banal remarks. Sync often. Add Comment # TLT - 2005.06.07 Yesterday I neglected to mention Sarge was released. One of Beth's complaints about linux is that I'm always changing things. So I've had her on testing for a while and now I'll move her over to stable. Then nothing will change for like 3 years! At work I'm working on this timesheet application. The structure was put into place previously, but I've made some significant alterations to the internals. Well now that I've got things worked around, once again it goes back to user interface design, which is always an interesting challenge -- even in what many would see as something mundain. The subtlties involved are numerous. Core to the struggle is the tradeoff between useability (with little to no training) and productivity. The goal is to have an intuitive interface which doesn't slow down the experienced users. People will be using this on a daily basis, so its pretty important that they don't have to click through friendly messages reminding them of what they can and cannot do. Reflecting upon the solutions posed by others in the desktop application world, we see that there are a variety of methods to bridge the gap. First is a good help/documentation system. Every screen has a help button that will tell you all about the current part of the program, its features and limitations. Lovely little screenshots and links to more in-depth topics. Then there are tutorials. These go hand-in-hand with the help system, and often the tutorial is somewhere in the Help. There are of course many depths of tutorial... and if something much deeper than an overview of nuances of the system is required I'm not sure that this is the right idea. In other words, if the going through the tutorial is the only way to figure out the application, perhaps the application needs to move a bit toward the intuitive side of the gap. Besides, "tutorial" is another way of saying non-supervised training. Two more. Next is having a per-user set of preferences. Then you can have users and power-users. Or even just different ways of approaching the problem to be solved. I'll have to think about this more (in regard to the applications I work on). One thing I see in a lot of applications are first-time-usage messages. So the first time you run into the overtime issue extra documentation appears to let you know what is happening. These are all obvious things when it comes to desktop apps, but they are missing in a lot of web-based applications. I suppose I just need to continue letting go of the static-webpage ideology and embrace the application. Comments on TLT - 2005.06.07 ### 6 Comments. The regular employees (not me - I'm a contractor) here at USGS are getting a commercial timecard system. I think their whole system could be made in a couple of days - it looks as if zero usability testing was done and all but the most simple features break. The manager can't figure out how to work with multiple projects. It apparently stores what project she's in in her session. It sounds like a real piece of junk. I would guess that the program was selected only on the basis of features, not design quality. I suspect that if someone complained that they had to use the program every day, the out-of-towners who bought the program would say something to the effect of "at least you're only using it for a few minutes every day". It's interesting to see the neat approaches hackers take on even the most mundane problems. On a side note, I'm going to take tomorrow off and devote all my time this weekend to the ICFP '05 contest. I don't know how far I get, especially since I'll be working by myself this time due to lack of planning, but it should be a neat experience. -- Ben 2005-06-23 20:59 UTC Hiya Ben! What programming language are you going to use? -- awwaiid 2005-06-23 23:25 UTC Python and/or Ocaml. -- Ben 2005-06-24 14:00 UTC Well I'm doing it in Perl and/or OCaml :). Except that I didn't get today off, so I don't know how well I'll fare. Whats your email addr? -- awwaiid 2005-06-24 14:27 UTC Well I'm doing it in Perl and/or OCaml :). Except that I didn't get today off, so I don't know how well I'll fare. Whats your email addr? -- awwaiid 2005-06-24 14:41 UTC ben@benatkin.com -- Ben 2005-06-25 03:27 UTC Add Comment # TLT - 2005.06.06 Work at SWCA is going very well. I have a whiteboard and PowerBook and everything. I've done a port of Continuity, or at least the philosophical core, to PHP. Perhaps Steve will let me open source it... but right now I'm too busy using it to publish anything. Here is the summary of the world: • Star Wars, Revenge of the Sith - Sucks • Ongoing AJAX craze - interesting but scary • Intel Inside Apples - interesting but scary • Mirabel down for a few hours today - sad • Daily Show - good • Monk (TV Show) - makes me happy • Sherlock Holmes - same • PowerMac G4 - nice, especially the battery life... but I'll stick with Jill • Rabbit - DRIVES ME CRAZY WHEN I'M TRYING TO SLEEP Stupid rabbit. Kept me up most of the night yesterday making chewing sounds. Grr. I woke up downright angry. Comments on TLT - 2005.06.06 ### 3 Comments. Intell in Apples doesn't really bug me. They make reasonably good CPU's and I think Apple /still/ suffers from "Not enough MHZ" symdrom in the consumer market place. Further, while the Power4 is a really f'ing nice chip, it was never on the radar for my next cpu, even with real vector instructions. Dual opterion running linux *mmmmmm*. Too many people know just enough to have been taught by Intell that MHZ is all. -- Anonymous 2005-06-07 12:16 UTC I love you because you said "downright". PeeEss: Tell Miss Elizabeth that some customer has made 'recommends' lists for all of her father's books and put them up on display. It's kind of creepy. Hearts! -- mandies 2005-06-08 03:46 UTC I'm a fan of amd as well. I heard that IBM was also giving apple trouble in meeting supply orders on time. (hey -- sign your name so I know who you are) For all those others out there, Mandieshead refers to wikipedia:Michael_McCollum, the science fiction author and my father-in-law. -- awwaiid 2005-06-08 05:52 UTC Add Comment # TLT - 2005.05.10 Describe the new page here. Sweet... the soundcard in my Vaio isn't broken after all! See http://modular.fas.harvard.edu/z505he.html, where they mention the issue. Basically the connector to the sound card, which sits about where my left hand rests, comes loose. First goes the speakers, then goes the headphones. Exactly my issue. In fact, now that I know about the problem I press down on the spot and my sound magically returns! Now I just need a clean table to take jill apart and she will be as good as new! I am now employed with SWCA, and so far so good. In-house PHP programming, building on some nice clean existing code. I'm very pleased with it so far! Comments on TLT - 2005.05.10 ### 5 Comments. Some of those vaio stories are pretty funny. Seems like your new job is easier to swallow morally than the last one. I actually had to google to pass your human test. I am a bad human. -- Anonymous 2005-05-11 08:43 UTC Which test was it? Some of them are a bit independent... but as a secrent hint you can try hiting reload to get another one :) -- awwaiid 2005-05-11 13:31 UTC Why is a raven like a writing desk? I miss you guys. Semester hell is finally over and all is well. How's Beth doing? And are you guys coming down to the valley or are you working there via Flagstaff? Leslie Gurney came into the store a couple of weeks ago. She's a D&D Dork now, which cracked me up. It was great to see her again, though, since I hadn't since before your wedding. Happy Anniversaryishness, by the way. (I know I'll forget over the next few days. :p) -- mandies 2005-05-12 19:10 UTC Aww... its a MANDIES! I will pass the happy-anniversary on to beth. We are coming down the the valley. specifically I am already down in the valley, and beth will be joining me soon. We will stay at beth's parent's house for a bit, and then get our own place before too long. So then you can come and chill with us in tempeland. -- awwaiid 2005-05-13 20:04 UTC Then we need to have a party and attack the world. Tell Beth that the Bookmans in Phoenix is hiring; it's barely-livable wage, but an awesome job. :) Mad hearts and such. -- mandies 2005-05-17 04:02 UTC Add Comment # TLT - 2005.04.25 I'm not dead yet! Job search is going well. Surprisingly, jobs have started to come to me, via various contacts and Monster. All sorts of fun. I've been thinking about Science and Mathematics lately, and how they interact. There was a very interesting paper mentioned on http://lambda-the-ultimate.org/, The Unreasonable Effectiveness of Mathematics in the Natural Sciences, which is a great read. This and a few other random encounters have led me to contemplate the relationship between mathematics and science. One thing, which I cannot repeat often enough, is a simple yet profound difference between the process of the two disciplines. Mathematics is about proof, while science is about disproof. This has surely been written elsewhere, but it is nice to contemplate the idea on its own. In mathematics you come up with a theorem, and then attempt to prove that the theorem is correct or incorrect though logical argument. In experimental science, on the other hand, you come up with a theory which explains all known data points. You then try to collect further data points or make a logical argument in an attempt to disprove the theory. That framework in mind, lets turn our attention to the concept of completeness in mathematics. From Goedel we have the incompleteness theorem, which states that (in our current system) there are truths of mathematics which are not reachable by logical argument from existing truths. That is -- there are some statements which we cannot prove nor disprove, but for which there is no situation in which the statement is false. In other words, there are true statements of mathematics which cannot be proven. Now lets turn our attention to science. Are there, then, statements of science which cannot be disproven, in a corresponding way? The most direct instance of such a concept is that of God. God is here defined as something completely outside our physical system, yet which exists non-the-less. Existence without physical manifestation seems like something we surely cannot disprove. This seems to put the question outside the reach of science. Yet we have one more bit of thought from the mathematitions which can be borrowed. How did they react to the incompleteness theorem? They kept right on trying to prove everything under the sun. Even with problems which took years and years to solve, they continued. Even with the threat that these problems may in fact be un-provable. Many of these problems have yielded great results and even proofs... but others are left unsolved. When do we give up? Now apply this question to science. Comments on TLT - 2005.04.25 ### 1 Comment. Thanks for the spelling fix, person from UNC. One of these days I'll finish the spellchecker thingie I started once... -- awwaiid 2005-04-25 21:51 UTC Add Comment # TLT - 2005.03.18 I used to get Dr. Dobb's Journal, and the first thing I'd flip to was Swaine's Flames. They were simple, one-page articles, centering on some random thought from Michael Swaine. Like many of the stylistic articles I enjoy, he'd start on a topic, wander off for a while, and then bring it all back around to his point (if he had one). Enthralled with this, and wanting to spread my own memes throughout the world, I set out to emulate this style. In my head, anyway. So far it hasn't actually happened, even though I've tried a bit. Now and then I write something down, but it doesn't really come out the way I'd like. Primarily I try to use the TLT, but there are some issues. Biggest issue -- I don't spend enough time on any one entry. There is no editing or revision, no thought or consideration. Instead I write whatever comes into my mind at the moment and then hit the 'post' button and thats that. Thus here I am, unsatisfied, forced into a meta-discussion. Not that I don't enjoy meta-discussions. In fact, if you stick the meta- prefix onto just about anything there is a very good chance that I will be interested in it. Lets try... meta-programming. Meta-mathematics. Meta-cooking. Meta-taxes. All things I love! But I digress. So time and revisioning are definately things which are slowing my progress. Of course, Swaine has the advantage of being paid to write his rants. Oh, and he actually has things to rant about. What do I have? Strange stories about how I think the neo-nazi party should have an image makeover centering around using 'Z' (with a little sideways z overlayed) as their new logo and name ("We're the Z's!"). Perhaps. Until you realize that Z's point the wrong direction to simulate an official swastika. Though it could still be their "unofficial" logo. Not that I want to encourage nazi-ism, mind you. Its just marketing. Point being that he gets to go on strange tangents whereas I do not. Thus I have in mind a solution which will be pleasing for everyone, especially me. All it takes is you... your donation could mean one more hour of thought will go into my next entry! Just imagine all of the high-quality articles which I might produce once your check arrives in my mailbox. Wouldn't it be wonderful?! I could even use the money to re-subscribe to Dr. Dobb's Journal so that I can read Swaine's Flames. Add Comment # TLT - 2005.03.10  New idea in mind Current idea neglected The flood pushes past Add Comment # TLT - 2005.03.09 I think that, in addition to xor, we should use "ior" to explicitly mean "inclusive-or". Yeah yeah... I know that "or" alone is implicitly an "ior"... but I just like the sound of ior :) Doh! I didn't notice that my little edit-todays-entry shortcut was messed up and didn't pad my dates with zeros... oh well. I've been trying to use KHTML instead of Gecko to do the magical html->ps rendering... and in some ways its better and in some ways worse. First of all, it is pretty darn easy to get it going, and the KHTML widget is waaayyy easier to use than the mozilla one. But really we should be comparing the KHTML widget to the gtkmozembed widget... in which case they are much closer in ease-of-use. The KHTML widget, however, has no issues rendering to buffers unattached to the screen (so far). I just now have to get it to print without any screen interaction. The big drawback is that out-of-the-box it has to start all of freakin-KDE in order to do anything... which sucks. So I plow on! Add Comment # TLT - 2005.03.07  Caffeine in my veins Soaring above world constraint Then come crashing down Add Comment # TLT - 2005.03.03 Demonstration Add Comment # TLT - 2005.03.01 I wonder what the world would be like without the '@' symbol. I remember back when I had my first computer, an Apple ][e, which was when I first noticed the symbol. I hated it. I mean... who needs an abreviation for 'at'? Its only two letters long as it is! I refused to use it, even when typing short-hand notes. But look at me now... I use '@' all the time. The first thing that comes to mind is email addresses. What would we use instead of '@'? Well they used random stuff before Ray started the '@' thing in '67, and would surely have gotten along just fine. So I cruise on over to wikipedia, and lowe-and-behold... italians. Yep... the ampersat very likely came out of the renaissance. If they only knew how much they were contributing to Perl! Add Comment # TLT - 2005.02.20 Made some progress on my Perl backend for OGPF. I keep thrashing though... still not feeling great about the whole structure. I keep thinking that I should just start over, yet it is quite clear that it would be a mistake. It works, and it works pretty darn well - just needs some tuning. Or better yet some feedback. What I really need is someone ELSE to actually use the thing. But the likelyness of anyone else using it in its convoluted state is pretty low. I suppose I should focus on how well it works for me :) Add Comment # TLT - 2005.02.19 Roman numerals annoy me. After some brief research on the internet (especially see Wikipedia:Roman Numerals), I've discovered that the way I've always considered "standard" is not necessarily so. Unfortunately the Superbowl does it the way I don't like... so I'm afraid the status will be commited forever! It comes down to this (from wikipedia): "Some rules regarding Roman numerals state that a symbol representing 10<sup>x</sup> may not precede any symbol larger than 10<sup>x+1</sup>. For example, one should represent the number "ninety-nine" as XCIX, not IC. However, these rules are not universally followed." I would like to thus publically state that I am one of those non-adopters of that stupid rule. As far as I'm concerned we recently had Superbowl IXL. And you just know its all the fault of those marketing people because (1) they learned it the stupid way in school, and (2) MORE X's PEOPLE! Everyone loves X! X X X!!! Bloody Romans. Add Comment # TLT - 2005.02.18 I'm slowly making progress on my perl backend for OGPF. Lately I've been feeling a little down on my genetic programming activities because I spend a lot more time building frameworks than actually using the frameworks. On the other hand I've always conceived OGPF as an experimental system... so I suppose if I eventually abandon it so that I can get some actual work done it would be OK. Back on the other hand it isn't really worth abandoning. It certainly works, its just that I'm not using it. I built a simple tree-based backend, and tested that. Then I built a untyped lambda calculus backend, but haven't really used it. Then I decided at CodeCon that it would be fun to do a Perl backend. Using Perl for the backend has several advantages over the lambda calculus, foremost being ease of interface with system constructs. But then I wonder what I would get out of Perl as compared to a typed lambda-calc (such as even dumping to a subset of OCaml/ML). See if I dumped to OCaml I would also solve my interface issue, while maintaining performance and a single-language system. On the other hand the programs themselves loose flexibility. Using Perl I get limited typing, which is more than none but less restrictive than full. This all brings me back to Lee Spector's Pushpop system. He has constructed a programming language/system specifically for evolutionary computation. In Pushpop the individuals in the population are responsible for their own reproduction which has some interesting implications, such as their building of abstractions to copy themselves also pushing them toward modularity of sorts. Providing a flexible environment means that programs can evolve to solve the problems in a natural way, not necessarily a human-logic way. Overall I am walking a thin line between flexibility for the GP individuals and simple interfacing with external systems (including humans). I'm just not sure where I fall on this issue and the only way I'll figure it out is through actual experimentation with a variety of systems... and if I never complete any of my backends then I'll never make progress. And time marches on. Add Comment # TLT - 2005.02.17.11.09 Well, updating an existing entry doesn't work, because lj is nice and caches the entries. So now I have to explore getting around that. Hrm. Anyway. Midendian is on his way to the orient! I take it back, it did update! woo hoo! Well then, I guess I don't have to do anything special afterall. I think it updated, anyway. Oh well... I'll just move forward with the assumption that it does update. Well, since I wasted this entry anyway, I might as well test out some stuff. Here is a . Here is a local link, Projects. Here is a web link, http://wikipedia.org, and here is a named web link, wikipedia. Fun, eh? Comments on TLT - 2005.02.17.11.09 ### 1 Comment. test comment -- awwaiid 2005-02-17 20:55 UTC Add Comment # TLT - 2005.02.17 So you livejournal feed readers may have noticed that I finally fixed my feed. Now it sucks not just the subject but also the content including links. Since I now know that people might be listening I'll have to think of something useful to talk about... yeah right. So now we will experiment to see what happens if I change an entry after it has been sucked over to livejournal. Wish me luck. OK... this is a test of an updated entry! Add Comment # TLT - 2005.02.15 Sheesh. I should go to bed. Well, in any case, I've just completed my initial run of work on Oddmuse EditSection. This extension makes sections have individual edit buttons, just like on http://wikipedia.org/. Sooooo fun! The nerds go hacking one by one! Hurrah! Hurrah! The nerds go hacking one by one! Hurrah! Hurrah! The nerds go hacking one by one, right until the night is done and they all-go-hack-ing Down. In the dark. To get out. Of this dream. Add Comment # TLT - 2005.02.13 CodeCon is fun, though different than other conferences I've attended. Its all nerds, but I've seen that at math conferences. Its hosted at a nightclub, and the lighting is set up about how you'd expect a night club to be done, which is to say that it is quite dark. This certainly makes it easy to see the ongoing presentation, and definately adds a very hackeresq feel to the whole thing. Pretty good variety in the people, in both interests and talent. On Friday evening we went and hung out with Tim and his kids. His kids are great, they even did a skit for us right out of The Holy Grail. Tim and I got to talk about some of our pet projects, stuff that relates to Continuity mostly. His idea is that (basically) in an MVC system the entire View component should live on the person's desktop. Now, while I agree that this is how things should be, it is hard for me to believe that we have reached the point where it can actually be done. But he points to javascript in the browser allowing for rich client interaction... but my heart is still holding back. Neither of us are actually doing it that way yet at this point, but others are beginning. Today the presentation which I'm most looking forward to is WheatFarm. Its an intersting idea (though possibly already-been-done in a lot of ways). I'd like to know if they have any ideas for non-coolness uses for the thing. Add Comment # TLT - 2005.02.09 I'm very excited... will be heading to SF for CodeCon tomorrow evening. I get to see mid off before he goes on his big trip. I'm getting jill all charged up, syncing everything. All kinds of fun. Add Comment # TLT - 2005.02.07 hrm. bleh. Well, looks like the comment hack for the questionasker extension does something bad and sucks up tons of server memory. Until I fix it comments won't work... if you want to leave a comment (even on a comment page) just edit the page! I noticed it was broken last night, so I turned it off because I was showing a the wiki off and wanted all the features working. But turned the questionasker completely off... just between then and this morning I actually got more SPAM! Crazyness. So far I have gotten zero spam when the QuestionAsker is turned on though... hrm. Add Comment # TLT - 2005.02.06 Arg. I turn my QuestionAsker extension off for less than two days and I get SPAMed! I'm turning it back on and fixing it so that people can add comments again. My previous idea was to allow comments without the question, but the recent spam was added to both my sidebar AND to the comment section on my sidebar. Evil. The thing is, that in general the question-asker is annoying. One idea I just had is to do a one-time question asker thingie... where the login for the Editor mode is the question, and thereafter (so long as you are logged in) you do not need to answer the question. This still isn't as easy as no question at all though... hrm. So I got the QuestionAsker Extension to work on comment pages, and I bypassed it for my tracker stuff. Grr. Comments on TLT - 2005.02.06 ### 1 Comment. OK... I fixed the comment pages. Now you do have to answer the question, but you can leave a comment if you get it correct! -- awwaiid 2005-02-06 21:37 UTC Add Comment # TLT - 2005.02.04 I never could figure out what was wrong with my simple-changes sidebar thingie... so I've given up and just hacked around it. Also set up a demo issue-tracker, see Create Tracker Item and try it out. This whole wiki thing is such a powerful idea... it doesn't take much to make it do all sorts of things. I think I still need to fix my RSS feed though. hrm. Tomorrow is the LUNA installfest! I'm excited. Depending on who shows up and what they want to hear I might give a talk. Just an overview of the major software components in a typical desktop setup. Still fun though. Getting close to when I get to go to Codecon... Add Comment # TLT - 2005.01.31 Describe the new page here. In the "other comments" section of an NAU parking services survey: Two crazy ideas: (1) Don't sell more parking stickers than you have parking spaces<br> (2) Give everyone one single assigned spot And a bonus (in the case that you don't do the above, which I'm sure you won't): (3) Only ticket people when they are consuming resources in a way that limit those who have paid. In other words, don't ticket someone who is parked in an otherwise empty parking lot without the correct sticker. The only reason this is done is to make money, and if you want more money it should come from an increase in tuition not an evil plot to suck money out of the student population one ticket at a time. This back-handed way of getting funding is ethically wrong and you should be ashamed of yourselves. I suspect they will ignore me. Hopefully they will get a good laugh out of it :) I should fix my comment pages. I broke them when I added my QuestionAsker extension. hrm. Add Comment # TLT - 2005.01.28 So the folks over at IlliGAL started a genetic-programming blog, http://www.illigal.blogspot.com/. I think its super cool! In like one day they've generated more interesting GP tidbits than the mailing list has generated in quite a while. Unlike the mailing list, the detailed information in the blog actually makes me feel inspired to write down the thoughts inside of my own head. So i did something super cool the other day, I created a smalltalk-like browser for perl (see GOE) as a module in the EPFarms Panel. It was such a simple thing to do... and yet it seems to have so much potential. The first thing I want to get going is this: when you get an error now (a panel-module crashes for example), the system emails me. Well what I want it to do is to detect whether the person logged in is a developer, and if so give them a link to directly see the code which caused the error. I'm going to CodeCon in a few weeks, and I'm quite excited. One of the many interesting projects being presented is Wheatfarm, which was my inspiration for the above hack. It is a wiki/object system/web-based-programming-envirionment. Interesting... but I'll stick with Perl for now :) Add Comment # TLT - 2005.01.13 At last Mirabel lives! Hopefully all my faithful readers have noticed the significant speed boot to the wiki. Feel free to enjoy it further by commenting ona page or something. So yeah. All sorts of fun! Add Comment # TLT - 2005.01.03 Lots of snow today. It supposed to snow every day for a week (except for maybe thursday). I hope to go skiing on friday :) Add Comment # TLT - 2004.12.21 Got a game going with Jason over at the Dragon Go Server, should be fun. Started some more work on OGPF last night. I keep going back and forth between using the untyped-lambda-calculus implementation and doing a full OCaml/MetaOCaml method. I'm going with the lambda-calc (again). Implementing a tic-tac-toe competition. The immediate plan involves trying things like seeding the population or starting from scratch, trying different sizes of population, etc. The longer term is to create a disparity between the genotype and phenotype and start doing some neutral evolution. Add Comment # TLT - 2004.12.16 Describe the new page here. Hello. Add Comment # TLT - 2004.12.14 Happy birthday to me! Went and watched National Treasure... it was ok. Certainly no Davinci Code or anything... some frantic running (which adds points in my book). Now that RSS works again I'll have to re-start my cron job to notify me of changes to this site. No spam yet, but since they are most likely humans doing the spam (so I hear) the question-asker may not stop them. It was fun anyway though. I often feel that I should program in Smalltalk more, or at least a little. I think it goes back to my initial quest for an understanding of object-oriented programming. For something silly like a year and a half I read everything about OOP I could get my grubby hands on... books, papers, websites, anything. I just didn't get it. What, exactly, did OOP provide which I didn't already have using a modular style of programming, as was available to me in a language like Pascal? There must be something, I thought, or people wouldn't go on and on about it all the time. Finally I found Smalltalk. In its simplicity and beauty I had my answer... OOP is not better than other techniques, but it is different. Seeing the code for displaying a button on the screen, and realizing that the method which controlled the button's physical location was the same as the method which controlled the overall windows' location... that they were in fact the same exact method... I realized that this way of organizing code and relating it to the data it manipulates made sense and wasn't overly stupid. I didn't become an OOP fan per-se, but I did become a smalltalk fan. The hype of OOP in general did become pretty silly to me, however. I liked Adam's use of pointers-to-functions in C structs, in a lot of ways better than I liked C++'s real objects. Perl taught me that OOP may as well be equivalent to a fancy function calling convention and some hackery. OCaml/ML taught me that often what I really wanted was polymorphism and perhaps a powerful module system. But still... in the back of my mind is the powerful simplicity of Smalltalk. A couple times a year I'll grab Squeak and turn it on... but I never do anything with it. Add Comment # TLT - 2004.12.12 Woo hoo! I now have some anti-robot security. Stupid robots... Weekends sure are short these days. I think thanksgiving was just soo long that all the rest are, well, half as big. Add Comment # TLT - 2004.12.10 Arrg. Whole lot of wiki-spam over the last few days. I need to fix my RSS so that I will be notified of this sort of thing right away, first of all. Second of all... I must make it stop. For just a flicker of a second I thought "fine then, nobody edits but me"... but then I noticed in the change long that someone else actually fixed some spam for me :) The thing is, I'm not entirely sure how much of the junk is added by humans and how much is added by robots... hrm. Actually I just noticed that some of my referrers are obvious web-searches for the oddmuse footer text. Now I've repeated the search and found other peoples' pages which got attacked and fixed them. I'll figure something out to deal with this soon... Well my week was long and difficult... everything I touched at work turned to dust and that pretty much took up all my time. Here is an idea for the WikiSpam issue: You must answer a simple question to save a page. This is along the idea of "what do you see in this image" trick that some sites do now, except that it would be completely text-based. This has several advantages. First off, it is not so server-intense. The image-based techniques either cache the images or generate them on the fly (usually the latter to at least some degree). They must make the image un-readable by OCR but readable by people. Secondly, and more importantly, I can ask arbitrary questions of an english-speaking (intelligent) audience. Sample questions: • What is the first letter of this question? • How many letters are in the word "dog"? • What is 2 + 2? • Why is a raven like a writing desk? Add Comment # TLT - 2004.12.05 This weekend was too short. Probably just because the last one was so long. Still... I feel dissatisfied. And see the bottom of this for a lovely koan. Add Comment # TLT - 2004.11.24 Time for my weekly log entry :) Adam is staying with us for the last day or so. Tonight we will go down to Tempe for Thanksgiving. Beth and I will hang out, no specific plans yet. The real fun is Fri-Sun, we will be going to Exotic Yuma! (if I haven't mentioned that before).To take Hammie to a dog show. Beth's mom is in MA visiting Rob&Patty. Add Comment # TLT - 2004.11.17 Well it turns out the stupid motherboard we got for the New Mirable does in fact REQUIRE registered RAM! EVIL!! David picked up a stick last weekend and we tested it last night and at last we have a working machine. It'll still be a while before it is live -- have to order all new ram now, and then of course we have to send it back to Florida. But I'm very excited and soon will be recruiting new members all over the place. Saturate this machine and then buy another! That would be great :) Add Comment # TLT - 2004.11.10 Sometimes when I'm programming its a lot like being in a dream. This is most apparent when something interrupts me, pulling me out of the dream world. I'm groggy at first, unsure of what is really happening. Slowly I adjust, addressing the interruption. Then, when the interruption is over, I try to go back. But you don't always dream the same dream, and I can't always remember where I was and what I was doing in the program. I have to ease myself back into it until I finally let go and once again lose myself. Add Comment # TLT - 2004.11.05 Been quite busy with work. In a good way though. Tonight did some crazy DB field resizing under pretty serious time-constraint... went acceptably I'd say. Beth said something at dinner which has gotten me to think a bit about GP and the current status of OGPF. I left off at the spot where I was implementing some of Koza's examples. I didn't get very far because it really isn't very interesting to implement someone else's ideas... but I really do think that is the next step that I should do. After that I can move to the work Tinu Yu did on lambda-calculus as a genotype. And then, FINALLY, I can work on my own ideas about typed l-calc with various genotype-phenotype mappings. Other than gereral results from evolving typed l-calc stuff, I think that one of the most promising directions that GP can take is optimizing pre-existing programs. Actually I'd like to clarify -- by "optimize" I mean either simplify algorithms or improve performance, but I expect that the GP will have to focus on one type of optimization or the other. Though of course the solution spaces for either overlap quite a bit, I'd guess. We'll see! So I think I'll program until Beth is ready for bed. Add Comment # TLT - 2004.10.23 Hanging out in phoenix at Liz's. Red Sox won... I was recruited as a Red Sox fan while in the Boston area in the early summer. Perhaps the addition of one more fan has been just enough to raise the curse? We'll see soon enough. Liz has a neighbor below her who plays very loud deep mexican um-pa music, and he just started it. Considering that it is just getting to be 1:30AM, even the usual flexible, let people do their own thing ideology I have weakens and I have the urge to stomp or go down and yell at him. Liz asked the apartment people to talk to him, but that hasn't helped yet. Maybe he should move his bass away from the wall a bit or something. So. Yeah. Add Comment # TLT - 2004.10.17 Interesting weekend. Among other things I got a new release of Contize out to CPAN, with some minor changes all toward getting Continuity to work. And today I released Continuity, which I'm very pleased about :) Now I'm trying to drum up some people to push me into furthering this project. So far no such luck. I'll make a couple more example programs, as I need them, to show how the thing can be used. If you build it they will come? Add Comment # TLT - 2004.10.07 Add Comment # TLT - 2004.10.04 Welcome to October! I really should fix my SimpleChanges thingie... I didn't realize how much I used that until it was gone. But I'm too busy working right now. Working to use http://egroupware.org which is going OK. I even get flashes sometimes where I consider using it for eggplant farms. But then it passes. I was just checking out http://www.kjack.org/ and noticed some subtle but quite good changes that David made. I like it. Snow mentioned to him that he'd like a re-design, something... using Frontpage. ick. What a horrible idea that is. You should have seen it before I started... nnaaaasssttyyyy. The problem is that Snow doesn't see it getting utilized, so he believes that a redesign will somehow fix it. Truth be told, however, the trick is in advertising, not in its look. The site is clean and works well, and people use the shout-box quite a bit actually. But they have no motivation to use any other part of the site. Soon DJ's will start putting up their own pages, which will help. Anyway. bah. Back to work I think. Add Comment # TLT - 2004.09.27 Just chugging along here. Practicing my harmonica to whatever comes on -- went form "Bad Moon Rising" to "I'm Too Sexy" for an interesting transition. Curtis has returned to work after a weeklong vacation.., no meltdowns while he was goine which we are all happy about. Work is still going very well. Mirabel is frustrating, as usual. We put her together on thursday/friday, but of course she didn't work. David and I figure it is probably the motherboard, but we are going to try to get a second opinion in-town before we send it back to http://newegg.com. Wish us luck! I'm _really_ looking forward to getting it all working and sent off to Florida-land. Beth and I went down to Phoenix this weekend to send Jason off, he'll be leaving next weekend for DC. We'll go visit him next summer or so I hope, him and Erik et al. I've never been to DC, so I'm looking forward to it. Oh, and speaking of trips we're contemplating going to Idah to visit my family for Thanksgiving. Doo dah... too sexy for my cat... Add Comment # TLT - 2004.09.21 I just noticed http://www.hostingsoftware.net/, which is a direct competetor to http://eggplantfarms.org's own system of custom scripts and EPFarms Panel. I'll probably go ahead and install it to see what its all about, but from the description it is definately not an abandon-ship worthy project. Sounds like there are a couple core design descisions that we decided upon differently. Interesting none the less. I'm very excited about the new Mirabel! Pieces have already started to arrive in the mail. The only one that seems like it will be slow in getting here is the powersupply. Time to wake up Beth. Add Comment # TLT - 2004.09.20 So as I may have mentioned we got VOIP service instead of a landline from http://packet8.net. So far its been satisfactory, but we've had two outages. The first was because of the cable internet company -- messed up their DB of MAC addresses, but is fixed now. The second was tonight and was definately Packet8's fault. The outage wasn't for long, and I called up the tech support using the cellphone to make sure that it wasn't our fault. As usual they answered fairly soon and told me that it was indeed a network outage on their end (even their website was down at this time). Said it would be up in about half and hour and indeed it was. But while I was thinking about it I thought I'd push on with my research into the details of their system. Once their webpage came back I noticed that they had a firmware upgrade available, so I went for it. They produce their own phone --> ethernet gateway, the DTA-310, which comes as part of the service. I never noticed before (which is strange), but it has a simple little web interface. The firmware can be upgraded either through a windows executable (ick) or through a lovely http upload. I did the latter and in no time had new firmware with a couple new features, including some more statistics measurements for call quality. Well while I was in there poking around I noticed an Advanced Configuration section, which is blocked off by a password unbeknownst to me. Search on the net so far says that nobody knows it, or at least nobody is talking. BUT Wait! I have a lovely .bin for the firmware! So I open that up in a hex editor, as someone else mentioned doing, and see lots of lovely gibberish and strings from their webpages and settings. No plaintext password unfortunately, but I wasn't expecting one. Other research has led me to believe that they are programming everything in C... which should be perfectly de-compileable. Now I just have to find out what chip I'm decompiling for. Next step... pop the top. Stay tuned. Add Comment # TLT - 2004.09.13 Howdy. I'm back! We're all moved to Flagstaff and in our new apartment. Things are going wonderfully... workin and playin and all that. I got a VOIP phone from http://packet8.net which is fun to play with. Ended up doing some QOS and I will post the method here sometime. Just a brief update. Add Comment # TLT - 2004.08.27 I've said it before and I'll say it again, I love the [[Yucca_Tap_Room?]]. We went over there last night... figure that it would be our last evening spent here while not packing for a while. Jason, Liz, Beth, and I. Played shuffleboard and drank cheap beer... live band after a bit. First this one guy played alone, good player but made some aweful comments and jokes. Then a full band got on and played some nice loud rock stuff. Its the kind of bar I'd hang out in if I was an alchoholic or was always avoiding my wife. Add Comment # TLT - 2004.08.23 A friend once told me that you can put a person into one of two categories -- a Beetles Man or an Elvis Man. I told him that this was stupid and that he couldn't force me to choose one or the other and that it wasn't right to put people into such categories. The topic has come up from time to time since then ([[Brock's_First_Law?]] and all)... and each time I pretty much say the same thing. Just now I was listening to http://www.bootliquor.com/ radio, and something suddenly became very clear to me. I am an Elvis Man. Comments on TLT - 2004.08.23 ### 4 Comments. I am an Elvis Man. Well duh, I coulda told you that. --mid (Beetles Man) -- Anonymous 2004-08-24 01:22 UTC hrmpf. -- awwaiid 2004-08-24 02:20 UTC I'm totally with Adam here, but I told you that long ago. :p Guess which I am?! -- mandies the great 2004-08-27 18:17 UTC yadda yadda to both of you. -- awwaiid 2004-08-27 19:01 UTC Add Comment # TLT - 2004.08.22 So I'm learning about [[Answer_Set_Programming?]] and some other prolog-like things... my thought is that I might be able to teach Vladimir a thing or two about logical deduction :). I feel like I'm way behind on this material, but no time to start like the present. Add Comment # TLT - 2004.08.19 Everything Perl. http://www.timetravelfund.com/ -- makes a great gift! Add Comment # TLT - 2004.08.16 Hm. Don't mind me, I'm just working on an email TLT poster. Add Comment # TLT - 2004.08.14 I'm still alive. Doing some contract work for http://www.norchemlab.com/ in Perl which is fun. More details on my life to come soon as I get back into the habit of posting here. OK, lets consider the web framework that I've put together for the panel. First of all it is Model-View-Controller. The Model is based on Class::DBI, which I hope to someday have some lovely SetDB wrapper. The View is a thin wrapper around Embperl. And finally, the Controller is straight perl programming with the aid of Contize. Right now all three are separate, and I like it that way, but I am starting to think of ways to blend them together more efficiently. So, for example, I wrote a lovely method called dispTemplate which is used like this: sub personDetails { my (self, person) = @_; my f = self->dispTemplate('personDetails.tpl', person => person ); my action = f->{action} || 'Save'; # Save by default if (action eq 'Save') { self->saveRecord(person, f) } }  Actually I am using two helper methods here -- dispTemplate displays a template and returns the query string, and saveRecord extracts the appropriate variables from f to put into person. There are a lot of advantages to this style, from readability in code to editability for the template. Another thought I have is using OCaml instead of Perl as the language. OCaml has continuations, and we can certainly implement high-level DB and templating techniques there too. Perhaps all the pieces aren't in place yet... but lets imagine what it will look like once they are all in place. let personDetails person = let f = dispTemplate "personDetails.tpl" ("person", person) in match (Hashtbl.find f "action") with | "save" | _ -> saveRecord person f  This code would be even prettier if OCaml had a better hash syntax, like f{"action"} instead of Hashtbl.find f "action". But whatever. Here you can see that the actual code which makes up the controller aren't all that different between the two languages. I'd also make a template language which is identical to my current Embperl solution. It would be HTML (or whatever plaintext-based stuff you want) with two types of markup. [* ... ocaml code ... *] for raw code, and [+ expression +] for inserting the result of an expression. Though I suppose I'd have to take typing into account. grr. Which is why I'm doing it in Perl, not OCaml. Well. Though I am on some sort of a roll, typing-wise, I think it is best if I go to bed now. Besides, I might get carried away here and stay up all night... which would be fine if we weren't going to breakfast with the Kleizers and also visiting Beth's Grandma tomorrow. Doot do doo. Add Comment # TLT - 2004.07.29 Hanging out in Livermore, interviewing. Great fun. Free LAN at the hotel :) Mirabel is back! And the panel is in beta-testing and will soon be in production (for at least some of the modules). Everybody thank david. Add Comment # TLT - 2004.07.26 I'm very excited... I got my first module on CPAN, Contize I've also gained tons of ground on the EPFarms Panel. I've been very productive. Add Comment # TLT - 2004.07.19 (Extracted from an email to David) So I've been thinking about doing web programming using the new application-oriented technique (Contize). One thing that I have to deal with is breadcrumbs. In their current incarnation, and as they are used on most sites, breadcrumbs embrace the idea of state management, in addition to being useful navigation guides. What I've realized is that by clicking on a breadcrumb item you are in effect doing _two_ things. First you are canceling the current operation, and second you are returning to a previous state. I think that I will try to make it more apparent that this is happening. Imagine that you are in the accounting module, in a person's details, editing a transaction for that person. Your breadcrumb looks like:  Main -> Accounting -> User (awwaiid) -> Transaction (#1175) and you click on "Main". What I suggest is that this implies not just jumping to the main page, but also 'exit'ing all of intermediate stages. This is the whole 'goto considered harmful' thing I believe... instead of just doing a GOTO Main I want to do a 'exit until you get to main'. The implication is, however, that any of the intermediate stages of the exit could take control. They could, for example, prompt for a confirmation to cancel changes. If the user then chooses not to cancel then the request to exit to the Main area is ceased. Each intermediate stage doesn't really care that we want to go back to Main, rather they care that you want to exit them and they must take care of that request. As I've mentioned elsewhere... wrapping my head around this "simplified" method of web development is difficult and fun. Add Comment # TLT - 2004.07.15 I'm having a wonderful time with friends! Add Comment # TLT - 2004.07.14 Well Mirabel's harddrive went down a bit so we had to move all of her services to pointless. Not fun. But amazingly here I am... tlt is back up and running already (once DNS reaches you). I lost two pages but no real work (some stuff about Contize). David and I stayed up late last night moving things. Its probably not perfect but it seems to be a wonderful temporary solution. Good Comments on TLT - 2004.07.01 by Filmil. So PHP5 was released this morning, and after a very brief investigation I found that Contize can be implemented for it using the new __call method for objects... looks like it will have to be a proxy object thingie just like the perl one (intercepting method invocations, doing some magic caching, all that jazz). Pointless (machine we are using instead of Mirabel) is a slow but steady beast. We got just about everything running on it now. Looks like it's harddrive failure, so we will get a new one, reinstall here, and then send it to the colo, and they will put it in the box for us. They're quite nice. Add Comment # TLT - 2004.07.06 So I keep wanting a shorter domain name... but keep putting it off. Well today Beth's mom took beth@thelackthereof.org off of Beth's resume because it looked "unprofessional" so I've decided to bite the bullet. Here are some ideas: • tlt42.org • 42t.org • tao42.org Comments on TLT - 2004.07.06 ### 3 Comments. But I looovveeee TLT. Just get a more "professional" domain, go gmail, or something for those purposes. Sniffle. I'll cry for TLT and you change domains too damn often! :) -- mousetrout 2004-07-07 04:39 UTC Ohmygod someone left a comment! Of course it was mandie, who has done so before. eh. I won't change domains, thelackthereof.org will still be the domain and tlt42.org will be a re-direct and short mail address, just like sf.net. I'm looking for an alias for thelackthereof.org, not a replacement. -- awwaiid 2004-07-07 18:18 UTC Hmmm....I think I like "tlt42.org". At least it sounds cool. -Chris G. -- Anonymous 2004-07-09 20:02 UTC Add Comment # TLT - 2004.07.01 I posted this to http://perlmonks.org, but nobody seems to have read it. So I thought I'd put it here too. It was in the context of a discussion on breaking code into subroutines, http://www.perlmonks.org/index.pl?node_id=368279. There are many more reasons to separate code into subroutines (and modules) than what you have listed. In fact, it sounds like both of your points are actually the same thing -- the chunk of code in question is going to be called multiple times or somehow used in multiple ways (by "re-use" I'm guessing you mean in other projects... so perhaps describing that as being used in multiple ways is a stretch... but bear with me here). I believe that this might be the reason subs were invented in the first place, but very soon afterward the ancients became aware of yet another purpose for subs. Thus were discovered the offering of Organization and Structure to the Gods. A good program reads like a good book. A good book has a nicely structured table of contents, footnotes and references to other works, and references to other sections in the book itself (and a good index!). There is a certain balance to be struck when dealing with references, however. Too many and it will be a dry read with a footnote after every third word. Too few and some connections will be lost upon the reader. Sometimes, however, it is not appropriate to refer to other pieces of the book. It may not be appropriate to call some organizational subroutines in your code more than once. The table of contents is still very important, however, and breaking your big sub into many smaller subs (or even modules) will not only appease the gods, but it will also make your program a better read. Your big sub should become the table of contents, and reading the little subs you create from it is the text itself. I would say that a run-on subroutine suffers from the same disease as a book with no table-of-contents... something which no number of comments in the code can fix (unless of course the comments themselves break things into sections and lay them out like a table of contents... but as an ancient once said, "Do not say something in a comment which you can say clearly in code.") Comments on TLT - 2004.07.01 ### 3 Comments. I believe the word you are looking for is refactoring. Also may I point out that good code probably does not read as a good book, although it probably is readable. Take the example of Knuth's Literate programming. He thought that there are two sides to every code: the story of the program and the program itself. This is why he made a meta-language to describe both at the same time, and two programs to extract either one from the meta-description. The story of the program reads like a book. The program itself reads like a program. As they are obviously different, the program itself does not read like a book. Good code is readable but in a different way. -- filmil 2004-07-14 22:08 UTC Yes... you have a good point. Though I was replying to something (which I can't recall now) I think that I did draw the similarity between a book and code a little too closely. Maybe I could say that code should read like a good outline? -- awwaiid 2004-07-15 01:08 UTC I guess good code reads as — ah, well — good code, so think about a new readability type. Btw, a recent good read is Celestia. It's amazing to see how such a convoluted thing can be read so easily. Thumbs up for the authors. -- filmil 2004-07-15 19:14 UTC Add Comment # TLT - 2004.06.22 Well openratings reimbursed me for my plane flight and car rental, which was nice of them (though a bit short of the 1200 rent I wouldn't mind them covering). I have leads with VMWare, LLNL, and maybe Novell... in addition to a bunch of other applications. So things on that front are going pretty well. I need to pop over and see Rena (and Mario! and Carlos!) but I keep getting distracted. She is probably pretty busy anyway though. Comments on TLT - 2004.06.22 ### 1 Comments. Brock, if you're serious about coming back to California...I'm sure Jean would bend over backwards to help find you a job at LLNL. In case you have not been in contact with her lately, you should drop her a line...just to check in. -Chris G. -- Anonymous 2004-07-09 19:56 UTC Add Comment # TLT - 2004.06.17 And here I am back in Tempe. Job hunting. Add Comment # TLT - 2004.06.13 Well the abort-mission was really fast. I am now in Beth's house in Tempe, using the wireless her dad installed for me. I'm feeling a lot better... not so angry anymore. My job search continues. I will miss 59 Bacon though! Add Comment # TLT - 2004.06.10 Well... bad news. I had to abort the mission here in Boston. Yesterday Giorgos called me and said that they will no longer be hiring me. This was quite shocking of course (I'm still in shock a day later)... but it had very serious implications about my ability to maintain financial stability. My choices boiled down to two things -- either stay, Beth joining me, get a job as quickly as possible (which amost definately means a crappy job, same for beth), and make just enough money to pay rent and eat. Sustain. Perhaps I would find a better job than expected, or more likely I would continue looking for a good job while I worked at the crappy one. Second plan is to pull back completely, get out of my lease and go back to Tempe (Beth's parents' house) where we will be more financially stable and I could then begin searching again. Most likely I'd spread my search to be nationwide, or at least bigger than just-boston. A sub-part of this plan would be to stay at Rob&Patty's house and continue a job hunt locally... but this is nearly equivalent to going to Tempe except without Beth (and I miss her!). Actually it would also mean continuing to spread Beth and my finances between two locations. After talking to Beth and friends and family we decided to go for the second plan. Thus an abort-mission was called... I talked to Paul, my landlord, and he was very understanding and let me out of my lease. Beth is not going to fly out here on Saturday, instead she is going to get airline credit and I will fly back to Phoenix this weekend or next. I've already put myself back on the job market via Adam and Andrew (and am now re-subscribing to some jub hunt mailing lists). My reluctance to purchase a car seems to have paid off yet again.... no need to worry about that. I'm very very very VERY dissapointed... besides the slowness (and apparent financial instability) of Open Ratings, I was really looking forward to that job. It was a wonderful match for both of us and I sincerely hope that one day they realize what a great programmer they have now lost :). So what happened is this: They recently acquired Gentia (a similar company based in the UK). Gential's sales turn out to be a third of what they thought. So they transferred one of the programmers from that organization into the position I was going to fill. I technically had only a verbal agreement with them, so they dropped me. They've effectively cost me around 1500 cash and who knows what in lost time... and certainly some emotional trauma (Adam said he'd never heard me so angry). But I'm far from crushed. If any of you have a lead on a job for which I am applicable (I can do any type of programming there is, though of course there are some types which I am currently stronger with) let me know! Comments on TLT - 2004.06.10 ### 2 Comments. Rawr. Mad love, Rosebud. If I need to kick ass, I certainly will. :) I miss you, friend. If you need anything at all, particularly regarding the destruction of the universe, let me know. -- mousetrout 2004-06-10 21:57 UTC My god... someone used my comment system! I'm a happy duck! Of course it was just mandie... and she is the only one who had every used it before (that I can remember). Thanks mandie, I'll keep your offer in mind! -- awwaiid 2004-06-11 03:19 UTC Add Comment # TLT - 2004.06.07 Just had a lovely time on http://perlmonks.org/ reliving redneck moments while listening to BootLiquor (House Of Mercy Band - Sunny Georgia). Today I went with Judy to the harvard area. We ate and wandered and hung out and talked. Before that she came over here and saw our new place, which she liked. Very good day. Road the train/T and wandered around local Waltham a bit more. Still haven't gone to the library (will do that tomorrow). Oh, and while on perlmonks saw the greatest haiku:  Warm and humid night Hole in the screen; my cat and I - both chasing bugs. It's just beautiful. Add Comment # TLT - 2004.06.06 Moved in to 59 Bacon today -- discovered that a neighbor in a nearby house has open wireless :) The place has now been painted and cleaned and all the junk that was in here last time is gone... and now it is fantastic. It has a sun-roof in the bedroom and hardwood floors in parts and a dishwasher and a freaky-room and all sorts of things. And then to top it all off I discovered the wireless. I'm a happy duck! Add Comment # TLT - 2004.06.05 Yesterday went to Harvard with Patty and today went with Patty and Rob to the Aquarium. Both were nice little trips, and I got some photos (which I will put up someday). Oh, and yesterday we went by 59 Bacon and I got some [http://www.washingtonpost.com/wp-dyn/articles/A18948-2004Jun5.html Man smashes town with homade tank is a great article. Basically this guy lived in a small town and was mad at a bunch of people. This was mostly due to a zoning issue -- they built a concrete plant accross the street from his small business against his vote. So a few years later he had lost his business, was in significant debt, and then his house burned down taking his snowmobile with it... he just snapped. Fortunately for him he happened to have a bunch of metal plating and a 53-ton Caterpillar D9 bulldozer... he put two and two together and got a tank. Then he drove through the cement factory, through city hall, completely leveled the newspaper building, and finally smashed into the department store. The department store had a basement or something which the front end of his tank fell into, getting him stuck. That was 4:30 on Friday... cops worked all night with welders and small explosives to open the tank and when they finally did it appears he had commited suicide. A sad end to a sad day. Adam set me up on lj as a syndication! See (or add) http://www.livejournal.com/users/tlt_feed/. Add Comment # TLT - 2004.06.02 Just spent the afternoon wandering down to the Tatnuck Bookseller, about two miles away. Pretty nice place... though no free wireless. I think they had paid wireless. Don't know enough to hack it... looked like a borked IP grabbing trick. So today is Wednesday... then Thurs, Fri, Sat, then I move in to my new place, then I start my new job. It's getting close. Worked on SetDB while I was there. Finished up my graph module integration which clarified the code quite a bit. Now I need to clean some other existing code. I'm working on adds... I had them going once but only simple ones. I think I know how to do complex adds now. Then I will go back to EPFarms Panel development and perhaps write a SetDB::WebWidget module... this would act like the dbform stuff I did for PHP. Except better. Add Comment # TLT - 2004.05.30 Signed the paperwork and everything looks good. I'll move in next Sunday. I'm looking forward to our life at 59 Bacon :) Comments on TLT - 2004.05.30 ### 1 Comments. Nobody ever comments or adds to any of my pages :( Maybe nobody is out there? -- awwaiid 2004-06-01 21:30 UTC Add Comment # TLT - 2004.05.29 I had a great idea today. Remember Quantum Leap? Well... I think that all of the shows that are on now, everything from malcom in the middle to The Sopranos to The Simpsons, should have a special 'Quantum Leap' episode in which one of the main characters gets leapt-into! Rob and I went to Waltham (pronounced wall-thahm (ah like apple)) today looking for apartments for me and Beth. They were all pretty expensive and none of them had any immediate openings for what we wanted. But then we were driving down one street and saw a house with a rent sign. One of those houses where there are multiple apartments in the place. Well I went ahead and called and it was within the price range and bigger (two-bedroom) than I expected. So Rob and I got the guy to meet us there and took a tour. It is no fun to take a tour of a place when there are already people living there... especially when they are moving out so their stuff is all over the place. The place has a lot of character in that it is quite maze-like. This is a plus in my eyes. Maybe I'll draw you a diagram later. The whole place is 3 stories high, and our apartment would be spread accross the 2nd and 3rd stories -- I imagine taking up one side of the building or so. In fact I'm trying to even picture it now and I can't quite descibe it. Well in any case the kitchen, living room, and a bathroom are on the 2nd floor. Then above that, on the third floor, is two bedrooms, another bathroom, and a strange sort of storage room. The place seemd a bit on the worn side, but I think that impression was at least partialy due to the current occupants. Well, that was the best place we found so we're going to take it. Tomorrow afternoon Rob'll take me over and I'll sign paperwork and give him a last-month deposit. He is going to re-paint the place this week and I'll move in next weekend. I start work that week and hopefully Beth will join me the following weekend. Exciting! Add Comment # TLT - 2004.05.28 Well I got the job at http://openratings.com/ -- a very good thing since now I can actually be here permanently and have beth and the rabbit come out and all that. I'm VERY HAPPY! I went in earlier today and talked to Dima, looked around the place and all that. They should send out the official offer letter soon, and I should start on June 7th. Happy days! Now I can spend the next week doing nothing and enjoying it. Well... finding a place to live and a way to get to work and all that. But still. I can already feel myself typing faster. Add Comment # TLT - 2004.05.27 The new battery that Chris bought me as a graduation present came yesterday. It is slightly bigger than I expected (2600mAh instead of the 1400mAh which I had before). I charged it up all night and then tested it this morning. I ran at full LCD brightness and a pretty steady 25% CPU load from fully charged to completely dead (I let Jill die). I began the test at 6:13 and the battery died at 8:28... 2 hours and 15 minutes. This is WAY better than I imagined! Once it is charged up again I'm going to do a low-brightness and low-cpu test. Oh, and the USB netgear MA111 wireless card which I got to work is randomly making the machine lock up when switching from wall-power to battery-power (unrelated to the new battery). 13:11 I wish I could tell how much a specific device drains the batter. I am wondering if I should run my test with the USB-wireless disconnected. Hmm. 21:49 And here I am outside of Rob & Patty's house. This battery lasts almost 3 hours under normal usage is my conclusion. I'm a happy duck! I talked to Dima and I am going in tomorrow afternoon to talk about an offer they will give me. Very good news. Add Comment # TLT - 2004.05.25 Deep Thoughts of the day: What will they call paperwork when there is no more paper? Finally communicated with Dima today. Said he would be able to tell me something difinitive on Friday. Good news... having a timeline is good. Hopefully he will hire me and then Beth can come out and we can get going. I feel like I'm in purgatory... hard to do since the Catholics threw it out. Everything Zen. I'm trying out the EditCSS extension for FireFox and would ust like to say that IT ROCKS. Oh... and this is the 42nd TLT-wiki entry! It's a magical day! Add Comment # TLT - 2004.05.24 Here is today's JAPH: /='}"6ft.(&^)+@<B#,/JK2=>?@7eJp.'," =eval/,@/=split//,/.@,/=0;while(/ <26){_.=/[ord(/[++/])-7]}print  I am very pleased about it. Probably version-dependent... its trick is to use Perl's error messages as data to transform. Add Comment # TLT - 2004.05.22 Today was OK. Hung out with Rob which was nice. But I miss Beth. Add Comment # TLT - 2004.05.19 Heard back from Dima - he says it is crazy around there and he will hopefully be able to tell me (tell me when I can come meet, I assume) on Friday. Though perhaps he meant he can tell me if I have the job. Wouldn't that be nice? I've been applying for lots of Jobs... full customized cover letters and everything. I'm very tired of it. I miss Beth. I'm lonely without her, even though I have people here to hang out with. Lightyears away from being the same as having Beth. :( Add Comment # TLT - 2004.05.17 Today is Beth and my 1-year anniversary! Sort of sad since we aren't together today... but we will be together soon and celebrate :) No word back from Dima yet... I hope to interview ASAP so that this can be final (one way or another). Today I'm hitting the job applications extra hard as a backup plan. As Rena or Adam or someone said... its easier to not have a job or have a job than to be looking for a job. While I was searchng I ran accross the Worcester Computer Co-Op (http://www.worcestercoop.org/index.html) which I think is super-cool. If I ended up around here I would definately donate some time there. They even use debian :) So there is a post on Craig's list, http://boston.craigslist.org/eng/31160135.html, and I am trying to decide whether it is serious or not. Its for a web developer -- PHP expert and knows lots of other things like C++. Then it says "The job is full-time. You’ll spend approximately 20 to 30 hours a week as a developer and the remainder of your time filling out other critical roles within the organization: mail room, running errands, answering phones, light cleaning, etc." hmmm.... Add Comment # TLT - 2004.05.15 I'm having great fun with the Graph Module. Now I can do things like this. Which is probably more fun than you imagine. Unfortunately this particular flow chart has not yet come to fruition. I have another part of the interview next week, I think with Stan but I'm not sure. I've continued to apply at other places but so far nobody is jumping out of the dark corners begging me to come work for them. Yet. Its very nice here. Green and slightly humid. You should join me. Add Comment # TLT - 2004.05.10 Well, I'm in Worcester (at Beth's Brother's house), MA. Its beautiful here. Tons of green. My flight was uneventful, so generally good. Kinda mad at travelocity since they let me choose which seat I wanted for the flight when reserving the ticket, but then I got a completely different seat on check-in. Rob (aka Bob) and Patty picked me up at the Boston airport. Went by shuttle then by subway to downtown Boston. Patty does not like subways. From there we walked to the car and drove the scenic route along highway (route, road, whatever) 9. Like I said, tons of green. They live in a two-story condo, two bedrooms and two bathrooms on the bottom, livingroom, den, kitchen on the top. Worcester is a little more spread out than Boston itself, but we are in a spot where we can walk to a few things. Today I walked for 45 minutes to a bookstore, where I bought a Dan Brown book (not to be confused with [[Dan_Bern?]]), Digital Fortress, ISBN 0312263120 (alternate, search), which is good so far. The real exciting stuff starts tomorrow. I will pick up a rental car early in the morning, and then my interview for http://openratings.com is at 2pm. I must also add that I'm renting from Budget Rent A Car. All the others wouldn't rent to me. Dan Bern was right! I miss Beth, and she misses me... but we haven been talking to each other regularly so it is going good so far. I look forward to her joining me though. Add Comment # TLT - 2004.05.05 Here is a nice quote I picked up from http://www.bagley.org/~doug/ocaml/Notes/okoans.shtml. Michel Mauny was giving a guest lecture to new computer science students. After the students were seated, Michel pronounced "Today's lecture will be about Lazy Evaluation", he paused for a moment then concluded with, "Are there any questions?" Add Comment # TLT - 2004.05.04 If you've ever wondered about Fedora (the Redhat derivative), Adam found the perfect explaination: http://www.redhat.com/archives/fedora-devel-list/2004-May/msg00104.html I'm studying for my Buddha test. Liz asked me what sort of religious or spiritual beliefs I have, especially in regard to Buddhism and Taoism. I started to explain a bit and inadvertently came up with a new concept of 'soul' -- that souls are really just a person's [[Gravitons?]]. Adam encouraged me a bit. So now I'm developing a new philo-religion based on this concept. See Gravitonism. Add Comment # TLT - 2004.05.01 Well I set Jill up to be my primary computer and turned off Feline. All part of getting ready for the move. So now that I have no music I decided to turn KJACK into my personal jukebox (thank god for VNC). Got a bunch of boxes for books, so we're almost done with that. Liz is visiting. She and Jason are fighting but she has a bunch of schoolwork to do so she stole his car and came up here. Adam will be here soon to visit (for the week pretty much). We are going to hike the canyon a bit on Monday together, which I'm looking forward to. The most important things that I have left are: Abstract Algebra Test. Abstract Algebra Essay. Abstract Algebra Homework. Human Rights Research. Light study for Buddha test. Study for Math History test. Not bad. Add Comment # TLT - 2004.04.30 This is a partial journal page test. -- cut -- And this should not be displayed on the summary (journal) page! Add Comment # TLT - 2004.04.27 If you want a few minutes of fun, go to froogle.com Now hit refresh. Then hit it again. and again. As you hit refresh be awed by the list "A few of the items recently found with Froogle:" ... it is amazing what people are looking for. Add Comment # TLT - 2004.04.26 http://magnatune.com/ - "We're a record label. But we're not evil." I like their motto. Add Comment # TLT - 2004.04.21 So I got a response back from Dmitry (Dima) from http://openratings.com. He asked me to solve a little problem so he could get a feel for my background -- decide whether a given datastructure is a proper BST (Binary Search Tree). He preferred C but said another language would be OK. So here is my solution in C and here is my version written in OCaml. The OCaml version took me all of 5 minutes (if that), but the C version took me longer to get all my pointers and such correct... I guess if you don't use it you lose it. Feedback is welcome. I am quite rusty on my C! Add Comment # TLT - 2004.04.18 And who says perl error messages are not accurate?  Time::HiRes::sleep(-0.185915): negative time not invented yet So today I am still working on my math test (and a Buddha essay too, actually). It's kind of stressfull because I'm not quite halfway done yet and am additionally feeling kind of ill. But I trudge on! Talked to the Principal Software Engineer over at Open Ratings about their "Data Processing Algorithm Developer" position. I'm really excited about it because I'd get to do one of my favorite things -- develop algorithms and APIs the way that should be done. I might even fly out there for an interview soon. Oh My God. I just now decided I should learn more about the latest fad, "Aspect Oriented Programming" (AOP). I started with  http://www.onjava.com/pub/a/onjava/2004/01/14/aop.html which seems like a reasonable introduction. Let me give you a summary... AOP is a giant HACK (and not in a [[Right_Thing?]] sort of way). They invent some vocabulary which, so far as I can tell at this point, inserts hooks into pre-existing code. That way you can run some new code at the entrance or exit of a method... or insert a new initializer or destructor. Again, from what I understand, it does this at the JVM level (for java, anyway) so that you can do this in pre-compiled code if you so desire. The argument for AOP is that you can add orthogonol functionality to programs transparently. In the article above, for example, they mention being able to add a nice logging facility to existing code. The code itself shouldn't have to deal with logging as that is not its purpose, so they create these sort of hooks to add that functionality whithout cluttering code. Such functionality could also be added in a matter of minutes instead of the hours it might take to insert this code into the actual flow. I would now like to take this time to say that THIS IS THE STUPIDEST THING OF WHICH I HAVE EVER HEARD! I cannot imagine that this could possibly lead to better programs... instead I imagine programs which become harder and harder to follow and understand and debug. Harder then spreadsheets even! This is simply a very very bad idea. If there is anyone out there who can shed some light on why anyone might actually want to use this evil crap please let me know! I am very curious! Add Comment # TLT - 2004.04.14 Before I forget... the coolest thing I've learned in my math history class is that$$\sin\left(\frac{\pi}{2} - \ln(\sqrt{3} + 2) \cdot i\right) = 2$\$.

Please see for yourself on your TI-89 (and I'm sure others... I tried the 83+ and it couldn't hang with the complex input to sin).

I'm working on a take-home mathtest. Notes and the test. Fun stuff, eh?

# TLT - 2004.04.05

This is a great article which brings to mind several important and good thoughts. John Gruber

There’s an old engineering adage: “Fast, good, cheap: pick two.” (Where “fast” regards development time, not performance.) Desktop Linux software is cheap (free) and fast (release early, release often), but it’s not good.

Or, perhaps one could argue that it is cheap, and eventually it’s going to be good, but it’s getting there very slowly.

# TLT - 2004.04.02

I think I've finally figured out how to get a 'recent songs' list for http://www.kjack.org/.

The software they use doesn't have this feature, but it does have an error log which will mention what file name was just played. Unfortunately this filename is something like MUS00032.MTS, which scary and says nothing about the artist or anything.

Fortunately these files are mp3s.

Unfortunately they do not have id3 tags.

Fortunately I found their DB which stores the translation guide -- the artist and title to the filename.

Unfortunately it is a proprietary format.

Fortunately I can read it without too much trouble.

Unfortunately all this crap is on the wrong computer

And finally -- the breakthrough that I just realized -- I am fortunate enough to completely control the server now. Which means that I can do such whacky things as mount samba shares! So all I have to do is share the right couple spots of the drive over samba and then I can have a script rip out the appropriate bits from the two files. Neato, eh?

# TLT - 2004.04.01

It's raining... smells so nice.

Beth is gone already and I will be joining her tomorrow. Mike is back from Iraq and we are going to Phoenix to visit him and welcome him home.

I think I'll do some meditation and then go to bed. Long day tomorrow.

# TLT - 2004.03.30

Happy Birthday, Chris!

We (Brock, Beth, David) are over at Chris' to sing happy birthday and watch "The OS Revolution." Wireless in the kitchen.

# TLT - 2004.03.25

Here is a lovely document: Microsoft on OpenOffice.

# TLT - 2004.03.24

Snow Path Formation Simulator 0.5.2 (Default) by Matthew Strait<br>
Snow Path Formation Simulator is a program that models the process of people forming very distinct, and yet not always altogether logical looking, paths in the snow as they walk across open spaces. The evolving condition of the snow is displayed graphically. This project may eventually mature into a screensaver.

(Emphasis added). I should put that last line at the end of all of my projects!

# TLT - 2004.03.23

http://news.bbc.co.uk/2/hi/americas/3561165.stm

Sheesh.

12:32

Just got back from my Women's Studies (WST) course. Very depressing. We talked about "comfort women" in Japan... Korean and other women who were sex slaves to the men on the front line (against their will). Not to say that Japan is the only ones to do this, of course. We watched a movie which turned my stomache.

20:51

We went to the store and got food stuff. While there I saw one of those lighters with the long necks and decided to get it... we have candels which end up being pretty deep and it would be easier with such a tool.

But then when we got home and I tried it out I realized that I had purchased a flame thrower! I think this is an anti-wind thing, but it is pressurized and makes a hissing sound as it wooshes the flame to a sharp point several inches away from the tip of the lighter. It is very scary!

# TLT - 2004.03.21

I. Don't. Want. To. Go. To. School.

But I will anyway. Tomorrow.

# TLT - 2004.03.20

Only one more day of spring break remains :(

# TLT - 2004.03.19

Today was the 1-year anniversary of the Iraq Invasion.

Lets do a compare and contrast excercise. See the following two articles:

The most interesting thing is that Bush focuses on all of the terrorism that we've stopped by invading Iraq. He has also taken to using the word "Killers" instead of terrorists, especially when speaking about the recent bombing in Spain. They way he words it one might conclude that the world's center of terrorism was Iraq (which is false).

Kerry, on the other hand, is backpeddeling. He voted for the war and now he is trying to get out of it...

“He misled the American people in his own State of the Union Address about Saddam’s nuclear program and WMD’s, and refused – and continues to refuse – to level with the American people about the cost of the war. Simply put, this President didn't tell the truth about the war for the beginning. And our country is paying the price."

This does not redeem his vote in my mind, however. It seems like it was a bad idea even when we were being misinformed.

00:12

Well spring break is almost over. Very sad... I've been enjoying my freedom. The senioritus bug is niblling at my toes (though i'm trying very hard to beat it back) and I am looking forward to taking a break from school. After 18 years (if you include kindergarten) I think I deserve a bit of a break.

But school is not over yet. So tomorrow my plan is to go over all my books and study a bit. Make sure I don't have any homework due and such. Productive like. We're also going to go see a movie I think... probably just Beth and I which will be nice.

I added a pingback module for oddmuse (see OddMuse Pingback) which is fun and all but now I realize that nobody uses pingback. They hardly use trakback. How sad... they are such good technologies. *sigh*

Time for bed!

# TLT - 2004.03.18

I added a new module for the wiki which tells how many comments have been made on a page. It works by adding text to the actual comments_on_ page and then parsing this. I should, perhaps, be using the actual storage of a page or something for speed... but this seems fast enough to me.

I should make sure it works for journal listings...

It does! Woo Hoo!

This is a comment-on-journalpages test!

-- awwaiid 2004-03-19 00:06 UTC

# TLT - 2004.03.17

I think I'm lactose intolerant.

More...

2018-11-15

2018-11-10

2018-11-04

2018-10-27

2018-07-02

2018-06-30

2018-11-20

2018-11-17

2018-11-13

... more changes