Russel’s paradox states that there must not be a set y:={x|x∉x}, because then y∈y→y∉y and y∉y→y∈y.

In my younger days, when I had less knowledge but more time and fun when increasing it, I had a time when looking for paradoxes inside common theories. I simply didnt want to believe in the consistencies of the theories we have. I was desperately trying to get articles from Eduard Wette and liked hearing about failures mathematicians had made in the past. Well, this time wasnt too long, and soon I realized that searching for paradoxes in common theories is not useful anyway, since if they really arent consistent, either we will never know (and thus dont have to care) or we will notice someday and then adapt our theories. Anyway, on some day at this time, somehow I was thinking about the Russel Paradox and what happened to it if you did formal set theory inside number theory. Thinking deeper about it, I had a strange result which I firstly didnt quite understand.

First, lets not be too formal – such that you can understand my confusion at first sight.

Lets consider ℕ, the standard-model of peano arithmetic. As Gödel did, you can encode propositions about natural numbers in natural numbers themselves. Lets denote by [P] the natural number encoding the proposition P. Especially, you can encode every proposition with one free variable as a number, and a proposition with one free variable is something similar to a set of natural numbers. So lets denote by n∈ℕ[P] the fact that P(n) holds (and define it to be false if the second given argument doesnt encode a proposition with exactly one free variable). Now, ∈ℕ is a binary relation between natural numbers, which can be expressed inside arithmetic, and so is its negation, which we denote by ∉ℕ. Then the proposition n ∉ℕ n has exactly one free variable, and can also be encoded as a natural number, say m:=[n ∉ℕ n]. Now assume m ∈ℕ m. Then, by definition of m, we have m ∉ℕ m. Same vice versa. Sounds like a contradiction.

Ok, well, something obviously went wrong. Lets get a little more formal.

The first flaw is that we may be able to denote every proposition about natural numbers, but not the question whether it is true. Because we have to give a finite relation which tells when a given proposition should be true. Thus, lets redefine our ∈ℕ relation by n∈ℕ[P] saying “there is a formal proof of P(n)“, or in signs ⊦P(n) – it is known that this is possible. Then again consider our m:=[n ∉ℕ n]. It applies to all [P] such that ⊦P([P]). Again, we may ask whether m ∈ℕ m. This time that means ⊦m ∉ℕ m. That is, if m ∈ℕ m then we can prove that m ∉ℕ m which is a contradiction. Hence, m ∉ℕ m if any. At this point we had the contradiction above.

But this time, m ∉ℕ m means ¬⊦m ∉ℕ m. That is, there is no formal proof for m ∉ℕ m. At this point, we have shown that m ∉ℕ m is not provable in peano arithmetic, but that it is indeed true in ℕ. That is, we have a proposition that is true in the standard model, but not provable, like the one Gödel created.

And if you think about it, you will notice that actually we created exactly the same proposition as Gödel did, namely a proposition stating its own unprovability. But essentially we have followed the same idea as done in Russel’s Paradox.

The main difference is that in Russels’ Paradox, we assume some “omniscient” decider for the ∈-relation, while in ℕ we also assume an “omniscient” decider for the arithmetic relations we have, but we cannot assume an “omniscient” decider for meta-propositions [P], we must use provability for this.

To emphasize this a bit, lets not talk about sets but about deciding functions f:’a→bool. Lets say ‘a may contain every of these functions. That is, every function can be passed an arbitrary function as first argument. Lets again define a relation f ∈a g stating g(f)=True. Then we can define the function NSA(f):=True, if f ∉a g and False otherwise. Then as before, we can ask whetherNSA∈aNSA. Of course, this will lead to the same contradictions as above. In this case, the answer is again that such a function NSA must not exist. But this time we can clearly see the connections to both situations above: On the one hand, with NSA, we denote a set of objects, like in the Russel paradox. On the other hand, we want NSA to be something which can always “tell” us the truth of a proposition, and there must not be such a thing, like in Gödel’s incompleteness theorem.

Btw, NSA stands for Non-Self-Accepting, one can identify it with the class of Non-Self-Accepting algorithms, i.e. algorithms which return False when they are passed their own code, and with a little more recursion theory, the above argument is the proof of NSA not being decidable.

Bash is one of these languages who seem to be made just for a few small purposes and are now used for vitally everything using ugly hacks and producing unreadable, ununderstandable and undebuggable code.

There are other Shell-Languages, and of course, there is the Clisp-Shell. Except for Clisp they are not “lispy”, and mostly have a lot of Syntax-Structures. I myself dont like too much Syntax. Infixes can make code more readable, if fit into the language, like StandardML does. And having different kinds of Brackets also can do. But having a lot of special syntax for several purposes makes a language more complicated and harder to use, at least to me. This is why I mostly dont like Perl – you can write beautiful Perl-Code, but most people dont. To me, it is not an argument that a Perl-Programmer can express something in one line which can be expressed in Scheme only in 5 lines – the readability of the latter is mostly better.

And well, Clisp as a shell-language sounds not well, because it is a Common Lisp Implementation, which means it mighty – too mighty for a shell. A shell should be turing-complete and simple, it should give the possibility to call other programs with parameters it gets in various ways – but its primary use remains calling other programs.

There is no point in efficiency (other than maybe having a polynomial time algorithm instead of an exptime), it should be simple, easy-understandable, and serve its purpose.

So, thinking of a lispy shell-language, I had the following ideas:

The REPL should be Line-Aware

That is, you dont always have to write parentheses around every instruction to call programs. A line without parentheses and context should be interpreted as if parentheses were put around it. That is, outside any construct like let, loop, etc. – just for the purpose of small function calls outside any other context, just for convenience. As soon as you are inside another lispy context (like let, if, begin, etc.), this should fail. Whether to allow this inside shellscripts or not is a good question – some programs may rely on syntax without parentheses. I would allow it under the same conditions. And above all: As soon as there is one parenthese, parentheses are not optional anymore. That is to prevent ambiguousities. Having one pair of parentheses around a line should really mean the same as having none of them, while having two of them should really always mean having two pairs of them.

There should be only one type of token

Strings, Symbols and several kinds of numbers can be distinguished in most lisps. For a shell-language, this isnt really necessary, I think. Strings are enough. They can carry every information of the other ones. Numbers can always be encoded in decimal Strings – well, arithmetic will get a lot slower then, but for simple calculations it should be fully sufficient, for complex ones one shouldnt use a shell-language anyway. There should be two ways of specifying them: When they dont contain any special character, they can be passed like symbols known from other Lisps. With special characters, they have to be put in quotes. And – above all – no unquoting inside strings, like in bash or php. Some function like string-append should be provided, but inside quotation marks, there may be a syntax for special characters, but nothing more.

One problem which arises with this approach is how to handle variables. If you dont distinguish between numbers, symbols and strings, you dont have any possibility of determining whether a variable or the actual value is to be requested. Well, for the global environment-variables, there should be special commands getenv and setenv, anyway.

For local variables, it is the same as the problem about quoting and unquoting, that already arises in other Lisps. On the one hand, in most cases one could just say “just dont name your local variables like strings and other symbols are named”. Maybe that would be the best way to do, and leave the rest to the programmer. But that could also cause confusion. So for variables, maybe a bash-like syntax like $”…” would be good, i.e. having a $ in front of a string to denote variables. But then, one either would have to enforce quotation marks after $, or to add some additional conventions for strings which could get complicated. I think, just defining a function-like object called $ is also sufficient. Then you can access your variables with ($ var). You can pass Strings in both Syntaxes, and in the end, having ${varname} is not so much less verbose than having ($ varname). Of course, maybe this is not the most convenient thing one can imagine, but in my oppinnion, instead of adding a lot of additional Syntax to spare a few characters, a simple, easily-understandable programming model is more important.

There should be no high-level-objects

Lists can sometimes be useful in a shell, too. Like lists of files, or – if you want streaming – lazy lists of characters. So the basic instructions cons, car and cdr should be there (maybe named “pair”, “first”, “second”). But I dont see any use of cyclic data-structures in a Shell-Language. Without cycles, a simple reference-counter suffices for memory-management rather than a fully-blown garbage collector. Good garbage collectors can get very complex, while bad garbage collectors can be extremely bad in performance and memory-usage, both facts do not fit to a shell-language – a shell-language should do its stuff quickly and then be quiet and keep out of the way. A static reference counter and not allowing cyclic data structures anyway sounds like the best way to do. So, for lists, car, cdr and cons exists, but no way of setting the car and cdr of an existing cons.

There should be C-like scope-declarations rather than let-declarations

One thing that sometimes really annoyes me when using Scheme or Common Lisp is that local variables cannot be declared in the place they are used without adding an additional let-block. Therefore, either the variables need to be declared on top of the block, or you will get code which isnt readable because of the many sublists it contains. Or you will just use a long let*-declaration which saves all intermediate results, so you can code like you would do in a C-Like language.

Of course, inside a real Lisp, the let-approach gives you a lot of benefits like a complete control of which variables are currently declared in your scope, so in this case its a trade that you will kindly accept. But shell-scripting is mostly about quickly coding a few basic computations. Therefore, I think its better to give a possibility to declare variables and scopes in the way C does using curly parentheses and equal-instructions. One could declare the commands (block …) for declaring that here starts a new scope, and (var … = …) for declaring variables, as commands, and additionaly (set … = …) to set them.

Above, the usage of arbitrary strings as variable names was suggested, without the bounds a fixed let-Syntax would give, you can define variables named by arbitrary strings. In fact, the approach of allowing an arbitrary string for accessing variables has some disadvantages. You can produce very bad-looking code, and of course, you can use this as a hack for getting arrays and dictionaries. But on the one hand, if you quickly want to collect a few elements into indexed variables, there is nothing wrong with this, if you really need to exploit it to the maximum, you will get ugly unreadable code, but thats your problem then.

There should be a convenient piping- and streaming-API

Yes, I said a shell language shouldnt be too mighty. But piping and partially interpreting the output and generating the input of a process is something that has to be done so often that there should be an API included in the shell language. What happens if you dont add such an API can be seen in the various hacks that have found their ways into bashscripts. To be more versatile, tools like awk and sed evolved, but – honestly – many code generated with them is pretty unreadable. And its still hard to handle binary data, which is somehow needed, too.

So I think forbidding the handling of binary data and forbidding to read from stdout and write into a stdin directly produces more complicatedness than just adding a simple API that can handle all of this. I mean, in the end, its the only real way for the shell to communicate with programs it calls, except for the return values.

Conclusion

A lot more could be said about shell languages I think. And of course, every point I mentioned is arguable. Something that goes into the direction I mentioned seems to be Tcl, but as far as I see, Tcl is more a scripting language than really a shell language, even though the interpreter is called “wish”.

Jabber – the great free decentralized XMPP-Network on which even commercial services like Google Talk participate. So the default procedure is: Someone who likes to be admin of a server creates an XMPP-Server, making it freely available, and maintaining it. But it happens what always happens: The Admin gets older and therefore more work to do, and so, the XMPP-Server gets forgotten. Instead of giving some other person the possibility to maintain it, the server either goes down completely, or has downtimes and bugs whenever you want to use it.

Thats what already happened three times to my accounts. I had to switch the server and port my contactlist every time. I will try to keep my current account as long as possible, but at the moment I am just totally switching to google talk.

Basically, Google Talk works and has almost no downtime – yes, it already had maintenance-timeouts, but these were announced before and were short. Thus, well, Google is open to external Jabber-Servers, and thus part of the Jabber-Network, but as it appears to be the only long-term reliable server besides jabber.org, the “freedom” behind Jabber becomes arguable.

Then well, having an own little vserver should be sufficient for having an own Jabber-Server. The question is: What server-software to use? Jabberd2 seems very strange, and everyone suggests using ejabberd. But ejabberd – under Debian … well, most people suggest not to use the package, and I actually also do so, because not even the initscript works properly. But lets be honest. Ejabberd works – sort of. If you leave it to the basic configuration and hope that your server will be accepted by the other Jabber-Servers – and, above all, will accept other Jabber-Servers – there may come a time when you can actually use it (except when it crashes or refutes to connect because of some misconfiguration you didnt even notice before connecting to it from another IP-Address).

If you only want the service for yourself, you could also think of running a server locally on your Home-PC, using dyndns. Well, this solution is not very stable for a huge Jabber-Server, but for you and a few friends it should be sufficient. But then you are almost guaranteed to not being able to connect to the larger Jabber-Servers – because they mostly deny access of such IP-Addresses – which is obvious, since otherwise they would be flooded with spam.

And above all, having an own server is nothing for everyone. It is basically not what Instant Messaging was thought for. Instant Messaging contains the word “instant” – which means you want to use it instantly. You dont want to have to configure a complex server infrastructure everytime you want to ask a friend if he likes pizza when he arrives visiting you, or if he will join you in the canteen this noon. Especially, you as a conscious free-software-user could even be willing to take the extra efforts to maintain such a thing, but will the handsome neighbour-girl you want to date do so, too? IM is only an option if it is easily available to anyone.

This includes a simple Client which runs under Windows – which doesnt want to know lots of strange settings, but just a small User-ID and password, and then connects and then just works. Is that really so hard?

Well, facebook has an XMPP-Service meanwhile, which is a good thing (and does certainly produce some costs to facebook) which works perfectly as far as I see – except with the newest Pidgin-Version (which is the client which is most commonly recommended to users). I tried with other clients. I tried with older Pidgin-Versions. It worked perfectly. Only the new Pidgin-Version doesnt like facebook’s XMPP-Service. And – above all – I asked #pidgin for help. But nobody could imagine what the problem is.

This is an XMPP-Service – it uses an open protocol. And it used to work with the same client on an older version. But nobody can even tell how to trace the problem. Now, isnt that nice?

And to get your client being able to transfer files from point to point is another story. It isnt even always sufficient to have one open port on one side.

Actually, I dont see the point to XMPP at all. Seems like the main purpose it is used for is Instant Messaging. There may be multiuser-chats, but IRC is far more wide-spread, and far more usable, and has a simple protocol. Actually, IRC could be used for Instant-Messaging, too, when slightly modified or extended.

I cannot understand why its so hard to create a working protocol for instant-messaging. I mean, its not that instant messaging is something that has just been invented.