Rome, August 2008
3 January 2010 16:43:45
photos, travel, update
These pictures have been waiting for a review and tagging for ages.
I almost finished the task last summer but somehow that final push was
missing. Without further introduction here
are the pictures -- only 15 months late.
Permalink | Comments (0)
Python (2.5) and me
28 December 2009 13:53:17
rant, software
I have always thought that the fastest, the easiest, and the most convenient
way to learn a new (programming) language is to start using it. Not little by
little, but just using it as much as you can. Now that I have spent about a
month writing Python as Python-like as I can, I have to get a few things out of
my head. Obviously I'm still total newbie to Python so don't take my rant too
seriously. After all, so far I've only need rewriting one of my (unpublished)
5000-line Perl-scripts to Python from scratch. Rewriting things from scratch is
another great way to improve your stuff but that's another story.
Variable declaration not required
Python does not expect you to declare variables. In fact, as far as I
can tell, variables cannot be declared in the first place. I don't like this
because I make typos. I make a lot of typos. Well, maybe not that much. In any
case, I hate to hunt for typos in my code only because greater power decided
that declaring variables is for losers. Perl doesn't require declaration
either, but at least in Perl I can opt in for that. Nobody has been able to
tell me how to do that in Python.
found = False
for item in get_stuff():
if item.name() == the_one:
founs = True
break
if found and foobar:
# and no, the point isn't in "why can't you call do_stuff while still
# in the loop
do_stuff
No real encapsulation
There is no real encapsulation. Lack of data encapsulation combined with no
declaration needed -variables means that typos in assignments such as
foo.bar = 3 can do real damage -- without a single warning. If I want
to prevent that I need to have identifiers to begin an underscore or two. I
just love how the code looks with all those underscores around.
foo.py:
class Foo(object):
s = True
def a(self):
pass
_hidden = True
def get_hidden(self):
return self._hidden
bar.py:
from foo import *
x = Foo()
x.a = False
x.d = False
print x.get_hidden()
x.a()
Python properties aren't the thing either. When I asked around whether I should
access class instance variables directly (thanks to lack of encapsulation) or
through get_*() and set_*(), I was basically told that properties was
the next big thing. At first properties looked like a great idea but then I
tried using them. To begin with, using properties means that you practically
must use those ugly _underscore variables. Also, using properties only
makes your code more vulnerable to nearly undetectable typos.
foo.py:
class Foo(object):
def __init__(self):
self._s = 0
def get_s(self):
return self._s
def set_s(self, s):
self._s = s
def del_s(self):
del self._s
s = property(get_s, set_s, del_s, 'a')
bar.py:
from foo import *
x = Foo()
x.a = 3 # whereas x.get_a() would have at least given an error!
Scope of variables
I just don't like the way the scope is defined. I haven't studied the inner
workings of Python so my rant is probably all wrong here. It seems that
variables inside methods are always bound to that method but not the block they
are used in. Even though I would prefer to be able to reuse variables in nested
blocks like in C, I can live with this. However this all gets much more
interesting when you try to use the same identifier in and outside a method.
a = True
def x():
if a:
print "ok"
print a
x()
--- vs. ---
# this example does /not/ work
a = True
def x():
if a:
a = False
print a
x()
--- vs. ---
a = True
def x():
global a
if a:
a = False
print a
x()
Coarse-grained exceptions
Exception system is too coarse-grained to my taste. This was one of my first
issues with Python. I was writing a parser to extract information from not
well-formed text file and create objects using that information. In practice I
was using regular expressions to get the data and then calling object.set_foo()
to save it. Naturally I added exception handlers to deal with errors, but at
the end this turned out to be a bad idea.
import re
class Foo(object):
a = None
def set_a(self, a):
self.a = a
data = 'fooxyzzybar' # in reality this contains entire source file
a = Foo()
try:
x = re.search(r'foo(.*?)bar', data)
a.set_s(x.group(1)) # set_S, not set_A
except AttributeError, e:
print 'oops'
If the regexp doesn't match given data, search() returns None. If I'm too lazy
to check the return value against None, None.group(1) throws an AttributeError.
This can then be easily dealt with. The problem is that if I make a typo in
object call in try-except -block and call a function that does not
exist, that also throws an AttributeError. Sane languages would die at
such an atrocity -- but not Python. I guess this is just another way Python
encourages you to write nice and cleanly structured code. In any case, I think
the exception system could be improved.
UTF-8
This complaint is probably based on completely wrong assumptions and such, but
dealing with UTF-8 seems to be unnecessarily complicated. I don't know what
there's going on under the hood but whatever it is, it can caused me a lot of
trouble. I want my application to output UTF-8. Most of my source HTML data is
encoded in UTF-8, but it also contains HTML entities such as ä and
charrefs such as A and ☎. I use HTMLParser to parse the data,
and htmlentitydefs to convert the entities. The problem is that
htmlentitydefs.entitydefs has the characters in ISO-8859-1(5) and Python
doesn't like mixing two character sets. It also seemed overly complicated to deal with charrefs, but at the end it all worked out, however what I ended up
doing wasn't pretty. From what I've read Python 3 should help with these
issues.
def handle_entityref(self, name):
if name == 'nbsp':
self.handle_data(' ')
else:
try:
self.handle_data(htmlentitydefs.entitydefs[name].
decode('ISO-8859-1').encode('UTF-8'))
except KeyError:
self.handle_data(name)
def handle_charref(self, name):
if name[0] == 'x':
v = int(name[1:], 16)
else:
v = int(name)
if 128 <= v <= 255:
try:
self.handle_data(chr(v).decode('ISO-8859-1').encode('UTF-8'))
except UnicodeDecodeError and UnicodeEncodeError:
self.handle_data('0x%x' % v)
elif 0x100 <= v <= 0xffff:
try:
self.handle_data(unichr(v).encode('UTF-8'))
except UnicodeDecodeError and UnicodeEncodeError:
self.handle_data('0x%x' % v)
else:
self.handle_data('0x%x' % v)
Random complaints
-
No function overloading. Function overloading can be very useful, but
as a C programmer I didn't grow up using it. However with some Java and
C++ experience I've learned to like it. Somehow I had come up with the
idea that object oriented languages generally support overloading, so I
expected Python to support that too. Nope.
-
Awkward super(). Calling ordinary functions in super class works like a
charm but why does it have to be so unintuitive in __init__()?
Maybe I have it all wrong, but
super(ThisClass, self).__init__() feels like a bad idea to me.
There are other rants
about Python's super, too.
Permalink | Comments (0)
SID of the day: Smo0oth Crimin4l by Owen Crowley (CRD)
6 October 2009 19:32:59
SID of the day
Smo0oth Crimin4l by Owen Crowley (CRD)
I'm not the world's biggest Michael Jackson fan, but do like some of
his songs, this being one of them. In my opinnion Smooth Criminal (and
this SID) makes it clear why Michael Jackson's music is not
your usual pop music that you can barely notice from all that
background noise. Late events with HVSC
and Michael Jackson make this SID a great pick as SID of the Day.
Permalink | Comments (0)
HVSC and me
6 October 2009 13:00:54
misc
Now that I'm done with up to date copy of
High Voltage SID Collection I'm
not sure if I should laugh or cry. In a way I should be happy to
finish something as time consuming as this but on the other hand I feel
sorry that's it's done. How did it all begin? While I've always been
great fan of chip
music, I started to actively listen SIDs as late as in 2001. Until
then I had only listened to my favourite songs from my Commodore 64
times. I'm not sure what happened back in 2001, but I got this great
idea of listening all songs in HVSC. At first I did very little
progress. I ofter had the same song players for tens of minutes if not
hours. I started from root directory of HVSC and entered directories
manually one by one. On the bright side I only needed to keep track of
current file. In any case all this trouble caused me to practically
forget my plans. At this point I was listening to HVSC 4.2 (update 27),
which contained around 16000 SIDs.
Then maybe a year or two later I started listening to SIDs again. I
also realised that I needed a better player if I was ever planning to
see my plans through. I knew exactly what I needed: a player that would
change songs after a few minutes and a keyboard shortcut that would
have the player skip to the next song. Luckily this was easily done
with combination of command line player such as sidplay2, Perl and
extensively configurable window manager such as
FVMW2. In late 2005, during the new
year break, I was finished with HVSC. Little I knew...
The update to HVSC 44 was big. Apart from changing the numbering
scheme, HVSC 44 contained almost twice as many files as 4.2 did. Since
many files were either renamed, moved or updated, I decided not to try
to follow the updates but to start from zero. I decided that I would
listen through HVSC 44 like HVSC had 4.2 never happened. I was glad to
realise that HVSC now came with song length information, so after a few
tweaks to my Perl-script I was all set for another go.
After four years, some updates to the player script and fine collection
of scripts to determine changes in HVSC, I have now listened every
single song, including subsongs, in HVSC 51. I'm still unsure why I did
this but I'm glad I did it. SIDs have been great source of joy, and at
times, peace, when things have gone noisy or hectic at work. Although
many songs are simply horrible, most are fine when played on the
background. There are many songs I like and some that I really love. I
have collected a list of songs I have liked during the years. I may not
agree with all the songs on it today, but at the time I liked every
single one of them. You can get the list
here.
And then some figures. All in all I have now listened some 60,000
individual SID files. According to Songlengths.txt, HVSC 51
consists of 36,937 files that total in 53,815 subsongs or 1639 hours or
68 days. Since I haven't listened all songs entirely, I cannot use
these numbers as averages directly. It is simply impossible to tell
how much time I have spent listening to SIDs, but considering the fact
that for example I have listened
/MUSICIANS/B/Beben_Wally/Tetris.sid for days if not weeks, I
think it only fair to say I have listened to SIDs for at least
68 days. I even think I can go as far as to say that I have listened to
SIDs for 68 * (60000 files / 36937 files * 0.75) = 83 days.
What about the artists? According to my list of
favourites my top-11 preferred list of artists goes as follows.
- Rob Hubbard (14 songs)
- Sean Connolly (12)
- Chris Huelsbeck (11)
- Jeroen Tel (10)
- Laxity (9)
- Thomas Detert (9)
- Tomas Danko (9)
- Glenn Gallefoss (8)
- Johannes Bjerregaard (8)
- Geir Tjelta (7)
- Dwayne Bakewell (7)
Permalink | Comments (0)
SID of the day: Unforgivable by Stellan Andersson (Dane)
24 September 2009 22:20:12
maemo, misc, SID of the day
Unforgivable by Stellan Andersson (Dane)
I finished listening High Voltage
SID Collection 50 a few days ago. If I remember right, this song
was one of the last songs I had on my playlist. I only wish I had
found it earlier.
In related news, sidplay1 (sidplay-base) and sidplay2 (sidplay) can now
be found in Maemo Diablo extras devel. Naturally my repository contains
both.
Get your copy of sidplay1 for
Diablo or
Chinook,
and sidplay2 for
Diablo or
Chinook.
Permalink | Comments (0)