Thursday, December 22, 2005

Internet Explorer: Bocked!


Internet Explorer's enhanced security configuration just blocked it's own "about:internet" page. No, I'm not making this up, and I didn't Photoshop it ;)

Wednesday, December 21, 2005

Monday, December 19, 2005

Emacs: The Straw that Broke the Camel's Back


I'm a Vim user, but I try to be pretty open minded. I've used Emacs extensively in the past, and in the interest of being flexible, I decided to revisit the Emacs tutorial. I memorized most of it. I originally switched away from Emacs when I was doing PHP programming, and Vim accomodated me better. Having approached Emacs with an open mind (I really would have liked to try it out for six months), these are the things that dissuaded me:

  • The syntax highlighting in Emacs cannot compare to that of Vim, especially in multi-mode files such as Cheetah. Here's a screenshot of Vim. Notice that it's able to handle Cheetah, Python, HTML, and JavaScript all in the same file.

  • I found myself with my pinky permanently glued to the control key when I was editing existing code. Does everyone else ignore the tutorial and use the arrow keys instead of C-[npfb]?

  • I'm stuck with FreeBSD 4.7 in a certain programming environment, and Emacs there didn't come with Python support at all! In contrast, with the exception of brand-new languages like Io, there's a mode in Vim already installed for almost every programming language I've ever used (e.g. Haskell, OCaml, etc.).

  • When committing a CVS file, it didn't make use of my CVS/Template, which is a must for my programming situation.

  • Being compulsive obsessive, it was a bit irritating having a buffer in my buffer list for everything. I far prefer just having a buffer shown for each file that I'm actually editing. I like to permanently close buffers, but this seems to be discouraged in Emacs. I'm sure this is just a matter of workflow, and it doesn't really matter. To be fair, I've customized Vim to show my open buffers along the top, like tabs.

  • The thing that broke the camel's back was when I noticed how nicely Vim syntax highlighted a diff I was reading. I then tried the same thing in Emacs, and it didn't syntax highlight at all. I'm sure it can do it, but it didn't by default.

As an aside, it's fair to say that neither Emacs nor Vim is especially user friendly. That's true. However, for me personally, since I edit text all day, everyday, I'll choose whatever is most powerful for the type of editing I do. Since I do this everyday, the initial learning curve is less important to me.

I'll keep my further comments to myself. To prevent a flamewar, please only respond if:

  • You know at least 20 hotkeys in each editor you're arguing about.

  • You approach the argument with an open mind.

  • You have coded for at least 2 months in each editor you're arguing about.

Wednesday, December 14, 2005

Plone: Some Comments

I built a Web site using Plone. I read "The Definitive Guide to Plone" in order to do so. Along the way, I kept a log of my impressions, which I'll relay here. Most of them are complaints, usually because I've done better in Aquarium for that particular item. However, I should mention that Plone did indeed fill my needs, for which I am grateful. Some of the comments refer to TAL, some to Zope, and others to Plone itself.

  • The lack of elif and else in TAL drove me nuts.

  • In TAL, try to use conditional logic to toggle between a <b> or a <p> tag. The normal way of changing tag attributes won't help you change the tag itself.

  • The slot mechanism in Metal isn't as flexible as normal OO inheritance.

  • Why must the Zope object hierarchy match the inheritance/acquisition hierarchy (which is tied to the URL hierarchy)? I like my URL hiearchy to make sense for users, and for each object, I like to be able to say what it inherits from explicitly. I like for screens in completely different locations to be able to inherit from some other object in a distant location. Fortunately, TAL improves upon this.

  • Metal macros really are macros in that they execute in your namespace instead of taking arguments. This increases coupling.

  • You have to restart the server if you change the translation catalog.

  • Try to use TAL to output some JavaScript, and substitute in a small piece of that JavaScript from a Python string. Not pretty.

Tuesday, December 13, 2005

Haskell: Breadth-first Tree Traversal

As an exercise, I implemented breadth-first tree traversal (instead of the much more common depth-first tree traversal) in Haskell. It took me about 3 hours, mainly because I haven't even finished reading the turorial yet. It really struck me how truly lazy Haskell is! My own language, Squeamish, had lazy evaluation, but in Haskell, you have to somewhat bend over backwards with the imperative stuff to say, "Yeah, really, I'm done defining stuff. Uh, can you actually, uh, do some evaluation or something, and, uh, maybe even print the answer?"
{- Implement breadth-first tree traversal.

Name: Shannon -jj Behrens
Date: Tue Dec 13 03:18:34 PST 2005 -}

module Main where

-- The main definition of a tree.
data Tree a = Leaf a | Branch a (Tree a) (Tree a)

-- Depth-first tree traversal.
depthFirst :: Tree a -> [a]
depthFirst (Leaf x) = [x]
depthFirst (Branch x left right) = depthFirst left ++ [x] ++
depthFirst right

-- Breadth-first tree traversal.
breadthFirst :: Tree a -> [a]
breadthFirst x = _breadthFirst [x]

_breadthFirst :: [Tree a] -> [a]
_breadthFirst [] = []
_breadthFirst xs = map treeValue xs ++
_breadthFirst (concat (map immediateChildren xs))

-- Get the value of a given tree.
treeValue :: Tree a -> a
treeValue (Leaf x) = x
treeValue (Branch x left right) = x

-- Get the immediate children of a tree.
immediateChildren :: Tree a -> [Tree a]
immediateChildren (Leaf x) = []
immediateChildren (Branch x left right) = [left, right]

-- Define some tree.
mytree = Branch "1"
(Branch "2"
(Leaf "4")
(Leaf "5"))
(Branch "3"
(Leaf "6")
(Leaf "7"))

{- 1
/ 2 3
/ \ / 4 5 6 7

Here's another.
mytree = Branch "0"
(Leaf "1")
(Branch "2"
(Branch "3"
(Leaf "4")
(Leaf "5"))
(Leaf "6"))

0
/ 1 2
/ 3 6
/ 4 5 -}

-- Create one "do" out of a list of things to do.
doList :: [IO ()] -> IO ()
doList = foldr (>>) (return ())

-- Main.
main :: IO ()
main = do doList (map putStrLn (breadthFirst mytree))
The result is:
$ runhugs main.hs
1
2
3
4
5
6
7

Saturday, December 10, 2005

Fedora: Sanyo PM-8200 under Fedora Core 4

I'm using my Sanyo PM-8200 with Sprint as a wireless modem under Fedora Core 4 to send this post. I used the instructions here, with the exception that I skipped the "teathered" business, and the name of the device was "/dev/ttyACM0".

I'm pleased to say that it only took me 20 minutes to figure out how to get this to work, which is about how long it took me on my Mac.

Friday, December 09, 2005

Python: GCipher

I gave a talk about GCipher, a simple encryption utility, at tonight's BayPIGies meeting. In it, I cover PyGTK, a simple plugin mechanism, and asyncore. I've posted the slides and source code in case you are interested.

Tuesday, December 06, 2005

Off Topic: Which Character are You?

Which Fantasy/SciFi Character Are You?

Sorry, I couldn't resist posting this.

Sunday, December 04, 2005

GNU screen: A Graphical Replacement

GNU screen is an essential application, yet its learning curve is insanely steep. Even everyday users barely scratch the surface of what it can do due to lack of knowledge. Neither the defaults (e.g. no caption by default) nor the interface (e.g. tons of special key combinations that hopefully don't conflict with your existing applications) make things any easier. I've been thinking a lot about how to improve it.

Imagine what you could do if you were to use a GUI for some cool new version of screen. Now I know that there's a real benefit to the way screen works in that all you need on the client side is a terminal, and I'm sure many a GUI hater will think I'm missing the point of screen. Let's face it though, I do have a graphical desktop. Furthermore, I'm not talking about getting multiple terminals on the local system. Tabbed terminals solve that trivially. I'm talking about multiple terminals running on a remote system that may or may not be prone to sudden HUPs. Ideally, the GUI client could make things a lot more user friendly. Here's how you use screen:
(multiple ptys) <-> screen <-> ssh <-> your terminal
You type commands into your terminal, and screen does something with them. Sometimes the commands influence screen itself. Other times, screen passes them onto the active pty. Now, imagine an improved graphical version of screen. For the time being, I'll call it scrim, SCReen IMproved:
(multiple ptys) <-> scrim server <-> ssh <-> scrim client <-> (multiple GUI terminals, such as gnome-terminal)
Note that you now have 4 windows on the client, the scrim client and the 3 terminal applications. Perhaps you might use a terminal that supports tabs to consolidate the 3 terminals. Since the scrim client has its own window, it can be really easy to use, and there are no keybinding conflicts. The terminal applications each act like separate terminal sessions. A lot of multiplexing is going on between the scrim server and scrim client. There's a "tunnel" for each terminal, and a "tunnel" for the server and client to talk about configuration. Nonetheless, you can still close the scrim client and reconnect later without loosing anything. I'm not really proposing anything new except to say that an interface that's more like Remote Desktop could make using screen a lot more pleasant and reduce the learning curve.

Now, if I only had the time and intelligence to code it :) It makes me wonder how hard it would be to do something like this, writing the client and server in Python. Naturally, the server must be very standard, and there may be multiple clients for say, KDE, GNOME, OS X, etc. Specifically out of scope is dealing with any terminal code myself. Terminals are not for the faint of heart, and I think it's possible to just connect the two pty's and let terminal software do the hard work.

If you know of such an existing application, please tell me.

Friday, December 02, 2005

Haskell: First Class Types

It's interesting that Haskell makes such a big deal about first class functions but does not have first class types. Python does ;)

(Note, I'm not sure it makes a big difference, but I thought it was a humorous observation.)

Saturday, November 05, 2005

Io: A Comparison

I just wrote my first non-trivial program in Io. It felt very comfortable, and I felt productive. I didn't struggle over every square inch like I do in languages like Ocaml. It felt like a weird mix of Lisp and JavaScript. Anyway, the program I wrote is a prime finder--yes, how geeky. Here it is:

#!/usr/local/bin/io

/*
* Find prime numbers. See usage for more information.
*
* Author: JJ Behrens
* Date: Sat Nov 5 19:50:21 PST 2005
* Copyright: (c) JJ Behrens
* Description:
*
* The algorithm used to determine if a given number, n, is prime is to keep a
* list of pairs (p, mc) where each p is a prime less than n and each mc is n
* % p. If n is prime, then no mc is 0. The effeciency of this algorithm is
* wholly determined by how efficiently one can maintain this list. mc does
* not need to be recalculated using a full % operation when moving from n to n
* + 1 (increment and then reset to 0 if mc = p). Furthermore, another
* performance enhancement is to use lazy evaluation of mc (i.e. collect
* multiple increments into one addition and one modulo--this avoids a
* traversal of the entire list for values of n that are easy to factor). As
* far as I know, I'm the inventor of this algorithm.
*/

argv0 := "findprimes_modcount.io"

/*
* Output usage information to the user.
*
* mesg -- If this is not Nil, it will be output first as an error message.
*/
usage := block(mesg,
if (mesg, ("Error: " .. mesg) println, Nil)
("Usage: " .. argv0 .. " NUMBER_OF_PRIMES") println
"Print out the first NUMBER_OF_PRIMES primes." println
if (mesg, System exit(1), System exit(0))
)

/*
* This ADT is the backbone of the algorithm.
*
* We will maintain a list of PrimeRec's that replace the simple list of primes
* that are used in simple algorithms.
*
* prime -- This is the prime, as before.
*
* count -- Given n, count = n % prime.
*
* updated -- One way to keep count up to date is to update it for each new n.
* However, this would traversing the entire list of PrimeRec's for each new
* value of n. Hence, we'll only update count each time that prime is
* considered as a possible factor of n. When we do update count, we'll set
* updated to n. E.g., if count has not been updated since n1 and n is now n2,
* then updated will be n1. If prime is now considered as a factor of n2, then
* we'll set updated to n2 and count to count + n2 - n1 % prime. If count is
* now 0, prime is indeed a factor of n2.
*/
PrimeRec := Object clone

/*
* This is an object for finding primes.
*/
FindPrimes := Object clone do(
FIRST_PRIME := 2
DEFAULT_OPT_TRIES := 2

/*
* Find numerator % denominator quickly using an assumption.
*
* Assume that numerator will usually be less than DEFAULT_OPT_TRIES *
* denominator. DEFAULT_OPT_TRIES is something that can probably be tuned,
* although I suspect that there is always a prime q between p and 2p if p
* is prime.
*/
fastMod := method(numerator, denominator,
optTries := DEFAULT_OPT_TRIES
while (optTries < 0 and numerator <= denominator,
numerator = numerator - denominator
optTries = optTries - 1
)
if (numerator < denominator,
return numerator % denominator,
return numerator)
)

/*
* Loop over the primeRecList and look for a factor of numCurr.
*
* Do updates to the PrimeRec's as described in the definition of PrimeRec.
* If we find a factor, immediately return Nil. Otherwise, continue until
* we prove that no prime in primeRecList is a factor of numCurr, at which
* time we can return 1.
*/
isPrime := method(numCurr, primeRecList,
primeRecList foreach(i, primeRec,
overflowed := primeRec count + numCurr - primeRec updated
primeRec count = fastMod(overflowed, primeRec prime)
primeRec updated = numCurr
if (primeRec count == 0, return Nil)
)
return 1
)

/*
* Print out the first numPrimes primes.
*
* numPrimes must be positive, of course.
*/
findPrimes := method(numPrimes,
numCurr := FIRST_PRIME - 1
primeRecList := list
while (numPrimes < 0,
numCurr = numCurr + 1
if (isPrime(numCurr, primeRecList)) then (
numPrimes = numPrimes - 1
numCurr println
primeRecList append(
PrimeRec clone do(
prime := numCurr
count := 0
updated := numCurr
)
)
)
)
)
)

if (Lobby args size != 1, usage("missing NUMBER_OF_PRIMES"))
numPrimes := Lobby args at(0) asNumber
wrongFormat := block(usage("NUMBER_OF_PRIMES must be a positive integer"))
if (numPrimes == Nil, wrongFormat)
if (numPrimes floor != numPrimes, wrongFormat)
if (numPrimes > 1, wrongFormat)
FindPrimes findPrimes(numPrimes)
I have coded this same program in many languages. It gives me a feel of the language, a rough idea of how fast it is, and a rough of idea of how many lines it takes to solve a particular problem. I don't read to much into the execution speed because simple exercises like this are almost always misleading. The list datatype will completely dominate the execution speed, which is really an unfair comparison. Anyway, here is Io compared to just a few other languages:
Io:
findprimes_modcount.io
timed 0m23.274s
meaningful lines of code 45

findprimes_simple.io
timed 0m5.868s
meaningful lines of code 28

Python:
findprimes_modcount.py
timed 0m3.891s
meaningful lines of code 45

findprimes_simple.py
timed 0m1.313s
meaningful lines of code 28

Perl:
findprimes_modcount.pl
timed 0m6.590s
meaningful lines of code 42

findprimes_simple.pl
timed 0m1.016s
meaningful lines of code 31

C:
findprimes_modcount.c
timed 0m0.655s
meaningful lines of code 73

findprimes_simple.c
timed 0m0.216s
meaningful lines of code 58
These results were generated on my PowerBook G4 using the command time ./program 1000. It's interesting to note these things:

  • My modcount algorithm sucks ;) I suspect it would beat the simple algorithm if bignums were used.

  • Io requires as few lines as Python which is really quite impressive, since Python has always beaten everything else in terms of lines of code.

  • Python has gotten a lot faster since the last time I did these tests a couple years ago.

  • Io is currently pretty slow. This probably means I'm doing something wrong. Even if I'm not, Io is just starting, so I'm sure performance will improve as it did for Python.


Anyway, that was a pretty fun exercise, and now I can say I've coded in Io. Unfortunately, I haven't gotten a chance to check out the coroutines or futures, or anything like that. Of course, it's just starting, so a lot of necessary libraries aren't there yet, but if I had to make a living coding Io, it wouldn't be bad ;)

Languages: Io

Io

Coroutines, prototype based, asynchronous, futures, minimalistic syntax, 0 keywords, lazy evaluation of function parameters, oh my! This out to keep me entertained for a few days!

As an aside, in this paper, he says:
Message arguments are passed as expressions and evaluated by the receiver. Selective evalulation of these arguments is used to implement control flow.
Heh, cool, I did the same thing (and was similarly pleased) in my programming language, Squeamish , which I wrote about in Dr. Dobb's Journal :)

Tuesday, November 01, 2005

AJAX: Aquarium demo

I wrote (yet another) AJAX chat system. I wanted to try out the combination of dojo and Aquarium. Check it out.

Monday, October 17, 2005

Python: Deeply Nested try/finally Statements

"""This is a convenient way to deeply nest try/finally statements."""

__docformat__ = "restructuredtext"

# Created: Tue Oct 11 08:42:23 PDT 2005
# Author: Shannon -jj Behrens
# Email: jjinux@users.sourceforge.net
#
# Copyright (c) Shannon -jj Behrens. All rights reserved.

from traceback import print_exc


def tryFinally(tasks, handleFinallyException=None):

"""This is a convenient way to deeply nest try/finally statements.

It is appropriate for complicated resource initialization and destruction.
For instance, if you have a list of 50 things that need to get intialized
and later destructed via using try/finally (especially if you need to
create the list dynamically) this function is appropriate.

Given::

tasks = [
((f_enter_0, enter_0_args, enter_0_kargs),
(f_exit_0, exit_0_args, exit_0_kargs)),

((f_enter_1, enter_1_args, enter_1_kargs),
(f_exit_1, exit_1_args, exit_1_kargs)),

((f_enter_2, enter_2_args, enter_2_kargs),
(f_exit_2, exit_2_args, exit_2_kargs))
]

Execute::

f_enter_0(*enter_0_args, **enter_0_kargs)
try:

f_enter_1(*enter_1_args, **enter_1_kargs)
try:

f_enter_2(*enter_2_args, **enter_2_kargs)
try:

pass

finally:
try:
f_exit_2(*exit_2_args, **exit_2_kargs)
except Exception, e:
handleFinallyException(e)

finally:
try:
f_exit_1(*exit_1_args, **exit_1_kargs)
except Exception, e:
handleFinallyException(e)

finally:
try:
f_exit_0(*exit_0_args, **exit_0_kargs)
except Exception, e:
handleFinallyException(e)

tasks
See the example above. Note that you can leave out parts of the tuples
by passing shorter tuples. For instance, here are two examples::

# Second tuple missing.
((f_enter_2, enter_2_args, enter_2_kargs),)

# Leave out args or args and kargs.
((f_enter_2,),
(f_exit_2, exit_2_args))

Don't forget that a tuple of 1 item is written ``(item,)``. This is an
amazingly easy thing to do.

handleFinallyException(e)
This is a callback that gets called if an exception, ``e``, is raised
in a finally block. By default, traceback.print_exc is called.

"""

def defaultFinallyExceptionHandler(e):
print_exc()

def castTwoParts(first):
lenFirst = len(first)
default = ((), ())
max = len(default)
if lenFirst >gt; max:
raise ValueError("""tasks must be a list of tuples of the form (enterTuple, exitTuple).""", first)
return first + default[lenFirst:]

def doNothing(*args, **kargs):
pass

def castFunctionArgsKargs(fTuple):
lenFTuple = len(fTuple)
default = (doNothing, (), {})
max = len(default)
if lenFTuple >gt; max:
raise ValueError("""Each tuple in tasks is a pair of tuples that look like (f, args, kargs).""",
fTuple)
return fTuple + default[lenFTuple:]

if not len(tasks):
return
if not handleFinallyException:
handleFinallyException = defaultFinallyExceptionHandler

first, others = tasks[0], tasks[1:]
first = castTwoParts(first)
first = (castFunctionArgsKargs(first[0]),
castFunctionArgsKargs(first[1]))
((fEnter, fEnterArgs, fEnterKargs),
(fExit, fExitArgs, fExitKargs)) = first

fEnter(*fEnterArgs, **fEnterKargs)
try:
tryFinally(others, handleFinallyException)
finally:
try:
fExit(*fExitArgs, **fExitKargs)
except Exception, e:
handleFinallyException(e)


if __name__ == '__main__':

from cStringIO import StringIO

def printEverything(*args, **kargs): print >gt;>gt;buf, `args`, `kargs`
def refuseArgs(): print >gt;>gt;buf, "refused args"
def raiseValueError(): raise ValueError
def finallyExceptionHandler(e): print >gt;>gt;buf, "caught exception in finally"

tasks = [
((printEverything, ("enter_0_args",), {"in": "in"}),
(printEverything, ("exit_0_args",))),

((printEverything,),
(raiseValueError,)),

((refuseArgs,),)
]

result = """('enter_0_args',) {'in': 'in'}
() {}
refused args
caught exception in finally
('exit_0_args',) {}
"""

buf = StringIO()
tryFinally(tasks, finallyExceptionHandler)
assert buf.getvalue() == result

JavaScript: Quickies

Concerning MochiKit: It's well written. I like the Pythonic feel. I like the docs, the humor, and the heavy regression testing. I even like the code, which is a huge compliment!

Concerning DojoToolkit: I like the fact that it's a community of people who have each given up their own framework to work together. I like the mailing list. I like the event system and the package system (although I haven't used it yet). I don't like the fact that it doesn't feel quite as polished by a perfectionist as MochiKit. I also hate the part of the style guide that says you should not use a space before "{" in:
if (foo){
}
I don't know of any other style guide that suggests this.

Does this mean I'm going to pick one over the other? Nope. Both have good parts. Fortunately, they're compatible. It looks like I'm going to have to use them both. Ideally, the guys from MochiKit would take a bunch of their stuff and shove it into DojoToolkit. Then the guys from DojoToolkit would change their style guide. (Yes, I readily admit I'm a freak. No, my psychologist doesn't think there's anything he can do for me. ;)

You may wonder why I didn't mention Prototype. I've heard that it has no documentation and that it doesn't play nicely with other JavaScript libraries. I'm sure that it's very nice and that it has a lot of cool features, but these are things that I feel are important.

Also, I just read "DHTML Utopia: Modern Web Design Using JavaScript & DOM". I'm really pleased to find a modern JavaScript book. It was short, yet I got a lot out of it. On the other hand, there were many errors. I think the editing left something to be desired. Furthermore, it reinforced my belief that the intersection of good JavaScript programmers and really good software engineers is really small. There were many code snippets where too much code was duplicated instead of put into some utility function. I wish they had a technical editor who suffered from chronic analness like I do. Nonetheless, it was a pretty good book, and I thank the author for writing it.

As a last note, why have I made it through two DHTML books yet never had the prototype system explained as well as this paper explains it?

Friday, October 14, 2005

AJAX: Humor

Have you ever noticed that some of your best work happens in the bathroom?

The other day I was trying to resolve a particularly sticky user interface problem. I thought I'd try out some AJAX, Asynchronous JavaScript and XML. It wasn't really working out, and although they really aren't the same thing, I tried some CLOROX, Common Language Object Reference Over XML. Displeased with that, I fell back to COMET, Common Object Method External Transport. Next I thought I'd try some old fashioned BLEACH, Binary Language Exports And C Headers; however I made sure to remove all the COMET first because I've heard that mixing COMET and BLEACH can have disastrous side effects. I think I was most satisfied with CLOROX, especially thanks to its BLEACH heritage. I found that all of these options were better than SOAP, Simple Object Access Protocol, which leaves a sticky substance behind that is nearly impossible to get rid of.

Tuesday, September 06, 2005

JavaScript: JavaScript has Closures

Python has closures:
def outer():
print "Enter number:",
num = raw_input()
def inner():
print num
return inner

f = outer()
f()
Note that the variable num is available from within inner when outer has already completed.

Did you know that JavaScript has them too?
function testSetTimeout() {
var privateVar = 'A string';
function bar() { alert(privateVar); }
window.setTimeout(bar, 1000);
}

testSetTimeout();
The function bar makes use of privateVar which a variable in testSetTimeout's local scope even though bar is invoked later by setTimeout, i.e. after testSetTimeout has completed.

Wednesday, August 31, 2005

Linux: NETGEAR MA52 on Fedora Core 4

For the sake of those using Google to try to figure out how to get this to work, here's how to get the NETGEAR MA52 802.11b wireless card to work under Fedora Core 4 using the NdisWrapper. These are the instructions I followed:

  1. Created /etc/yum.repos.d/livna.repo per the instructions above.

  2. rpm --import http://rpm.livna.org/RPM-LIVNA-GPG-KEY

  3. yum --enablerepo=livna-stable install ndiswrapper kernel-module-ndiswrapper-$(uname -r)

  4. Downloaded the binary driver from here.

  5. unzip ndis5x-8180(173).zip

  6. /usr/sbin/ndiswrapper -i NET8180.INF

  7. /usr/sbin/ndiswrapper -l

  8. /sbin/modprobe ndiswrapper

  9. dmesg

  10. /usr/sbin/ndiswrapper -m

  11. Setup the network settings as usual.

Tuesday, August 30, 2005

Java: The Emperor is Naked

This just in: the emperor is walking around naked, and prominent government officials are willing to admit it! Read more!

Friday, August 12, 2005

Java: Thinking in Java

Here's a Java snippet from Bruce Eckel's blog:
static List<Test<List<Integer>>> tests = 
new ArrayList<Test<List<Integer>>>();
static List<Test<LinkedList<Integer>>> qTests =
new ArrayList<Test<LinkedList<Integer>>>();

Crazy.

Thursday, July 14, 2005

Python: Wrapping Methods Via a Backdoor

Often, when you write a server in Python, you include a backdoor. The backdoor is something that you can telnet to from localhost, and it's basically a Python shell. Within the Python shell, you can snoop around the running program. It's cool. Now, suppose you want to insert some code to debug a problem. Suppose you want to intercept all method calls to a certain class. (If you're a hardcore Python hacker, feel free to stop reading, but many other people will find this interesting.)

>>> class C:
... """This is some pre-existing class within the running application."""
... def f(self, num): print "I got called with:", num
...
>>>
>>> def wrap(f):
... """This is a function decorator. inner below is the wrapper itself."""
... def inner(*args, **kargs):
... print "I'm about to call %s with %s %s." % ... (f.__name__, `args[1:]`, `kargs`)
... return f(*args, **kargs)
... return inner
...
>>>
>>> # Wrap every method in C.
... for name in dir(C):
... attr = getattr(C, name)
... if callable(attr):
... setattr(C, name, wrap(attr))
...
>>>
>>> # Now, when you call C.f, the method is wrapped.
... C().f(5)
I'm about to call f with (5,) {}.
I got called with: 5

Saturday, June 04, 2005

Python: Generator Expressions

In one of his talks at PyCon, Alex Martelli said that if you have complicated loop logic, throw it into a generator so that you never have to duplicate it. In the old days, it was common to duplicate loop logic. I like this rule, and I have seen it improve my code. Just in case you haven't seen the syntax yet, it's:

>>> def generate():
... yield 1
... yield 79
... yield 26
... for i in range(0, 10):
... yield i
...
>>> for i in generate():
... print i,
...
1 79 26 0 1 2 3 4 5 6 7 8 9

In Python 2.4, generator expressions were added. When I saw these, I figured, "Well, yeah, that's pretty natural." It took me a while to realize that just as list comprehensions were taken from Haskell, generator expressions are lazy lists from Haskell. Again, here's an example:

>>> import itertools
>>> import random
>>>
>>> numbers = (random.random() for i in itertools.repeat(0))
>>> print "The sum of 10 random numbers is:", sum(itertools.islice(numbers, 10))
The sum of 10 random numbers is: 4.83875818377

Thursday, June 02, 2005

Python: HTMLTemplate

Paul Abrams suggested to me the idea of having 100% pure HTML, and then using some DOM on the server side to splice chunks of HTML together. After talking about it for about two hours, I became excited about the idea, and I wondered if it would be pleasant in practice in contrast to, say, Cheetah. At the very least, it would be an interesting alternative.

It turns out that HTMLTemplate is one such system. I asked the Python web-sig about it, as well as a few other people. Tung Wai Yip said that he really liked HTMLTemplate. I figured my buddy, Donovan Preston, of Nevow fame would like it because he's a fan of getting away from the whole "big chunk of HTML in an amorphous string" idea. Ian Bicking had the following comment, which I feel was very perceptive:

If there's no code then it's not a presentation layer. It's an HTML layer, nothing more, just dumb data. Presentation requires logic.

Ksenia Marasanova, the newest member added to the Aquarium project, had the following comments based on real experience:

I used it quite a lot, and while it is fast, bugs free and simple to use, total separation of markup and code is IMHO contraproductive - every simple change mostly requires changing two files.

Since Ksenia's opinion is based on experience, it carries a lot of weight in my mind. Feel free to add your comments below.

Thursday, May 12, 2005

Laszlo

laszlo-in-ten-minutes
LZX, the Laszlo XML-based language, allows you to develop Rich Internet Applications using industry standards such as XML, JavaScript, and XPath.
Interesting stuff. It's too bad Flash isn't an open standard.

Friday, April 15, 2005

MVC: Cargo Cult

Don Hopkins posted this to the Bay Piggies mailing list:
"a lot of the related literature seems to use MVC as the canonical
example of a design pattern"

MVC is the canonical example of the "Cargo Cult" design pattern of
blindly aping Smalltalk without understanding it or considering if there
are any more appropriate design patterns.

http://en.wikipedia.org/wiki/Cargo_cult

I've never heard a good explanation of what a "controller" is really
supposed to do (other than entangle brittle dependencies between the
view and the model, and allow programmers to bill for more hours
maintaining the code). But people always throw in that extra
"controller" class and its requisite complexity, just because Smalltalk
uses them, and it doesn't feel right imitating Smalltalk without the
whole MVC trifecta.

Just because MVC is a commonly used and cited "pattern" doesn't mean
it's the best one to use in all cases. It's better to have a "purpose"
than a "pattern".

http://osteele.com/archives/2003/08/rethinking-mvc
Agree with it or not, it's interesting reading.

Sunday, April 10, 2005

Open Source: Humor

Personally, I think free as in speech is good, free as in beer is better, and free as in spirited is best.

Saturday, April 09, 2005

Open Source: Apple

When I think of Apple, I am reminded of Richard Stallman. When you stand on the back of a giant, you can plainly see that a walled garden is really a jail cell.

Friday, April 08, 2005

Hyperthreaded Micro Threads for Aspect Oriented Programming

I recently discovered a series of articles written by Jon "Hannibal" Stokes on arstechnica.com. Usually, I stick to learning weird, exotic languages, but I'm really fascinated by his descriptions of modern processors. I'm especially fascinated by the idea of tuning modern day processors and programming techniques so that they take advantage of one another. For instance, C++'s use of automatic variables results in so many function calls, that if these function calls are not inlined, they can play hell on the pipeline, unless branch prediction works well.

Having read Hannibal's articles on hyperthreading, SMT, and the Itanium-64, IA-64, I became intriqued by the performance aspects of SMT on aspect oriented programming, AOP. AOP is currently confined mostly to the Java world, so it doesn't have a direct effect on the processor, per se, but I wondered if a natively compiled AOP compiler could better take advantage of an IA-64 processor. It would do this via explicitly parallel instruction computing, EPIC, and what I call micro threading.

Specifically, AOP permits a separation of concerns. Hence, a function that looks like this:

void do_f() {
log();
authenticate();
do_stuff();
log();
}

can be torn apart into something like:

void do_f() {
do_stuff();
}

// Blatant pseudo code.
match function do_* {
before { log(); authenticate(); }
after { log(); }
}

I propose that the above AOP could possibly be extended to:

match function do_* {
before { thread_fork log(); inline authenticate(); }
after { thread_fork log(); }
}

Hence, in the above example, for every function do_*, there would be a "micro" thread to take are of logging at the start of the function and another micro thread to take care of logging at the end of the function, but the authentication would be inlined. Thanks to EPIC, the compiler could give a hint to the processor and the OS that it would be best to run these micro threads at the same time as the main function. Paraphrasing the words of Intel, I'm creating code-level parallelism in places where there was none before. AOP was designed to make the programmer's life easier, but with the addition of hyperthreaded micro threads, it can possibly result in substantial performance increases as well.

Well, I hope the above made some sense. I most definitely welcome your comments. Hopefully, someone more intelligent than me can make it happen ;)

Monday, April 04, 2005

FeedBurner: RSS

If you're having a hard time getting FeedBurner to give you RSS, try setting your user agent to "FeedDemon/1.0 xyz". Thanks go to Jesse Montrose for this tip.

Friday, April 01, 2005

Hitachi G1000 Pocket PC

I just bought a Hitachi G1000 Pocket PC. I installed Python, Cheetah, Aquarium, and Glass (Aquarium's Web server). I have a simple Web application running in the background, and I can look at it with IE. I can even see the Web application from my laptop over USB from within Linux! There's something intrinsically cool about extremely small Web servers used as an application platform ;)

Wednesday, March 30, 2005

FeedBurner

Jesse Montrose asked me to submit my blog to FeedBurner, which I have done http://feeds.feedburner.com/JJinuxLand.

Tuesday, March 29, 2005

Python: PyCon 2005 random thoughts

Some people have asked me to provide some comments on PyCon 2005. Here is an informal collection of impressions and opinions. I won't cover the Web topics because I've already done that.

Alex Martelli's talks are a joy. I especially liked his talk on 'Descriptors, Decorators, Metaclasses: Python's "Black Magic"'. I just wish he had more time. 25 minutes is simply not enough time to understand the subjects he is trying to convey unless you already understand them.

PyPy is definitely not what I thought it was. Apparently, it's about type inference. I thought it was an attempt to rewrite the front-end of the Python interpreter in Python so that the front-end could be shared among all the versions of Python. If this were the cases, the front-end could be distributed as .pyc's, and all the versions of Python would only need to write VM's to interpret the .pyc's. :-/

wxPython is a pain to use. PythonCard is a wrapper around wxPython that makes it a joy to use. PythonCard is obviously not as mature as a lot of widget toolkits, as I can see obvious deficiencies (e.g. more sophisticated layout strategies). However, it is quite impressive.

Schevo is interesting. It's a GUI for object databases.

"Dabo, the 3-tier Database Application Framework" is a database-neutral, GUI-neutral RDBMS GUI. The author complained about wxPython a lot. The author mentioned that 80% of his effort was spent working around wxPython. I asked why he didn't use PythonCard. He said he wanted to remain GUI neutral. The whole thing looked like a bit of a waste of time :-/

Durus is a trimmed down version of Zope's object database. Having seen Schevo, I can see that object databases can make a certain set of database problems a bit simpler to solve.

Soap box warning:
However, I just don't see why people have to spend so much time trying to solve problems that were already solved in the 70's. Why does everyone hate SQL? I think SQL's the best thing to happen to computer science in the last 30 years! Here are things that RDBMS's do that object databases have a hard time with (although some do succeed with some of these points):
  • Cluster.
  • Atomic transactions that work even if the power chord is pulled at an inopportune moment.
  • Query extremely large data sets without transmitting all of the data to the client. Furthermore, the RDBMS can execute the query one hard drive block at a time without trying to bring the whole table into memory.
  • View the data in ways it wasn't meant to be viewed, i.e. do joins on arbitrary fields.
Concerning iterators and generators, I took away these two points:
  1. Anytime the loop logic gets complicated, write a generator so that the loop logic can be reused.
  2. Use the itertools module. It's blazingly fast and convenient.
"Sequential Code in an Event-Driven World" was basically "generators are cool."

"Python for Series 60" was impressive. I want one, but Sprint doesn't have them. Bang for buck, it's hard to beat Symbian phones.

Web: The Brian Problem

Thinking back to the early days of Aquarium, Chuck Esterbrook and I thought about merging Aquarium and Webware. Unfortunately, I'm a bit of a code nazi, and Webware isn't the most minimal, style-conforming code around (which multiple people have confirmed, so it's not just me). This dissuaded me from joining forces. The fact that I was out of the Web world for about two years gave Webware a big leg up :-/

Moving forward, I'd like:
  • To work hard on newbie documentation for the PyWebOff's concept of "Brian" (i.e. a Python newbie who knows PHP and is now trying to write Web applications in Python).

  • To revive Piranha for all the "Ruby on Rails" folk. SQLObject and the Subway project may make some or all of this work unnecessary.

  • To better integrate with SQLObject and FormEncode.

  • To write a WebServerAdaptor for Twisted. At IronPort, we use coroutines. I work with Sam Rushing, the author of Medusa. Since coroutines are strictly better than Twisted (same benefits, but easier to code), if I can't support Twisted, I'm going to push harder for IronPort to open source its coroutines library and its version of stackless Python. This will be great since Aquarium's Web server, Glass, can already run in a coroutine environment.
There are many Web frameworks out there. Although reducing code duplication among them is a laudable goal (e.g. WSGI), I think having common things like Cheetah, SQLObject, FormEncode, etc. are great places to reuse code. However, having many Web frameworks reuse code doesn't really help "Brian". What we need for "Brian" is:
  • Great beginner documentation.

  • A larger community who agree on how Web applications should be developed.

  • Mind share.
I think unifying the best parts and people from the Aquarium, Webware, CherryPy, Quixote, Subway, and Twisted community would be a great way to achieve this goal. Hence, I am approaching the "Brian" problem as a political one. The code is already there.

Web: PyCon 2005

I just finished attending PyCon. Specifically concerning the Web, I'd like to direct your attention to:

http://pyre.third-bit.com/pyweb/index.html
Basically, there are too damned many Web application frameworks, and they all assume you know what you're doing. The PyWebOff is an attempt to figure out which is best from a newbie's perspective. Hopefully the talk will be available in video format later. I just finished reading the blog. She said, "Please, whatever you do, don't try to solve the problem by writing another Web application framework!!!"

http://www.python.org/peps/pep-0333.html
Ian Bicking gave a talk on this. It's an attempt at consolidating some underlying Web application API's. Basically, it's an attempt at making up for lack of a servlet API. It's great in that Web application framework authors may be able to share some code, but it still doesn't address the fact that there are too many choices for the user. Furthermore, it does nothing for the API's exposed to the user himself. These aren't changing, it's the underlying API's that are changing. The API exposed to the user has to remain pretty much the same or else existing code will break :-/

http://www.python.org/pycon/2005/papers/75/LivePage.pdf
Donovan Preston, the author of Nevow, did a talk on writing dynamic Web applications. About the coolest thing is that he transparently transmits selected JavaScript events to the server so that he can write the callbacks in Python. From Python, he can do things like "client.myDiv.innerHTML = 'foo'". Furthermore, he uses an iframe that is always waiting for a response from the server. In this way, he can have the server "push" data to the client at anytime. I'm a bit bummed because I thought of almost all of these things before I had heard of him doing it, but he beat me to the punch in writing a proposal for PyCon. Nonetheless, it's always a pleasure talking to him.

http://sqlobject.org
I just ran into this. It's from Ian Bicking.

http://www.python.org/moin/Aquarium
I didn't write this, but I'm definitely impressed with how well the author summarized Aquarium. I've talked to him via email, and he sounds like a great guy. In fact, he suggested SQLObject would be a good combination with Aquarium, which is news to me ;)

I'm a little bummed about the whole WSGI thing since so much of it is really a duplication of the API's that Aquarium sought to lay down. Porting Aquarium to WSGI is like making an adaptor for an adaptor :-/ Nonetheless, I will probably make an Aquarium WebServerAdaptor to support WSGI's API.

I'm also a bit bummed about the "Ruby on Rails" thing, since Aquarium had the same functionality in a subproject called Piranha about three years ago (both automatic retrieval of data from an RDBMS and automatic code generation for a GUI to work with that data). The essential difference wasn't features, but it was accessibility for newbies, and it didn't help that I "left the Web" for about two years to work on the IPv6 project. In the future, I'm hoping to direct more of my attention to the newbies.

Python: Create a new class on the fly

At PyCon, Alex Martelli mentioned that you could create a class on the fly using the type function. Previously, I probably would have used the exec function. I feel like such a dork:
>>> class Template(object): # Must be a new-style class.
... def bark(self):
... print "woof"
...
>>> Page = type("Page", (Template,), {})
>>> Page().bark()
woof
>>>
>>> def meow(self):
... print `self`
... print "meow"
...
>>> Page.meow = meow
>>>
>>> Page().meow()
<__main__.page>
meow

Welcome to JJinuxLand

Karl Guertin told me, "He who blogs gets his opinion heard." Hence, inspired by the blogs of Anthony Eden, Leon Atkinson, and Ian Bicking, I have created my own. This is a purely technical blog concerning topics such as Python, Linux, FreeBSD, open source software, the Web, and lesser-known programming languages. In the interest of everyone's time, including my own, I hope to keep the volume low, and the technical content high.

Please excuse the fact that I did not write my own blog software. It isn't that I am unable to. It's simply that I hate reinventing the wheel when exceedingly round ones already exist. I chose blogger.com specifically on the recommendation of Krishna Srinivasan, Tung Wai Yip, Anthony Eden, and Google.

I look forward to your comments.