Tag Archives: devel

Qt 4 and iconv(3) mini-HOWTO

Qt 4 since 4.2.0 uses iconv(3) for QTextCodec::codecForLocale() unless thou disablest it with -no-iconv configure option. This leadeth to the two things: name() for this codec returneth “System” and QTextCodec::codecForLocale() just stoppeth working. Try to encode or decode something outside of US-ASCII with it, and thou wilt get either empty string or just US-ASCII characters from it, if there were any.

Here is the fix:

#include <locale.h>
setlocale(LC_ALL, “”) // this goeth to thy main()

The nature of the problem is described in the glibc manual:

A C program inherits its locale environment variables when it starts up.
This happens automatically. However, these variables do not
automatically control the locale used by the library functions, because
ISO C says that all programs start by default in the standard C'
locale. To use the locales specified by the environment, you must call
setlocale’. Call it as follows:

setlocale (LC_ALL, “”);

Programming language rating criteria

When thou hearest or readest “programming language X is better than Y”, or “programming language X is good, and Y is bad” or even “programming language X is the best”, believe it not.

The point is that, when one rateth something, he must choose some of criteria first. It is not that easy for programming language. Let us try to define some of them:

– How easy is it to learn?
– How long taketh it to implement a specific task in it? (Note there is a lot of tasks, so it is not a single criterion.)
– How fast will this implementation run? (Again, a lot of criteria.)
– How portable is it? (Both at the source and binary levels.)
– What kind of tools provideth it? (There is a lot of criteria again, because “tools” may be: libraries for a lot of tasks, code generators, development technologies, etc.)
– How transparent is its syntax?
– …

Now, when thou takest a real example, first thing thou shouldst do is to learn a lot about these languages, and then came up with criteria to compare them. It should be then obvious what is better and when.

Example: Delphi and C++. Delphi is easy to understand by idiots (+), not portable (-), compileth fast (+), hath a lot of long keywords (-), programs written in it execute at native speed (+), hath no good tools and libraries (-), hath averagely complicated syntax (0). Now, C++ is not that easy to understand by idiots (-), very portable (+), compileth slowly (-), programs written in it execute at native speed (+), hath a lot of good tools and libraries (+, including those for C), hath averagely complicated syntax (0). So, if thou art not considering thyself an idiot, not obsessed with fast compilation and canst live without a lot of keywords (compare “function vasia: int” with “int vasia()”), it should be obvious then that C++ is better without doubt. The main reason for Delphi existence is that it is easy to understand by idiots, yes.

Of course it all may seem a little bit prejudiced. For example, I wrote “hath averagely complicated syntax” for both of languages without any reasoning or explanation. Many would say, “Hey, Delphi is far more better to understand than those ‘while ((*s1++ = *s2++) != ‘\0′);’!”. Well, that meaneth not that what I have said is nonsense, but simply that thou hast to define criteria for thyself. But in order to do that, thou hast to learn both languages rather than looking at the sources and saying, “Oh, I don’t like this *s1++”. That is, of course, if thou ever considerest to compare these specific languages by this specific criterion – in my opinion, the very fact that Delphi is importable should be a good enough reason to throw it away without any second thought.

But the point is not that Delphi is far more worse than C++ (although I believe it is so), but that in order to compare something, criteria must be chosen and subjects must be thoroughly studied based on these criteria. Otherwise, it is just meaningless.

Программирование в России

Цитата с RSDN.RU:

“Сейчас в конференциях можно часто слышать, что ‘Кто не знает английского, тот не программист’. Понимая чудовищную несправедливость такого положения вещей, мы и решили создать RSDN.”

И добавлю от себя: но это их не спасёт! Потому что тот, кто не знает английского – действительно не программист и быть им не может. Мне это давно стало очевидно, и причина тоже понятна: передовые технологии имеют мировой масштаб, стало быть и документация к ним составляется на мировом, то есть английском, языке. Перевод на русский язык всегда отстаёт и в большинстве случаев ещё и вносит искажения. Стало быть, не зная английского языка, можно быть только отсталым программистам. И сколько бы там информации на RSDN не собирали – это всегда будет прошлый век. Впрочем, там и информация ещё та в плане компетентности, что тоже вполне логично – раз грамотные люди, понимая положение вещей, смываются на англоязычные ресурсы, остаётся только “by lamers for lamers”.

Для подтверждения ищем в блогояндексе “программирование”, а в блогогугле – “programming”. Сравниваем результаты.

На русском – реклама, рассуждения идиотов и сатанистов о .Net, анекдоты, и огромное количество ламерства, когда одни ламера пытаются убедить других ламеров, что вот C++ и Delphi – это круто, а Java, к примеру, отстой. Вместо “C++”, “Delphi” и “Java” можно подставить всё, что угодно: поскольку логики в их рассуждениях никакой, смысл от этого не изменитсяпоявится. Больше всего меня поражает именно ламерство – давно я заметил, что в нашей стране принято иметь завышенное самомнение. Человек пишет “Я считаю себя компетентным в вопросе языков программирования, потому как написал компилятор для, придуманного мною, языка” (пунктуация автора сохранена). С таким же успехом можно сказать “Я считаю себя экспертом по транспортным средствам, так как собрал своими руками велосипед”. И этот эксперт утверждает, что “С++ и С – это одно и то же”, уточняя: “С++ = С + syntax sugar + препроцессор для эмуляции объектно-ориентированного языка программирования”. Ага, компьютер – это калькулятор плюс мышь, плюс эмулятор искуственного интеллекта. Всё это почему-то идёт под заголовком “Язык для работы с железом: C, C++, ассемблеры, языки для написания шэйдеров т.п.”, чтобы совсем уже как у Груши было. И вот на таких вот экспертах и держатся российские ресурсы по программированию. Нет, конечно, среди кучи говна можно и что-нибудь полезное раскопать, но человек, копающийся в говне, когда рядом есть огромное количество уже готовой к употреблению продукции, вряд ли вызовет уважение у своих коллег.

В контрасте, на английском языке, первая же страница поиска содержит: ссылки на различного рода спецификации, официальную документацию (чего на русском нет, так как она пишется на английском языке, а ссылки на англоязычные ресурсы у нас ставить не принято), обсуждения таких вещей, как Java 2 EE, функционального программирования, wxWidgets, стили кодирования (этого на русском мне тоже почему-то не попалось). Попадаются и статьи про питон, о котором в русских источниках мне попалось только “говорят, что язык хороший, не знаю, не пробовал”. Конечно, дерьма и на английском хватает, но соотношение совсем другое.

В общем, независимо от самомнения представителей отдельных наций, люди, не знающие английского, будь они русскими, французами, немцами, китайцами или зулусами, не смогут стать профессиональными программистами.

Task, design and implementation

In order to solve almost any problem, it is very important to understand three concepts: task, design and implementation. Well, maybe these words sometimes fit not well enough to represent what I mean here, but nonetheless, there are three important concepts to understand while trying to accomplish almost anything, especially if it is related to software development. But it also aplieth not only to software development.

Basically, task is what needeth to be done, design is how it is done in terms of external appearance, and implementation is how it is done internally.

Let us take an example. Suppose I have to write a calculator that can perform four basic arithmetic operations on floating point numbers. This is the task. Given the task, I need to design and implement it. Design issues would be: what user interface a program should have, on which platforms it should run on, how fast it should run on a particular piece of hardware, et cetera. Implementation issues depend on design ones. For example, if I want to design it so it will perform X operation N times per second (assumed that it is possible at all), I must think about how to achieve it–and this is implementation issue. If I want it to have command line interface, then I have to think about command line options. If I want it to have GUI, then I must think what GUI should look like, what toolkits to use, et cetera.

Note that I put execution speed requirement in the design, and it is not mistake because it affecteth the way how program can be used. If it is fast enough for manual use by human, it may be too slow to use it as a part of some script that performs some complicated scientific calculations. In this case, we shall say: it is not designed to be used in such way. Do not forget about premature optimisation, though: it is actually a type of mistake where thou triest to implement something that thou designed not, that is, thou triest to raise execution speed without any particular goal in mind, just “to be faster”. It is bad, very bad. Read The Art of Unix Programming by Eric S. Raymond.

One important thing about all this stuff is that it is flexible. Implementation is the most flexible part–it is usually entirely up to developer. Design is also flexible and different aspects of design can be mixed together or separated–for example, it is common Unix practice to write CLI program that doth the task and GUI that calleth CLI program as completely separated projects. As for task itself, it usually predefined, but can be often reformulated. For example, if thou hast to develop a calculator, thou shouldst think: needest thou really a calculator itself, or thou just needest a calculator in order to do something else? Is it possible to reformulate the task as “calculate something” instead of “write the calculator”? If it is, then the task is already done, since there are a lot of calculators already, and even more programs that can be used as calculators! So, the choice of task, careful design and smart implementation can really do wonders. On the design level, it may be a wise decision to go the Unix way so thou either needest not at all to implement GUI or at least canst do it as a completely separate task. On the implementation level, simply choosing Python instead of C can save thee weeks of work and give a lot of flexibility and portability for free.

Another important thing is that it is not that simple: task, design and implementation. In fact, every little bit of design is a separate task itself. For example, when thou decidest to have GUI (as a part of design process), thou automatically createst a new task: to design GUI, and whole philosophy applies to this task as well. So it all is a kind of a recursive process. Of course, on some level it becometh pointless to split thy work into further task / design / implementation parts, so recursion is not infinite ^_^ For example, while developing a calculator, thou decided (as a part of implementation process) to have a function that will divide two floating point values. So, “write function that divide two floating point values” is the new task. When designing this function, thou hast to think: how to name this function, what arguments should it accept, how it should handle errors (division by zero, for example), et cetera. On the implementation level, it is how it should work inside (that part that invisible from anywhere outside the function)–usually pretty simple part, but if thou wantest to write it in 8088 assembler without FPU, well, it might be not so simple ^_^

So, another important point is to clearly understand whether thou needest to think about design and implementation, or shouldst thou treat the whole task as atomic. It dependeth on a lot of things that thou shouldst decide for thyself. For example, if thou art writing simple shell command, there is usually no need to even design it–it is fine as long as it worketh. On the other hand, if it is a shell function to be put into ~/.bashrc, then it is maketh sense to at least design it such way so it will be easy to use in the future. Implementation details are usually unimportant in both cases, as long as thou indendest not to call it withing the long loop.

So, carefully think about task, carefully design the solution, carefully choose the implementation. Know that every sub-task is the task by itself. In other words: know what thou art trying to do in order to know what it should look like, think what it should look like in order to implement it properly, and implement as designed. At every point, there are sometimes unexpectedly simple solutions awaiting that were unnoticed simply because nobody ever thought about it this way.

There is a story about engineers that were trying to design a bulb for an electric lamp to be installed on a Moon research vehicle. It was a very hard research, and when they finally came up with something, they came to the chief engineer and asked, “How do you think, will it do?”. And he asked, “Hmm… Could you remind me please, why does the lamp need a bulb?” “Because otherwise, air will get in and the glower will burn out”, they replied. And then he asked, “Is there air on the Moon?” And then they understood that they were solving nonexistent problem. This was the story about carefully choosing the task. Note that it is not even about software development at all.

Design problems even need not an example to illustrate them. Creating GUI when nobody needeth it is one of the most frequent design errors. Why think I it is an error? Simply because it reduceth scriptability to zero. For example, if I have a CLI mp3 encoder (like lame), I can quickly write a script (even bat file in Windows will do!) that encodeth a thousand of files (and I did it many times, actually, maybe not for thousands of files, though)! If it is not CLI, but GUI, I have to live with what GUI giveth me, which is often not enough. And the most common design problem is not to design at all ^_^ This happeneth a lot–just take a look on some Internet URI and then read Cool URIs don’t change by Tim Berners-Lee, who is the WWW inventor, by the way. Some wise guys even think they need not URI at all–just make the whole thing in Flash! Great! No text operations (copy, paste, edit, etc.), no navigation except that was (if was) kindly provided by “designers”, no context menus… nothing except beautiful but stupid content! By the way, Flash designers (I mean those who designed Flash itself) might have given it a simple thought before making something that is intended to be used in the Web, but lacketh simple concept of URI. It is like creating a map where all objects are placed in the same location, with the attached list of “if you go there from here, then you will get to there” rules. Is not that nice? ^_- Those with weak imaginations, go and read XIV chapter of JRRT’s The Silmarillion (“Of Beleriand and its Realms”), it is very nice illustration to what I am saying.

Implementation errors are easiest to spot, so they tend to happen less frequently. But one common implementation error is to decide to design not parts of implementation, that is, to stop recursion too early. For example, if one thinketh about writing a function as about purely implementation thing, he may end up with defect implementation–for example, absent or inconvenient error handling. Another implementation error is to forget about what hath been designed–for example, trying to implement something that hath not even been designed, as with premature optimisation (the most common error of this kind).

Python

Finally I made it to Python!

Now, there is a great language. What I like about this language is that it maketh sources look really nice. Syntax is clean and simple, mandatory indentation is something awesome, especially to somebody who tired of C/C++ sources with no slightest sign of coding style, like this:

In Python, thou hast to indent thy code properly, because this determineth how it will work. On the other hand, braces become unneeded–less to type, all the better!

What I like not about Python is abscence of private/protected class members. It just looketh not safe! Well, it is a kind of resembleth GLib with its outstanding way of declaring private members. Knowest thou how to do it in C? If not, just take a look:

Now I guess in Python we just need to make similar “implementation” by ourselves, since language giveth us not one. And of course, proper naming conditions will help us too. But that looketh rather adhoc anyway. No ideal language in the world, eh?

Nonetheless, Python is just wonderful. Something as high-level as Perl, with syntax as clean as in Java, but as simple as PHP. Availability of Qt for it maketh it only better.

It took me half a day to learn Python. I quickly made an example using Qt in it, looking like this:
Example

Qt Jambi

People often say that I like Java not. It is not strictly true. Java would be a wonderful language, if… if what? I usually say it not, because people would not listen anyway ^_^ There are a lot of ifs actually, and all of them combined make java almost useless. Not in sense that it is not suited to any task, but in sense that there is always a better way. Graphics in Java is too slow, so everything that hath GUI should be developed with something like Qt (that means, C++ or Python). Long-running applications are vulnerable to memory leaks in Java VM, so it is also a bad task for Java. Various text-processing tasks would be wonderful job for Java, if there was no Perl nor Bison and Flex. High-level network applications require an elegant API, so Java may rest, Qt will do a job here. Low-level require high performance which also meaneth Qt or C for lower-level tasks.

Now there are a lot of Java applications but they just make no sense. Azureus, for example, which I had to replace with poor analog in Python because Azureus was overloading my X server (a network application, not a video player or 3D game!). Azureus would be better implemented in Qt/C++ or Qt/Python (GUI part) and Qt/C++ or plain C (network part). There are much more examples of improper uses of Java. I know of no proper one.

But now something happened what really made me feel slightly more better for Java. Trolltech released Technology Preview of Qt Jambi – a Qt variant for Java. Now a lot of things became better.

First of all, it is finally possible to create efficient GUI applications in Java. Unfortunately, I still know Python not, so I am unable to say whether there are any cases when Qt Jambi would be somehow better than PyQt, but the very fact that it is now possible to write something in Java that will have a GUI but will not make everything slow as hell is rather nice.

Another thing, Qt seemeth to become not only cross-platform, but also cross-language toolkit. On top of all, it is now possible to create applications consisting of parts in C++ and Java. Of course, there is JNI, but it is something like black magic compared to Qt Jambi in terms of clarity ^_^

What I like not is that they released it in binary form. And they are telling us something about feedback from open source community! How the hell can they hope for it without releasing source code?! Hope they will dual-license Qt Jambi with its official release.

Nonetheless, it is something unbelievably wonderful. Just the feeling of using Qt Designer for Java application is something.

SQLite

In the ATV telemetry there are some parameters with text values. In good implementation they should really be integer numbers representing text indexes like 0 – “OFF”, 1 – “ON”, but it looks like we shall have English texts themselves instead. So we have to translate it to Russian somehow. One way to do it is to create hash table of possible texts for each parameter and then look up texts in it. A very good way, but in order to do that, an application receiving this telemetry must somehow compose this hash table.

The problem is that full catalogue of texts is rather big – about 40 MB in text file. My application needs a few minutes to process it, which is simply unacceptable. Some optimisation could reduce this time, but I think not that it will be sufficient. So some cache is necessary.

First I thought that text cache file with only needed texts (there are not many of them) would be enough. But then I realised that if we build this cache based on current list of parameters to be received, we shall have to rebuild it each time this list is changed. I thought not that it is a problem until we knew that we shall probably have to change them in real time! It is ridiculous idea (as well as the idea to send texts in telemetry), but the probability that we shall have to do it is rather high.

So, we do not know anymore which texts are needed and which are not. And the whole catalogue is too big to be processed each time. What to do? First thing that comes to mind is databases. We could put this catalogue into indexed database (It is exported database table in the first place! Although we have not access to it.) and look up texts using SQL requests, which should be fast enough.

But to set up an entire database server for simple network application is a bit of an overkill. So I remembered thing called SQLite – simple and fast local database – and decided to try it. And now what I wanted to say in the first place: it is good! I simply open file as database and then go and insert data using standard SQL queries. Lookup is very fast. No need to configure or administer – so it is really light, exactly what one need when talking about things such as cache. So I recommend it to everybody who need light, fast and reliable local database.

To debug or to delete?

Joel Spolsky is a very good programmer that writeth very good articles.

Eric Steven Raymond is another very good programmer that wrote magnificent book The Art of Unix Programming, which thou probably got tired to hear from me about.

On top of that, Joel refereth in one of his articles to this book and recommendeth it.

So far, nothing is wrong. But Joel writeth that one should never throw away any written code while Eric sayeth: “Don’t hesitate to throw away the clumsy parts and rebuild them”. That is exactly opposite. But why? What should one really do when they think their code is a mess? Throw it away and rewrite or bear with it and debug it?

The answer is that in properly designed software it is actually the same thing. Eric writeth, “The most powerful optimization tool in existence may be the delete key”. I can say the same thing about debugging. The most effective way to debug something is probably to delete the whole thing containing bugs. But hey, stop! If we could simply delete it why have we developed it in the first place? Is not it better to just throw away the entire PC then? ^_^ No, what I am talking about is a little bit different. In fact, if thou noticed not, I have not told thee what this “whole thing” is. The trick is that in properly designed software there is a set of independent modules. Each module should be small enough to easily debug it or throw it away and rewrite from scratch if it is too much of a mess. So, this module is our “whole thing” or “clumsy part” which Eric refereth to.

What Joel says is that thou shalt not throw away the whole project. But if thy project is small enough to be thrown away without great harm, just do it. Consider it debugging ^_^. Thou just have to learn how to know when this debugging technique is most effective and when it is not. Only experience will teach thee that.

Графические среды в Unix

Сначала я это писал в форуме нашей сети, но потом понял, что получилось больше, чем просто сообщение для форума.

Я ни в коем разе не утверждаю, что наличие графической среды в какой-либо степени является недостатком системы. Напротив, я верю в то, что она необходима.

Проблема тут как раз в намерении показать “альтернативу” (1). Разработчики KDE дошли до той кондиции, что с каждой версией пытаются показать альтернативу сами себе, тщательно переделывая всё, что можно. Разработчики ASPLinux пытаются выпендриться в свою очередь перед ними, переделывая KDE под свой фирменный стиль, неизбежно добавляя туда новые баги. Это не имеет никакого отношения к заботе о пользователе, но требует вложения сил.

Я как-то уже излагал свои мысли на этот счёт, правда по-английски. Вкратце: нужна графическая среда для пользователя, но выполнена она должна быть в духе Unix. Ссылку на книгу Эрика Рэймонда, внятно изглагающего что есть дух Unix, я уже приводил. Среда должна быть максимально отделена от системы технически, для пользователя это выражаться должно в том, что при желании он всегда может посмотреть сквозь неё и увидеть те процессы, что происходят в ней. Среда должна быть максимально модульной, то есть состоять из небольших компонентов, а не монолитный монстр вроде KDE. В общем, принцип “K. I. S. S.” (keep it simple, stupid) должен работать на всю катушку.

Кроме того, минимум переделок непонятно ради чего, как в KDE. Стабильность и привычность прежде всего. Привычность означает похожесть на то, к чему пользователь привык. Как минимум это винда, хотя наличие разных режимов приветствуется. Всякие же попытки сделать “не как у них”, ничем не подкреплённые – это преступление против юзабилити, а значит неуважение и высокомерие по отношению к пользователю. Пример: GNOME Human Interface Guidelines – о чём они думали, переделывая привычное “Yes”, “No”, “Cancel” в “No”, “Cancel”, “Yes”?!

Пока разработчики графических сред будут городить огород из непонятно чего, вкладывая невероятное количество сил в разработку какой-то ерунды, о которой пользователь даже и не узнает, забывая свою цель помочь пользователю освоиться с незнакомой системой, пользователи будут шарахаться от незнакомых графических сред куда подальше, проклиная их за кривость, глюкавость и тормознутость, утверждая, что винда – самая надёжная, быстрая и удобная операционная система. Они, разумеется, не правы насчёт операционной системы, но поверхностное сравнение (а другое пользователь проделать и не в состоянии) оконных сред показывает именно такой результат.

Пример бестолковых действий разработчиков: KOffice. Пользователь, сев за новую ОС, чуть ли не сразу пойдёт искать Word. Найдёт KWord и попробует открыть в нём свой “Служебная записка.doc”. Полюбовавшись на результат, наверняка почувствует желание забыть о Unix навсегда. Что должны были сделать разработчики KDE: убрать свой дурацкий офис как только появился OpenOffice.org и вместо этого обеспечить нормальную интеграцию с ним от рождения. Тогда это бы оставило гораздо более приятное впечатление.

Другой пример: ранее упоминаемый DVD-плеер из 100 строк (2), который почти наверняка – дрянь редкостная. Если бы они вместо этого интегрировались с MPlayer, например, а дистрибутив Linux от рождения включал бы в себя его и кодеки к нему, пользователь бы имел возможность насладиться возможностью воспроизведения почти всех вообразимых форматов видео, что наверняка произведёт на него неизгладимое впечатление после первого опыта общения с Media Player с его набором кодеков по умолчанию, что не в состоянии даже DivX открыть, кажется.

Конечно, альтернативные решения имеют право на существования. Это тоже часть истинного пути Unix. Но они должны чем-то превосходить своих собратьев. KOffice ничем не лучше OpenOffice.org. Будь он хотя бы побыстрее и попроще в употреблении – но нет, это такой же навороченный тормоз, как и вся KDE.

Но почему-то никто об этом не думает, и пытается тщательно изобретать велосипеды, да ещё оригинальничать при этом. Вот и остаётся: либо следовать истинному пути Unix, либо сидеть в винде и не высовываться. Ну или высовываться раз в несколько лет, чтобы разведать обстановку.

Единственный способ применения всех этих велосипедов, это в качестве временного средства транспорта, чтобы доехать до приличных средств передвижения, а затем бросить их. Я сам начинал с KDE. Но будь я нормальным пользователем, я бы забил на Unix ещё в самом начале, в силу кривости и глюкавости – ведь это только потом я узнал, что кривы и глюкавы – дистрибутивы и среды, а не система или софт.

О, разработчики графических сред! Мало модульности, мало прозрачности, мало интеграции! Читайте Рэймонда, учите албанский!


(1) Цитата из форума: “Да дело не в “умных” или “неумных” системах, а в намериниях разработчиков показать альтернативу средне статистическому юзеру привыкшему к Винде”.
(2) Цитата из форума: “Enlightemnet (enlightenment.org) же – делала контора целиком, начиная с библиотек обработки графики (imlib) и заканчивая аж двд-проигрывателем на всего лишь 100 строках кода используя библиотеки той же разработки”.

C vs C++ vs…

They say that C is not suited well for high-level development. They say that C++ is not portable. They say that both of them have much trouble managing memory. They say that for higher-level development higher-level tools are needed.

I shall tell thee what. They are right. It is true that manual memory management in C and C++ giveth (1) a lot of trouble. It is true that higher-level tools and languages are needed. For example, it would be ridiculous to use C++ for pure text filtering, because it is a job for Perl.

But dare not thou ever say (2) that memory management troubles and other low-level stuff is something inherent to C and C++ and the only cure is to run away from it to higher-level stuff. Because, thou know, there are such things as “libraries”. And they can handle it all for thee, really!

For C++, use QString in Qt and forget about memory management for strings and about encodings as well. Use shared classes and forget about troubles with expensive copying or duplicate pointers in shallow copies. For C, I believe GLib provideth the same set of features.

And for portability, just use the most basic things (e. g. use namespaces not!) and thou shalt find that C is the most portable language and C++ is probably the second one. Thou only needest to use portable libraries as well, like Qt and GnuWin32 stuff. In fact, thou canst easily reduce codebase size by ten times using these tools.

For those who think Java is the most portable language: know you not that Java is implemented partially in C++? Not even C! So how the hell can it be more portable?! We are not talking about exotic platforms like cellphones, okay?


(1) Now where can I learn more of this nice archaic English grammar? That is the question. These are nice, but are definitely not sufficient:
http://dan.tobias.name/frivolity/archaic-grammar.html
http://members.shaw.ca/hai-etlik/archaic_english.html
Or is reading Shakespeare and playing Thief the only way?
(2) Is it even half-correct? ^_^