The best kittens, technology, and video games blog in the world.

Saturday, July 15, 2006

Friday, July 14, 2006

Gmail sucks

Gmail is kinda cool for regular mails, but it's horrible for mailing lists.

The feature it lacks is "ignore this thread" button. Very often there are threads that are completely uninteresting, or maybe they were interesting at first, but became flamewars later. Now the notifier is flashing every 5 minutes and you don't know whether it's an actual mail or simply the flamewar going on.

There isn't even any obvious way to make notifier ignore mailing list trafic. First, one cannot create filters on List-Id (only on From, To, Subject and body), and even if it worked, Firefox gmail notifier doesn't have such option.

Kmail supposedly has this thing done right, but I'm not very enthusiastic about having one more big program running all the time on this small machine, and email being available only when I'm here. I'll probably just drop all mailing lists, they're waste of time anyway ;-)

Metaprogramming koans

I found more koans for expanding awareness. Compared to callcc koans, these are much simpler, except for trick with evaluating default block argument in instance context.

It seems that most people did it Scheme way (with hygienic macros analogue), but I followed the Common Lisp path to enlightenment with gensym and $gensym_counter ^^; That was pure fun evil. Of course binding variables in lexical context is almost always better than gensyming in Ruby.

Continuation koans

Zen Panda from Airy Nothing.
Callcc is the ultimate control structure, but it requires some getting used to. Continuation koans will help you meditate callcc to expand your awareness.
taw@taw-desktop:~/koans$ ./continuation_koans.rb throwcatch.rb
koan_01 has expanded your awareness
koan_02 has expanded your awareness
koan_03 has expanded your awareness
koan_04 has expanded your awareness
koan_05 has expanded your awareness
koan_06 has expanded your awareness
koan_07 has expanded your awareness
koan_08 has expanded your awareness
koan_09 has expanded your awareness
koan_10 has expanded your awareness
mountains are again merely mountains
As far as I know the only mainstream languages in which callcc is available are Ruby and Scheme (and maybe Smalltalk). There was once Python fork (Stackless Python) with callcc, but it's dead. And there is some talk about adding callcc to Perl 6, but we all know it's Duke Nukem Forever of programming languages ;-)

Thursday, July 13, 2006

Autovivification in Ruby

W00t, one of my favourite Perl features can be ported to Ruby in just a single line of code. As everyone knows, in Perl it's possible to write:

$x{a}{b}{c}{d} = "e";
And all intermediate-level hashtables will be created automagically. This is often extremely useful. On the other hand in lesser languages like Python or Java the only way to set a value in a nested hash is to create intermediate-level hashtables by hand:
x={}
x["a"] = {}
x["a"]["b"] = {}
x["a"]["b"]["c"] = {}
x["a"]["b"]["c"]["d"] = "e"
This may be a small thing, but multi-level hashes are used so often that one actually misses this functionality. For long I thought that Ruby doesn't have autovivification. And well, it doesn't have the full Perl thing, but it can get reasonably close with just this small definition:
def autovivifying_hash
   Hash.new {|ht,k| ht[k] = autovivifying_hash}
end
And now you can say:
x = autovivifying_hash
x["a"]["b"]["c"]["d"] = "e"
And that's going to be good enough most of the time :-)

Wednesday, July 12, 2006

List of things that suck in Ruby


As Bjarne Stroustrup said: "There are only two kinds of programming languages: those people always bitch about and those nobody uses". Well, let's bitch about Ruby. And not about lame things like performance or libraries, but about expressiveness.

  • It's not possible to change class of an existing object. Now, why the heck would anybody want to do that ? It is actually quite useful - you use object factory to create user interface widgets from XML, determining their look, and then move them to subclass to determine their behaviour. Without this we have to use some ugly tricks. evil.rb lets us do that in some cases, but not with UI widgets. Languages where it works: Perl.
  • Ruby has really nice and concise syntax with one nasty exception - one needs to write end almost all the time. Relying on whitespace instead would make the code look much nicer. Languages where it works: Python, Haskell.
  • Keyword arguments to function are not ordered. foo :a => 1, :b => 2 is identical to foo :b => 2, :a => 1, and that's often not what we want. Languages where it works: Perl, PHP.
  • irb doesn't remember command history between sessions. Languages where it works: Octave.
  • Most libraries use Java-style constants with huge namespace prefixes instead of real Ruby symbols. So we have Gtk::Widget::TEXT_DIR_RTL which evaluates to some number instead of :rtl which would simply be converted to number on call (actually it's converted to magical object, not to a number, but that makes little difference). This makes many APIs a lot harder to remember and a lot less natural. And adding Enums to Ruby would be going in completely wrong direction. Languages where it works: it sucks in all languages I know, but that's no excuse ;-).
  • Symbol is not Comparable. I don't care what's the order between :foo and :bar, but there should be some. Without it, it's impossible to sort structures that contain Symbols (to get canonical representations etc.), and that seriously limits Symbol's usability. Languages where it works: Prolog. It does not work in Scheme or Common Lisp.
I think all these issues are reasonably easy to fix.

Monday, July 10, 2006

More movies


Some recently watched movies, in approximate order of coolness:

  • All about Eve - A great movie about how evil can people be in their quest for fame and greatness. There are well developed characters, great acting, and even an actual plot.
  • Hotel Rwanda - A genocide story. It's much more realistic and interesting than all the lame Holocaust movies. The characters actually feel real, completely unlike Schindler's List cardboard.
  • Chinatown - A film noir classic. It is evil, it is sick, it has complex plot, and it is fun.
  • Touch of evil - Another film noir classic. A little less twisted than Chinatown, but with more cool camera effects. Like the must-see opening scene.
  • The Great Dictator - I thought Charlie Chaplin movie would be idiotic commedy about slipping on banana peels and stuff like that. Surprisingly it wasn't. The movie tries to be serious and funny at the same time, and it kinda works.
  • Rebecca - I kinda liked it, but it was so slow. And the characters somehow didn't seem very believable.
  • 2001 A Space Oddyssey - A "hard science fiction" classic that is lamer than Star Trek: The Original Series as far as realism is concerned. Were people back then so scared of the computers or what ? And the monkey scenes are not even silly, they are plain dumb.
  • The wizard of Oz - Now who the heck voted that to IMDB top list ? The movie throws away all social commentary from the original book, and replaces it with a children story. So lame.

Monday, July 03, 2006

Unit testing

Good karma for Ruby and for Extreme Programming today. I've just tried to port libgmp-ruby from handmade testing system to Test::Unit. It is totally sweet:


#!/usr/bin/ruby

require 'test/unit'
require 'gmp'

class TC_Z < Test::Unit::TestCase
   def test_init_null
       assert_equal(GMP::Z.new(), 0, "GMP::Z.new() should initialize to 0")
   end

   def test_init_fixnum
       assert_equal(GMP::Z.new(1), 1, "GMP::Z.new(x : Fixnum) should initialize to x")
   end

   def test_init_z
       b = GMP::Z.new(1)
       assert_equal(GMP::Z.new(b), b, "GMP::Z.new(x : GMP::Z) should initialize to x")
   end

   def test_init_string
       assert_equal(GMP::Z.new("1"), 1, "GMP::Z.new(x : String) should initialize to x")
   end

   def test_init_bignum
       assert_equal(GMP::Z.new(2**32), 2**32, "GMP::Z.new(x : Bignum) should initialize to x")
   end
end
Executing this script runs all the tests:

$ ./unit_tests_1.rb
Loaded suite ./unit_tests_1
Started
.....
Finished in 0.006574 seconds.

5 tests, 5 assertions, 0 failures, 0 errors
Do you see any executable code, any list of tests to run ? Nah, it works by smoke and mirrors. We're going to leave XML BDSM to Java programmers, they seem to like it. ;-) It even found an actual bug in libgmp-ruby (something was pointing the wrong way around) in the first 5 minutes of testing. That's kinda cool. You can use multiple assertions per test, fixtures and so on. It still works by magic.

class TC_Q_Basic < Test::Unit::TestCase
   def setup
       @a=GMP::Q.new(100,11)
       @b=GMP::Q.new(200,17)
       @c=GMP::Z.new(40)
       @d=2**32
   end

   def test_add
       assert_equal(@a + @b, GMP::Q(3900, 187),       "GMP::Q should add GMP::Q correctly")
       assert_equal(@a + @c, GMP::Q(540,  11),        "GMP::Q should add GMP::Z correctly")
       assert_equal(@c + @a, GMP::Q(540,  11),        "GMP::Z should add GMP::Q correctly")
       assert_equal(@a +  2, GMP::Q(122,  11),        "GMP::Z should add Fixnum correctly")
       assert_equal(@a + @d, GMP::Q(47244640356, 11), "GMP::Z should add Bignum correctly")
       assert_equal( 2 + @a, GMP::Q(122,  11),        "Fixnum should add GMP::Q correctly")
       assert_equal(@d + @a, GMP::Q(47244640356, 11), "Bignum should add GMP::Q correctly")
   end
end

Sunday, July 02, 2006

Linux permissions system rant


Hello, today I want to rant about Linux permission system and how totally broken it is.

Summary of the system: In the Linux permission system each program gets one User-ID and a set of Group-IDs. Objects in the file system belong to some user, and may also be accessible to some group. Processes with the same User-ID can control each other (stop, look inside etc.). Also any process with User-ID 0 (root) can do whatever it wants to the system, including changing own User-ID/Group-IDs. Some executable files on the system may have SETUID/SETGID flag set, what means that when they're run they get an extra User-ID/Group-ID.

This is pretty much the same system Unix had 20 years ago. I think we should drop it completely and get a one that actually works.

Here's a short list of things that are wrong with the system:

  • Group-IDs are per-process, not per-user. So if user fred is added to group audio, so he can play music on the computer now, the programs he is running still aren't in group audio ! So he has to log out and log in again before the change is effective. Reboot after every change ? Is it Windows 95 or what ?
  • Of course the permission system isn't even supposed to run like that. The only user who can control audio should be the one that is currently logged-in to the physical console. One that is logged remotely should not have any access to the audio system. This is pretty much unimplementable with the current permission scheme.
  • There are no sandboxes, in particular there are no sandboxes for normal users. So it's impossible to run untrusted programs without risk.
  • There is no real nouser/nogroup. Each program in nouser/nogroup can mess with other programs in nouser/nogroup.
  • There are no per-process root sandboxes either. So one cannot start a foobard server in a way that even if the server is compromised, it has access to nothing outside. If the server runs as foo User-ID it can mess with other servers with the same User-ID. Even if there's no other program with the same user-id now, it can still create a SETUID binary and control servers running with the same User-ID in the future.
  • Normal users cannot install programs using standard interfaces. They should be able to install whatever they want for themselves (even if system-wide instalations still require administrator permissions).
  • For single-user systems, having to remember user and administrator password is silly. Well, Ubuntu is a bit better here using sudo instead of a root account.
  • Users cannot make public only one subdirectory of their home directory without granting some access to their whole directory. One might want public ~/public_html/ and private everything else. It can't be done (unless public_html is outside the normal directory hierarchy).
  • There are no guest accounts, which would be created just for one session without being able to affect other guests.
So it sucks for single-user desktop, it sucks for multi-user desktop, it sucks for public access terminals, and it sucks for the server. Why are we still keeping it ?

Full Metal Panic: The Second Raid

Some more recently watched stuff - Full Metal Panic: The Second Raid is more like the original series, and not like Fumoffu. It is sometimes a bit darker than the original and I'd rather they didn't add those parts to an inherently cheerful series like FMP.

This is quite funny - in Full Metal Panic the best part I like most is the filler and the main plot is passable, but not all that great. My favourite series is Fumoffu and it consists of 100% filler and pretty much no plot.

Oh well, there is enough filler in TSR too, so it isn't that bad :-)