Friday, June 27, 2008

No System Beep

I found the following file on my laptop recently:

I'm traveling by plane from San Jose to Philadelphia. It's just me and my laptop (no network) so I'm poking around for things to do.

No System Beep:

I've got some audio files which I'm playing through my headphones but every time I type C-g in emacs a very loud beep hurts my ears...

 sudo xset b off
ahhhh. OK now back to my wanderings.

Thursday, June 26, 2008

Perl: hashes of unknown elements

#!/usr/bin/perl
# Filename:                unpack.pl
# Description:             Unpacks hash of unknown types
# Supported Langauge(s):   Perl 5.8.x
# Time-stamp:              <2008-06-26 21:47:59> 
# -------------------------------------------------------- 
use strict;
# This is an array of strings
my @array = ("arr1", "arr2");
# This is a "predicable" hash, each string maps to a string:
my %hash = (
    'key0' => 'val0',
    'key1' => 'val1',
);
# This is an "unpredictable" hash:
my %mixed = (
    'key0' => 'string', 
    'key1' => \@array, 
    'key2' => \%hash,
);
# Note that I had to use '\' to indicate that I'm building 
# this hash with references to the previous array and hash. 
# I.e. not the array or hash itself, but a reference to it. 
# 
# I say this hash is unpredictable because it might seem 
# tricky recurse throuh it if you didn't know the mapping: 
# if key0 mapped to @array and key1 mapped to %hash etc. 
# -------------------------------------------------------
# Perl's dumper works: 
use Data::Dumper;
print Dumper(\@array);
print Dumper(\%hash);
print Dumper(\%mixed);
# -------------------------------------------------------
# Let's recursively loop through each:
print "Array:\n";
foreach my $str (@array) {
    print "\t" . $str . "\n";
}
# -------------------------------------------------------
print "Hash:\n";
foreach my $key (keys %hash) {
    print "\t" . $key . " --> " . $hash{$key} . "\n";
}
# -------------------------------------------------------
print "\nMixed:\n";
foreach my $key0 (keys %mixed) {
    print "\t" . $key0 . " => ";
    my $unknown = $mixed{$key0};
    if (ref($unknown) eq 'HASH') {
 print "{";
 foreach my $key1 (keys %$unknown) {
     # dereference with $$
     print $key1 . " => " . $$unknown{$key1} . ", ";
 }
 print "}";
    }
    elsif (ref($unknown) eq 'ARRAY') {
 print "[";
 foreach my $str (@$unknown) {
     print $str . ", ";
 }
 print "]";
    }
    else { # it's a string
 print $unknown;
    }
    print "\n";
}

LD_LIBRARY_PATH

Enjoyed an explanation on why you should not set LD_LIBRARY_PATH.

Sunday, June 22, 2008

fluxbuntu

xubuntu, I think I've found someone new: fluxbuntu.

Saturday, June 14, 2008

Make your own iSCSI Server

I found a tech republic article about creating your own iSCSI Server on top of the Linux kernel. The project hosted at iscsitarget.sourceforge.net looks good and Fedora has a howto which makes it look easy enough.

Friday, June 13, 2008

condor & netlogo

I had an interesting chat with someone who is looking to get blades for condor to run netlogo modeling.

Thursday, June 12, 2008

Sipser's Theory of Computation

I stayed up late reading Sipser's Introduction to the Theory of Computation looking for high level connections between chapters. When I woke up I remembered that:

Finite Automata (FA) can recognize formal languages. A Deterministic Finite Automata's (DFA) next state for a given input is certain but a Non-deterministic Finite Automata's (NFA) is not: it might have two transitions for the same state. An algorithm exists to convert NFA into DFA. FA can recognize regular languages and an algorithm exists to convert FA into regular expressions. However FA have trouble with non-regular languages like {(0^n|1^n) for all n > 0}. Push down automata (PDA) are like finite automata but they have an infinite stack which they can use to recognize said language. We can describe languages by generating them from a context free grammar (CFG) OR recognizing them with a PDA. A CFG and PDA are equivalent. The church-turing thesis precisely defines what an algorithm is such that it must be computable by the lambda calculus or a turing machine; which are equivalent. A turing machine is like a PDA but has an infinite array for random access, which is less restrictive than a stack, so it is more powerful. If a turing machine will stop while carrying out an algorithm then the algorithm is decidable. The halting problem is undecidable.

Wednesday, June 11, 2008

O'Reilly's Learning Python

Google Books has a lot of O'Reilly's Learning Python. I found the following useful for getting myself back into Python:
  • Dynamic Typing: variables aren't typed, objects are:
    • variables are entries in a system table, with spaces for links to objects
    • objects are pieces of allocated memory, with enough space to represent the values for which they stand
    • references are automatically followed pointers from variables to objects
    "variables are always pointers to objects, not labels of changeable memory areas: setting a variable to a new value does not alter the original object, but rather causes the variable to reference an entirely different object."
  • Modules: highest-level program organizational unit which typically correspond to other python files. import finds the module's file, compiles it into byte code and runs the module's code to build the objects it defines (it's not just a textual substitution).

    Python forbids import foo.py or import /bar/foo.py. A platform independent module search path (print sys.path) abstracts this away. An import foo will use foo.py, provided it exists in the program's home directory: where the top-level program resides or where the REPL was started. To cross directories set the PYTHONPATH environment variable in your shell:

    $ cat modules/my_mod.py
    def f():
            print "I'm f"
    $ cat my_program.py
    import my_mod
    my_mod.f()
    $ cat shell_wrapper.sh
    #!/bin/sh
    export PYTHONPATH=${PYTHONPATH}:modules/
    /usr/bin/python my_program.py
    $ 
    
    In the example above running python my_program.py will fail but ./shell_wrapper.sh works. See also Python Tutorial: Modules.
  • Class Coding: Python's OOP supports:
    • Inheritance: based on attribute (method or variable) lookup. E.g. in X.name expressions, X is an instance of a class with attribute name. Inheritance comes up with respect to instances of classes as well as derived classes.
    • Polymorphism: in X.method(), the meaning of method depends on the type (class) of X.
    • Encapsulation: Methods and operators implement behavior; data hiding is more of a convention than the rule
    The object self is passed as the first argument of a Method. Because classes generate multiple instances, methods must go through the self argument to get to the instance to be processed.

    The book provides a quick example of defining a class and two instances:

    $ python
    Python 2.5.2 (r252:60911, Apr 21 2008, 11:17:30) 
    [GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> class FirstClass:
    ...     def setdata(self, value):
    ...             self.data = value
    ...     def display(self):
    ...             print self.data
    ... 
    >>> x = FirstClass()
    >>> y = FirstClass()
    >>> x.setdata("King Arthur")
    >>> y.setdata(3.14159)
    >>> x.display()
    King Arthur
    >>> y.display()
    3.14159
    
    It then goes on to create a second class which inherits from the first class:
    >>> class SecondClass(FirstClass):
    ...     def display(self):
    ...             print 'Current value = "%s"' % self.data
    ... 
    >>> z = SecondClass()
    >>> z.setdata(42)
    >>> z.display()
    Current value = "42"
    >>> 
    
    We used the inherited setdata() method but that the display() method was overrided.

    Python also supports operator overloading via __<HOOKS>__. For example, __init__ is the constructor hook that most classes should have. You can also get creative and support operators like + or * based on the hooks available:

    >>> class ThirdClass(SecondClass):
    ...     def __init__(self, value):
    ...             self.data = value
    ...     def __add__(self, other):
    ...             return ThirdClass(self.data + other)
    ...     def __mul__(self, other):
    ...             self.data = self.data * other
    ... 
    >>> a = ThirdClass("abc")
    >>> a.display()
    Current value = "abc"
    >>> b = a + 'xyz'
    >>> b.display()
    Current value = "abcxyz"
    >>> a * 3
    >>> a.display()
    Current value = "abcabcabc"
    >>> 
    
    Note that we're not using a setdata() method since we're just using the constructor. What's more interesting is that we're just adding and multiplying on our new object with standard operators and that they have meaning relative to the object.
It seems that Google Books will omit different pages based on a different host somewhat randomly (handy for missing pages).

Python: Iterators

Guido said: "The use of iterators pervades and unifies Python. Behind the scenes, the for statement calls iter() on the container object". But it gets better! Generators make it easy to create iterators. They use yield which calls next() behind the scenes and resumes where it left-off. Then "simple generators can be coded succinctly as expressions": So here's a loop (which is already using an iterator behind the scenes):
>>> for i in range(10):  
...     print i,
... 
0 1 2 3 4 5 6 7 8 9
>>> 
Which I'll use to define a list:
>>> [i for i in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
Or make a generator object:
>>> (i for i in range(10))
<generator object at 0x7f5fdb38d518>
>>>
Which I can feed to a function:
>>> sum(i for i in range(10))
45
>>> 
Makes Python feel more Functional.

Programming Collective Intelligence

Amazon rather accurately recommended Programming Collective Intelligence by Toby Segaran for me. One reviewer said:
...the author describes how the most popular of all neural networks, backpropagation, can be used to map a set of search terms to a URL... to try and find the page best matching the search terms. Instead of... proving the math behind the backprop training algorithm, he instead mentions what it does, and goes on to present python code that implements the stated goal... The upside of the approach is clear -- if you know the theory of neural networks, and are not sure how to apply it (or want to see an example of how it can be applied), then this book is great for that.
Sounds like something I'd want to play with.

Sunday, June 8, 2008

down for everyone?

I'm going to send this to the Help Desk: www.downforeveryoneorjustme.com

Update: Dig the recursion!

Thursday, June 5, 2008

Possible Worlds and Software Bugs

When I write a program I try to think of what could go wrong. I then try to address these concerns with conditionals or try/catch blocks. This eliminates a lot of bugs early.

The method described above reminds me of an informal logic book which encourages the reader to imagine possible worlds to find counter examples in order to determine if an argument is valid. This is not rigorous but provides a gentle and intuitive introduction to logic. I don't know of a rigorous method of finding bugs in code and in some cases it's impossible so I like to use this method. Interesting that the non-bugginess of the software will be limited by the programmer's imagination [0].

User testing should flush out bugs that the programmer hasn't thought of and is important. However a programmer should take the time to try to anticipate the bugs first because:

  • You might see the bug directly as you write the code that caused it instead of waiting and hoping that a blind test on a larger scale flushes it out
  • It's easier to work on code that you just wrote which is fresh in your mind than old code which you need to relearn
  • User testing and reporting might not get a bug fixed until it's inconvenienced a lot of users
  • The bug may not get discovered until the software is run in a new domain
A friend of mine with a philosophy background said that he often finds it easy to spot bugs in other people's code. I wonder if any of this is related to what he does. I think studying philosophy helped make me a better programmer.

Footnote:
[0]
Which is probably limited by how tired the programmer is or the programmer's mood. Which in turn is probably limited by how much coffee or antidepressants the programmer has consumed.

Tuesday, June 3, 2008

DNS Timeline

Sean Donelan's website has some interesting content including a design considerations for data centers and a DNS timeline.