My last post about the sorry state of my workflow triggered a few answers :
many thanks!

The most interesting was to use a database : after all, organizing data is
the whole point of databases, doesn’t it?

So I looked around for what is available to make my life easy, and found
glom (well, I had already read a few blog posts about it on planet gnome, but
never dug into it).

It turns out it’s not in debian (and probably won’t anytime soon : there is a
package in the works since so long…), and that its dependencies aren’t up to
date anyway.

So I chased them one by one, using the sources and debian’s .diff.gz to get
updated packages (I hate using ‘make install’) — as an aside, that reminded
me a lot about the early days of gnome. Sigh. I was so patient at that time.

Finally, I could compile and install glom (using ubuntu’s .diff.gz to get nice
packages this time, since debian lacked the equivalent). It even ran, but it
was a little too unstable for my taste : starting and stopping the database
gave issues, it didn’t like my passwords, for example [yes, I reported].

These stability issues mean I can’t use it for work, but I’m still pretty
impressed by what I saw, and I’ll have to find a problem to solve with. If
said problem doesn’t exist, I’ll just invent it 😉 .

Using a database directly didn’t look as promising, so I left that option out.

Embedding the tags into my files directly definitely is out too : it’s gross,
and would assume I only have text files, where it’s easy to embed things. This
is the case with texmacs files, as are most of the things I use (giac/xcas,
maxima, gnuplot, C, C++, …), but what if I want to associate an image to an
exercise? or anything binary-based where embedding text and using grep isn’t that easy?

So I went for the solution where I store the metadata separately, in helper
files. And I stored the metadata as XML files, since that’s both easy to use, and extensible.

At first, I tried using C+libxml2. The first tests went pretty well, and things looked
pretty promising. Then I typed something like :
$ ./exo-tag-create “Réduction d’endomorphismes”
12
$ ./exo-tag-text 12
<partial garbage>

I tried to use a few magical functions (g_locale_to_utf8, for instance) to
sanitize my strings before I feed them to libxml2, but couldn’t get things
right. I just hate when a stupid little thing completely unrelated to the
problem at hand gets in the way — I didn’t expect any issue since my env has
“LANG=fr_FR.UTF-8″… so things should have just worked!

When a problem doesn’t surrender fast enough using an approach, the best is
generally to try another one. I dug to see if ocaml had gained a decent XML
lib since last time I searched for one… unfortunately, no (such a shame for
such a beautiful and powerful language!), and I didn’t want to dust off the code
I wrote last year for babili.

Next try : apt-cache search python | grep xml
The debian description of python-lxml mentioned it used unicode strings, so I
settled on it, and quickly tried to build a pair of scripts to test if my
little problem still applied : no. Perfect!

So I wrote a first series of scripts to manage tags and then another to
manage items. Since there was too much code duplication, I refactored things.
Then I tried to write gtk+ helpers using the refactored code : easy. Then little
scripts to split my existing texmacs files into chunks, and join chunks into
a new document. I don’t have all I need yet, but it takes a pretty exciting
shape already.

Python saved me. It made things pretty easy, but I can’t help to
dislike it nonetheless : that language is too weakly typed for my taste (even
if using pychecker helps to alleviate this). I really prefer more serious
languages like eiffel or ocaml (the later leads to terser code : type
inference rules!).

In a few months (or years, if necessary), I’ll be able to push my data to a nice
database. And if so, I really look forward to using glom.

7 Responses to “Better workflow : saved by a rampant”


  1. I guess that space-in-password bug was from you, which I fixed in libgda. Thanks for reporting it. There’s a problem with the shutdown of the self-hosted postgres database sometimes, but there’s no other crasher or instability bug currently reported for Glom.

  2. Ali Sabil Says:

    Hi,

    I would like to note that python is not weakly typed, it is in fact strongly typed. You seem to confuse dynamic typing with weak typing.

  3. Snark Says:

    Well, as I said, I plan on waiting a little before I give glom another try, but the version I compiled with all dependencies gave me a hard time connecting to the db, then couldn’t stop it — that is already too much for a professional use : you have to keep in mind that sometimes I have under a minute to come up with an exercise fitting my needs!

    And I don’t confuse dynamic typing with weak typing : if I do something like:
    >>>def foo (a):
    … a+1
    … a+’1′

    the interpreter will just accept it. I will even be able to do help(foo) and learn it is a function with a single argument (but without knowing exactly what is expected)…

    If I try to do likewise with the ocaml interpreter :
    #let foo a =
    a+1;
    a+’1′;;
    then it will complain with a warning that a+1 is an integer which will be lost since I don’t catch this result (a warning which makes it clear the interpreter now knows a is an integer), and an error because the types are inconsistent in the next line. This is what I call strong typing.

    Oh, and if you wonder about the type of something, just type it and the interpreter will tell you :
    # (+);;
    – : int -> int -> int =
    # (+.);;
    – : float -> float -> float =
    (the ‘+’ is a function which takes two integers and returns an integer, and ‘+.’ two floats and returns a float — yes, it’s so strong it won’t do automatic conversions!)

    If you think that means code reuse is very low because of this strong typing, consider the following function definition :
    # let foo = a#foo;;
    (here you have to know that a#foo is calling method foo of object a)
    the interpreter answers :
    val foo : -> ‘a =
    which means my function ‘foo’ takes a single argument, which is a class with a method ‘foo’ which return something of an unknown type ‘a, and has a result of type the same unknown type ‘a…

    Ocaml is both strongly typed and dynamically typed!

  4. Ali Sabil Says:

    Hello again,

    now you seem to be putting dynamic typing, strong typing and type inference into the same bag …

    Python is dynamically typed, and strongly typed.
    OCaml is statically typed, strongly typed and makes (very clever and good) use of type inference.

    Concerning the python code you just showed, that code generally will not work, and you will get a TypeError on runtime.

  5. Snark Says:

    No, I do not put those in the same bag at all ; there are several things to take into account :
    (1) strong typing : everything has a type, even functions (for their arguments and return value), which can be attained either :
    (1a) by declaring them explicitly (eiffel, C++, OCaml if you want to) ;
    (1b) by automatic inference (OCaml)
    Python doesn’t have that, so it’s weakly typed : it will realize the code is incoherent only at runtime, and only if it goes down that codepath (pychecker helps on this problem — but it’s not builtin!).

    (2) dynamic typing : the method being called depends on the exact type of the object, not on the base type it had on compile time. This is always the case for weakly-typed languages (python) : they don’t have the choice. And for strongly typed languages, this is the default too (OCaml and eiffel), the stupid exception being C++, where you need an explicit “virtual” keyword to get something sensible.

    Example code :
    # class bar (id: int) =
    object
    method foo =
    print_string “bar”;
    id
    end;;
    class bar : int -> object method foo : int end
    # class baz (id: int) =
    object
    inherit bar id
    method foo =
    print_string “baz”;
    id
    end;;
    class baz : int -> object method foo : int end
    # let f (x: bar) = x#foo;;
    val f : bar -> int =
    # let b = new baz 2;;
    val b : baz =
    # f (b);;
    baz
    – : int = 2

  6. Serge Says:

    You’re using your on definitions of weak, strong, dynamic and static typing. The common definitions are: static – types are determined before code is run, dynamic – types are determined during code execution, strong – language avoids implicit type conversion and ad-hoc polymorphism, weak – language favors implicit type conversion and/or ad-hoc polymorphism.

    Python is known to have dynamic and strong typing system.

  7. Snark Says:

    I don’t like those definitions that much : the idea that dynamic is on runtime and static is on compile-time is all nice and well until a language which does part of the job on compile-time, and part of it on runtime…


Leave a Reply

You must be logged in to post a comment.