Tuesday, November 30, 2004

Future Interfaces

Computer interfaces should be dramatically improved, in the spirit of mpt's crufty rant. He sounds a refrain "We have the technology, so why....?" I don't think we have the technology yet, but we should.

No one should ever have to "save" a file. This requires a few things:
  1. Unlimited undo and redo
  2. Files should only be named with UUIDs
  3. Files should be easily searchable using metadata
Once we've eliminated the save requirement, we can eliminate the unnatural concept of "open" files and windows. The only natural concept is whether a file is visible or not. Everything else should be a transparent optimization.

We can't just use unix inodes instead of UUIDs for two reasons: they don't work across multiple filesystems and they can't handle being removed and restored. I don't think there is a stable implementation of the metadata interface yet, though Gnome Storage looks promising.

Finally, applications will need to support transparent persistence. We can't just use generic checkpointing because it would be so wasteful. (For example, a web browser keeps a lot of stuff in memory, but it really only needs to persist a scrollbar location, a url (and maybe a cached copy of the url, which it'll need apart from the checkpointed image anyway).) Window managers would also have to be better at managing and persisting window arrangements.

Besides window sizes and locations, we'd like to manage tilesets; we'd like them to remember the fact that we're working with two documents side-by-side. Tzorech iyun, sometimes tilesets just indicate the desire to work on two different things at the same time.

Monday, November 29, 2004

Traits for Python

Since python already has multiple inheritance, implementing traits isn't a matter of adding new functionality, but of restricting the functionality that's already there.

The metaclasses below enable preventing classes from having member data and preventing conflicting methods. (Just have your classes inherit from Trait or TraitUser.)

The next step is solving the Artistic Cowboy Problem in a pythonic fashion.

If you missed my earlier traits entry, here's the traits homepage link again.
#!/usr/bin/python

import operator, types, sets

def get_classdict(cls):
"get name:attr dict from a class"
names = dir(cls)
classdict = {}
for name in names:
classdict[name]=getattr(cls, name)
return classdict

def get_methods(classdict):
"get a set of nonsystem methods from a classdict"
methods = sets.Set()
for (k,v) in classdict.items():
if k.startswith('__'): continue
if type(v) is types.MethodType or type(v) is types.FunctionType:
methods.add(k)
return methods

class TraitClass(type):
"""Metaclass for classes that may not have state,
whose conflicting trait methods must be resolved in extenders,
and who may not extend classes which are not traits."""

def __init__(cls, clsname, bases, classdict):
type.__init__(cls, clsname, bases, classdict)
cls.conflict_methods = sets.Set()
all_methods = sets.Set()
for c in cls.get_method_lists(bases, classdict):
methods = get_methods(c)
cls.conflict_methods |= all_methods & methods
all_methods |= methods
#propagate conflicting methods from base classes
for c in bases:
if 'conflict_methods' in dir(c):
cls.conflict_methods |= c.conflict_methods
for c in bases:
#if c == object: continue
if type(c) != TraitClass:
cls.handle_base_class(c)

def get_method_lists(cls, bases, classdict):
"traits check for conflicts from parents and from self"
return map(get_classdict, bases)+[classdict,]

def handle_base_class(cls, c):
"enforce only inheritting traits"
raise "Trait %s cannot inherit from a class that is not a Trait"%cls.__name__,c.__name__

def __new__(cls, clsname, bases, classdict):
#if a nonexplicit class extends nontraits, make it a trait user
if classdict.get('__metaclass__') != TraitClass and 0 < len([c for c in bases if type(c) != TraitClass]):
classdict['__metaclass__']=TraitUserClass
#if class is actually a trait, make readonly
else:
classdict['__slots__']=[]
return type.__new__(cls, clsname, bases, classdict)

class TraitUserClass(TraitClass):
"""Metaclass for mostly normal classes,
that must use single inheritance of nontraits,
and that implement trait conflict handling"""

def __init__(cls, clsname, bases, classdict):
TraitClass.__init__(cls, clsname, bases, classdict)

unresolved = getattr(cls, 'conflict_methods',sets.Set()) - sets.Set(classdict) - sets.Set(dir(getattr(cls,'nontrait_base',None)))
if len(unresolved) > 0:
raise "conflicting methods",unresolved

def get_method_lists(cls, bases, classdict):
"check for conflicts in parent traits"
nontrait_base = getattr(cls, 'nontrait_base', None)
return [ get_classdict(c) for c in bases if c != nontrait_base]

def handle_base_class(cls, c):
"enforce single inheritance of nontraits"
nontrait_base=getattr(cls,'nontrait_base',None)
if nontrait_base:
raise "Trait-using class %s can extend no more than one class that is not a Trait"%cls.__name__, c.__name__
cls.nontrait_base = c

def __new__(cls, clsname, bases, classdict):
#python weirdness; __metaclass__ doesn't override parent's here
if classdict['__metaclass__'] == TraitClass:
raise "Trait %s cannot inherit from a class that is a TraitUser"%clsname
return type.__new__(cls, clsname, bases, classdict)

class Trait: __metaclass__=TraitClass #convenience object
class TraitUser: __metaclass__=TraitUserClass #convenience object

Python Metaclasses are Weird

$ python <<''

> class m1(type): pass
> class m2(m1): pass
> class c2: __metaclass__=m2
> class c1(c2): __metaclass__=m1
> print 'the type of c1 is', type(c1)
>
the type of c1 is <class '__main__.m2'>

Monday, November 22, 2004

Why XML is Case-Sensitive

# re: Tyranny of the geeks 11/20/2004 1:27 AM Tim Bray

XML markup is case-sensitive because the cost of monocasing in Unicode is horrible, horrible, horrible. Go look at the source code in your local java or .Net library.

Also, not only is it expensive, it's just weird. The upper-case of é is different in France and Quebec, and the lower-case of 'I' is different here and in Turkey.

XML was monocase until quite late in its design, when we ran across this ugliness. I had a Java-language processor called Lark - the world's first - and when XML went case-sensitive, I got a factor of three performance improvement, it was all being spent in toLowerCase(). -Tim

Friday, November 19, 2004

The Way to Manage Windows

Writing a window manager is hard (just like making war). I've no time to do it, so I'm going to describe my vision here.
  1. Windows should never overlap. Windows overlap when one partially obscures another.
  2. Windows should only ever be grouped by tabs or tiles.
Tiled windows are completely visible, and occupy all the available space because their edges line up. You can see an example in WindowsXP. If you have a bunch of windows open for an application, right clicking on that application's taskbar icon will give you "Tile Horizontally" and "Tile Vertically" commands.

Tabbed windows only have a single visible window, which also occupies the whole available space. Optionally, the system can display little "tabs" for switching between windows, or it can provide different mechanisms.

By nesting tiles and tabs, any reasonable window behavior can be represented. "Workspaces" and "virtual desktops" are essentially tabs. "Sticky windows" can be implemented with top-level tiles. The beautiful thing about having so few concepts is that features are available in many contexts.

I'm still not sure what window operations should be available. Dragging a window to a different tabset or tileset should move it, but should we have a mechanism for swapping tiles? It should be possible to change a window from tile to tab and back, but what mechanism should there be for zooming a tileset?

Here's a tentative set of operations: each window gets "pull up" and "push down". For tabs, this is pretty self-evident. For tiles, it involves resizing the partner tiles, so that this tile is in the same place despite the push/pull. In addition to push/pull, tabs get an operation "change to tile", and tiles get two operations : "change to selected tab" and "change to unselected tab". These operations are reversible, so tile positions are recorded (and resettable). The dimensions of the window otherwise determine the default horizontal or vertical tile placement. Drag and drop "moves" both tabs and tiles, and they will become tabs and tiles of the drag target, respectively.

There are window managers that implement tiles, but they all have two problems: they don't use this beautiful dual idea, and they are almost completely unusable.

Unfortunately, since many applications make unwarranted assumptions, the window manager would have to support the legacy behavior also.

Editor Feature

When I cut Levi from "Reuven, Shimon, and Levi", and I paste it to before Reuven, I want my editor program to do the right thing. That is, I want my editor to display "Levi, Reuven, and Shimon" instead of "LeviReuven, Shimon, and ".

My java editor should also do the same thing for commas, but it's really inexcusable that java doesn't allow lists to have trailing commas (1,2,3,).

Thursday, November 18, 2004

Traits for Reuse

Traits are an exciting development in object oriented programming.

Traits are collections of methods, like objects without state. These methods are parameterized over other methods, which may be traditional object methods or other traits methods.

A class may inherit multiple traits, but without the problems of multiple inheritance and mixins . This is because 1) their composition isn't ordered and 2) they support composition operators for resolving conflicts.

Traditional classes still have single inheritence, and they contain all the state and glue code. Traditional inheritance is for subtyping, and traits inheritance is for reuse. The developers are quite conservative; they propose traits as an incremental addition to traditional languages. The traits methods may be visualized as code which is simply copied into their composing classes (almost reminiscent of linked editing).

The End of Even Numbered Linux Releases

Until recently, the Linux kernel development followed alternating cycles of adding new features and then stabilizing. The stabilization period was relatively short, and then development would branch off again. People would then be free to make low impact patches to the stable fork, but most developer attention would be focused on the new development fork.

With the most recent release, Linus has abandoned these alternating cycles. This is partly because new revision control tools allow him to better "cherry-pick", so that he can pull from other developers' own development forks. More importantly, though, the Linux distributions really want to make their own stable releases. They have their own release schedules, which they prefer not to tie to the kernel's schedule. The distribution kernels also get much greater user exposure (and testing) than Linus's own kernel, and so are better positioned to address stability issues.

The mainline kernel has become the permanent "unstable" kernel, albeit a little less unstable. Now the distributions contribute their patches back to the mainline and allow them to be beta tested there. If you want a rock stable kernel, you should get a distribution kernel, or even an enterprise distribution kernel.

Years ago, hackers debated whether Linux should remain a hacker system or if it should clean up its act and "go mainstream". Linux is remaining a hacker system, but companies have sprung up to build their own mainstream versions. It's nice that there's a business model in that.

Lee Revell describes the current situation nicely.

It remains to be seen whether there's a future for multiple distributions. It could be that, just like in the commercial software world, there can be only one. That is, that network effects may favor a single distirbution gaining the overwhelmingly majority of users.

Tuesday, November 16, 2004

My Bookmarklets

Boorkmarklets are bookmarks that consist of javascript code. Here are two that I rewrote:
Right-click on one and select "Bookmark This Link" or "Add to Favorites", and then you'll always be able to use the feature by selecting the bookmark that you created.

Friday, November 12, 2004

Making Things Easy to Maintain

A lot of the cost of software is maintenance. Currently, There Is No Magic Bullet for making maintenance cheap. But there are a lot of best practices which I'm going to try to collect.
  • Make it as simple as possible.
  • Use test driven development.
  • Keep as little state as possible.
And some particular points.
  • Centralize environment configuration.
  • Make jobs rerunnable/idempotent whenever possible.
  • Give temporary resources short-lived unique names.

Tuesday, November 09, 2004

Note About Dune

The two most powerful institutions in the Dune series are the Bene Gesserit and the Bene Tleilax.

The BG is entirely composed of women, and the BT of men. Both houses prefer to exercise their influence quietly, the BG by only manipulating and never controlling directly; BT by assuming a guise of inferiority. In the Dune world, artificial intelligences are absent, so improvement of human beings is the main historic goal. The BG pursue this goal through training the mind and body, and by a "human breeding program", while the BT pursue it through direct genetic engineering. Each institution has its own approach to effective immortality; the BG share the memories of all of their female ancestors, and the BT clone themselves and infuse the clones with their original consciousness.

The BG incorporates motifs of the Christian Church (and possibly the Jesuits), and the BT of Islam. Both houses pursue a Messianic dream. The dream of the BG is to create the "Kwisatz Haderach", but the dream of BT has not been revealed. The Kwisatz Haderach, among other abilities, will have access to the memories of both his male and female ancestors. It's clear that these schools must somehow synthesize, and in fact this has been alluded to in the last books of the series.

Though much of the Dune lingo is taken from greek and arabic, "Kwisatz Haderach" almost certainly refers to the hebrew קפיצת הדרך ("skipping of the way") that figures in Chasidic literature. It's a miracle of travelling great distances in a short amount of time. Accordingly, it was the Miles Teg character, and not "Paul Muad'dib" who became the first Kwisatz Haderach.

Incidentally, Leto, Paul, and Leto II evoke Avraham, Yitzchak, and Yaakov.

Thursday, November 04, 2004

On G-d's Side

There are two problems with fundamentalism: arrogance and self-service.

The root cause is that when you decide (on some level) to do the right thing, you get comfortable with the idea that you are doing the right thing.

Believing that you are doing the right thing can make you arrogant, and it can make you intolerant of people who are doing different things. Believing that you are doing the right thing can cause you to compromise for your own benefit. It's a case of the ends justifying the means, but it's more seductive. You feel that those who are doing good should be enabled to continue doing good. But if you ever flag in your devotion, you're also guilty of hypocrisy.

The converse danger is paralysis. If you refrain from judging, there's no basis for choice. All the choices that you do make will be weakened.

Maybe we can just continue to act on our consciences, so long as we realize how little we understand the connection between our efforts and their actual effects.

Wednesday, November 03, 2004

2004 Election Issues

from cnn's exit poll:

of the people who considered each issue most important, how many of them voted...

overallfor bushfor kerry
taxes5%57%43%
education4%26%73%
iraq15%26%73%
terrorism19%86%14%
economy/jobs20%18%80%
moral values22%80%18%
health care8%23%77%

also, people who voted for bush overwhelmingly thought that the economy is doing well, and that we should have invaded iraq. people who voted for kerry overwhelmingly thought the economy is doing poorly, and that we shouldn't have invaded iraq.

Categories of Chumra

The idea of the chuma, or stringency, in Orthodox Judaism looms large. G-d appointed the Jewish people His holy nation and gave us His Law, but individuals have always strived to do more. There are actually a few different categories of chumra. Scholars have written about the subject, but in the form of manuals for getting closer to G-d. I'm just describing people's actions as they appear.

Ever since the disbanding of the Sanhedrin (central government of rabbinic judaism), religious legislation has been somewhat up in the air. This situation leads to the most fashionable type of chumra, the attempt to satisfy all the conflicting decisions made by a group of different decisors.

The group of decisors is often the rishonim (medieval scholars), and satisfying their decisions inspires many of the famous "Brisker Chumros". These chumros are more compelling when the issue is a matter of Biblical law rather than Rabbinic, but often the provenance itself is also in question. It is literally impossible to always satisfy all of the decisions of all the rishonim. [To be written: rashi and rabbenu tam tefillin example, rov example]

As we consider later decisions, it becomes increasingly less clear whether a given position is a chumra or actual halacha. At least for opinions of the rishonim, we usually have a idea of the halacha from the Shulchan Aruch. After that, we often have many different strong positions and no agreed upon principle for deciding amongst them. These questions are usually either less fundamental, or else they deal with technology and new situations.

A subcategory of satisfying all decisions is to observe authoritative decisions that are mostly disregarded. This disregard may be explained away by later authorities, or it may be mysterious. Either way, we are reluctant to suppose that the majority of observant jews are violating halacha, so these decisions take on the status of chumra. An example is Ezra's decree that after seminal emission, men should immerse in the Mikveh before learning or praying.

Another major category of chumra is that of ascetic practices. In general, the torah encourages--and perhaps requires--embracing life, but historically scholars have valued greater restraint. Maimonides famously praises the ideal of moderation, but his view of moderation looks harsh by today's standards. An example is fasting most Mondays and Thursdays.

Excruciating attention to detail is another major form of chumra, which some consider to be part of normative halacha. The classic example is that halacha specifies the proper order for tying your shoes. This trend goes back to the Talmud, which wrangles over the exact right place to first break open a loaf of bread. People may try to be meticulous in interpersonal relations as well (for example, not telling a companion at a restaurant that you dislike your meal, lest the waiter overhear and get hurt feelings).

Many of these chumras evoke awareness of G-d and godliness in every aspect of one's life, even the most picayune. It could be that accomplishing this awareness is more important than the actual details themselves.

Mysticism informs mainstream halacha, but it also forms a rich body of chumra. Presumably this category need not be limited to the traditional literature, but may include fringe texts, and even personal research into hidden worlds.

Much of civil law is about compromise, where neither party to a dispute is actually at fault. The Talmud describes "chasidus" as the habit of forgoing legal advantage in many such situations, and exceeding one's pecuniary obligation. [Source in bava kamma]

The last category of chumra is a biggy: do more good. This means strengthening the pillars of the world: learning more torah, giving effort and money to those in need, and praying more meaningfully.