Wednesday, October 31, 2007

Mail

Amusing tidbits you pick up in the mailing industry...

No, you can't mail running chainsaws. At least I'm pretty sure about that; I don't know a specific regulation against them, but USPS takes a dim view of anything that puts its employees and machinery at risk.

On the other hand, you can mail live scorpions if you package them appropriately. Note that, however, that this is limited to the US; apparently doing so in Australia is not a good idea. The same page also gives the rules for mailing baby chicks (which must be not more than 24 hours old) as well as adult chickens (Express Mail only, please; and no refund if the chicken dies in transit unless the container was damaged).

Tuesday, October 30, 2007

Here we go again...


[10/30/2007]
Version 0.4.7 "Where did all these
balloons come from?
And why am I wearing
a fake nose?"

- New features:

* The options dialogs have been completely replaced by a new
interface, based on a top-level list view. This fixes many
deficiencies of the old interface: it handles long strings more
gracefully, avoids many of the focus-handling bugs that the old
dialogs had, and should generally be better-behaved.
(Closes: #197976, #331200, #424708)

* Prompts that ask you to enter text will now wrap to multiple lines
when the text gets long, rather than hiding parts of the string.

* The online help and other Help-menu itmes are now top-level views,
which should make them somewhat more usable. (Closes: #434349)

* Support for the "Breaks" field and for trigger states (thanks to
Michael Vogt and Ian Jackson for patches and prodding).
(Closes: #438543)

* Two new styles, "PkgDowngraded" and "PkgDowngradedHighlighted",
are provided to control how downgraded packages look. By default
these packages look like any other installed package.
(Closes: #434442)

* aptitude can now display homepage URLs stored in the Homepage
field of packages.


There are bug-fixes too, but those aren't as fun. So instead I think I'll include some diffstat output. Everyone likes diffstat!


daniel@alpaca:~/programming/aptitude/head$ hg diff -r 0.4.6.1:0.4.7 | diffstat
.hgtags | 1
NEWS | 92 +
b/src/apt_config_treeitems.cc | 477 ++++++
b/src/apt_config_treeitems.h | 156 ++
b/src/generic/util/browser.h | 42
configure.ac | 20
doc/en/aptitude.xml | 187 ++
help-fr.txt | 10
po/ChangeLog | 24
po/dz.po | 188 +-
po/es.po | 82 -
po/gl.po | 19
po/ne.po | 1277 +++++++++--------
po/pt.po | 20
po/ru.po | 97 -
po/sv.po | 1854 ++++++++++++--------------
po/zh_CN.po | 23
src/Makefile.am | 2
src/apt_info_tree.cc | 4
src/apt_options.cc | 598 +++++---
src/apt_options.h | 12
src/cmdline/cmdline_action.cc | 6
src/cmdline/cmdline_check_resolver.cc | 2
src/cmdline/cmdline_do_action.cc | 134 +
src/cmdline/cmdline_prompt.cc | 124 -
src/cmdline/cmdline_search.cc | 4
src/cmdline/cmdline_show.cc | 20
src/cmdline/cmdline_why.cc | 64
src/defaults.cc | 4
src/dep_item.cc | 1
src/desc_parse.cc | 2
src/generic/apt/apt.cc | 32
src/generic/apt/apt.h | 30
src/generic/apt/aptcache.cc | 54
src/generic/apt/aptcache.h | 21
src/generic/apt/aptitude_resolver_universe.cc | 28
src/generic/apt/aptitude_resolver_universe.h | 57
src/generic/apt/infer_reason.cc | 22
src/generic/apt/log.cc | 8
src/generic/apt/matchers.cc | 531 +++++--
src/generic/apt/matchers.h | 28
src/load_grouppolicy.cc | 25
src/menu_tree.cc | 12
src/pkg_columnizer.cc | 19
src/pkg_grouppolicy.cc | 27
src/pkg_grouppolicy.h | 9
src/pkg_info_screen.cc | 10
src/pkg_item.cc | 31
src/pkg_item.h | 7
src/pkg_subtree.cc | 22
src/pkg_subtree.h | 12
src/pkg_tree.cc | 4
src/pkg_tree.h | 1
src/pkg_ver_item.cc | 31
src/pkg_ver_item.h | 5
src/pkg_view.cc | 24
src/reason_fragment.cc | 10
src/solution_fragment.cc | 5
src/solution_item.cc | 76 -
src/solution_item.h | 14
src/ui.cc | 179 +-
src/vscreen/fragment.cc | 140 +
src/vscreen/fragment.h | 40
src/vscreen/ref_ptr.h | 5
src/vscreen/testvscreen.cc | 20
src/vscreen/vs_editline.cc | 310 +++-
src/vscreen/vs_editline.h | 33
src/vscreen/vs_tree.cc | 113 +
src/vscreen/vs_tree.h | 40
src/vscreen/vs_treeitem.cc | 4
src/vscreen/vs_treeitem.h | 21
src/vscreen/vs_util.cc | 1
72 files changed, 4853 insertions(+), 2754 deletions(-)

Just rub it in, why don't you!

One of my co-workers told us about a message he saw posted on a British message board about Royal Mail. For people whose job does not involve postal systems, Royal Mail is the semi-governmental semi-monopoly that handles mail in the UK; it's a little like the USPS in the States.

The funny thing about the message had little to do with the mail: apparently the poster was saying that Royal Mail's standards have deteriorated because he can no longer pick up his mail at 9:30 AM, before he goes to work. Dude! You don't even have to leave for work until 9:30 and you're complaining about when your mail comes?

I bet he gets four weeks of paid vacation, too, and then complains about how that isn't enough.

Saturday, October 13, 2007

Mercurial repositories for the aptitude Debian tree now publically accessible

Since I switched the aptitude repositories over to Mercurial, I've been using hg-buildpackage to produce Debian packages. I wasn't sure at first if it would work out, so I didn't publish the repositories, and then I got swamped with work. But I've had good luck so far with hg-buildpackage, so I've uploaded the Mercurial trees to Alioth. You can find the upstream branch here:

http://hg.debian.org/hg/aptitude/debian-upstream

and the Debian branch here:

http://hg.debian.org/hg/aptitude/debian

Monad.Reader

The Reader monad is a simple and easy-to-use structure from the Haskell library that solves a common problem.

Very often, it's the case that you have a lot of functions that all need to use the same values. For instance, you might be laying out some text on a page, and you need to keep the details of the page size around in all your layout algorithms. Typically, you handle this situation by adding a new parameter to all your functions which represents the state. So,


layoutPage :: Text -> Page


becomes


layoutPage :: PageLayoutParams -> Text -> Page


This works just fine, but it can get really ugly. Every single function gets a new parameter, which must be threaded through to every related function that it ever calls. This causes visual clutter, particularly for functions that don't actually use the parameter themselves but just pass it on.

A function written in the Reader monad is augmented with a hidden parameter. For the hypothetical example above, we would write:


import Control.Monad.Reader
type LayoutFunc = Reader PageLayoutParams

layoutPage :: Text -> LayoutFunc Page


Note that the Reader monad is partially applied here. The result, LayoutFunc, is a new monad that adds a parameter of type PageLayoutParams to any code that runs inside it.

So, now that we have this monad, how do we use it? The "ask" operation retrieves the parameter that's hidden in the monad:


ask :: Reader a a


or, specialized to LayoutFunc:


ask :: LayoutFunc PageLayoutParams


In order to remain close to the example in question, I will provide specialized type signatures for the rest of the library functions. You can find the generic type signatures in the Haskell library documentation for Control.Monad.Reader.

Suppose that layoutPage started out like this before it was moved into the monad:


layoutPage st txt =
let width = pageWidth st
...


In the Reader monad, this becomes:


layoutPage txt =
do st <- ask
let width = pageWidth st
...


As you can see, we've gone from one line of code to two. As this is clearly unacceptable for a clutter-reducing device, the Reader module provides a convenience function encapsulating the above pattern:


asks :: (PageLayoutParams -> a) -> PageLayoutFunc a


This allows us to simplify the monadic implementation to:


layoutPage txt =
do width <- asks pageWidth
...


It's quite common, when multiple functions share context information, to invoke a function in an altered context. For instance, we might have a layoutSubPage routine that changes the page width:


layoutSubPage st newWidth txt =
doLayout (st {pageWidth = newWidth} txt)


The Reader equivalent of this idiom is the function "local":


local :: (PageLayoutParams -> PageLayoutParams) -> LayoutFunc a -> LayoutFunc a


local executes an operation in a context modified by its first parameter. For instance,


layoutSubPage newWidth txt =
local (\st -> st { pageWidth = newWidth }) txt


Finally, to actually invoke a computation in the Reader monad, use runReader:


runReader :: LayoutFunc a -> PageLayoutParams -> a

main = showPage (runReader defaultPageParams someText)


For much more information on the Reader monad, see All About Monads, or the Haskell library documentation.

Wednesday, October 10, 2007

Science: who does it, why?

On the topic of "why so few scientists are women", I recently came across a rather thought-provoking article (thanks Erinn). It's worth a read, especially for anyone (man or woman) that's thinking about heading into academia.

Wednesday, October 03, 2007

Feline Love

Coding while a cat kneads your chest: awkward.

Coding while a cat sleeps on your face: difficult.

Coding while a cat nibbles on your fingers: painful.

Coding with a cat snuggled up against your side: adorable.