守破離

Shuhari and Computer Science

守破離

Shuhari is a term that describes the phases or learning in Japanese arts and is considered a part of some martial arts like Aikidō. Learning can be decomposed into three phases:

(SHU) – Conformance
Learning while conforming to the rules.
(HA) – Deviation
Developing one’s own style, breaking some rules
(RI) – transcendence
Building one’s own rules

While reading about the subject on the internet, I found an interesting blog post called The Fallacy of Shu-Ha-Ri, which discusses the application of that principle to computer science. It is not so much a criticism of the decomposition than a realisation that it cannot really be applied in a chaotic medium like computer science: what is the point of mastering some technique if you are not sure that said tool is the solution.

To me shuhari looks like a good model once you have accepted a given path. Unsurprisingly, Japanese arts are divided into ways ( []), early on, you choose a way and you follow it until you transcend it; not exactly the way things work in computer science.

Reflecting on my situation, there are a very few tools that have stayed around since I started dabbling with computers, having learnt the trade on Commodore 64 with BASIC and 6510 assembly. I learnt C programming in 1992, at the University of Geneva and I’m still coding in C++ these days, but the difference between the two languages is pretty large. In C++, I would say I’m at somewhere between SHU and HA: can’t say I’m fully mastering it, but sometimes bending some rules and using advanced features.

Flattr this!

Swift Logo

A first look at Swift

Swift Logo

Apple’s announcement of the Swift language was quite a surprise, while the company had extended Objective-C in the past, it had not dabble in programming languages since Dylan and Applescript, so I was quite curious to see what this is about.

Swift is presented as the successor of Objective-C, but drops the C compatibility while keeping a C-like syntax, in a way similar to Go or Rust, Swift borrows ideas from many existing languages: Objective-C, Python, but also Rust and C♯. Compared to say Python, the language is actually pretty complex, as it has many features. Gone are the days were languages tried to be minimalistic, here the goal is clearly to implement features for common programming patterns.

Given the fact these day I mostly code in C++11 and Python 2.7, I found the language to have interesting features:

  • Compiled language, with the goal of being faster than Objective-C. Uses LLVM as compilation back-end.
  • References and Value types. Swift borrows from C♯ that classes are reference types and structs are value types, passed by copy to functions and methods. This means that complex data can live on the stack and be contiguous in collections. This makes a big performance difference and is also a big theme in C++11 and C++14.
  • Strong typing with type inference, with a differentiation between variable and constant, one declared with var, the other with let, no duck typing for functions, but the language supports templates and protocols (interfaces). Types can be extended outside of the original declaration and this can be used to make them adopt new protocols.
  • Enum types can be based on any raw type (not only integers), and can have associated data depending on the enum value, so they also implement the functionality of union.
  • Switch statement based on any types, with the complex matching rules, so you can branch on ranges, or conditional expressions. Something that the Rust language has.
  • Optional types everywhere. Swift has no pointers, and no magic None/Nil value like Python has, Conditional types express the idea of something of type X or nothing, a feature you would implement using a pointer and check for null, this is the same as the boost:optional template in C++, but more integrated into the language, as there is an optional access operator.
    Consider an object A which has a field b which can contain a value of type B which has a field c, which can contain a value of type C. If you have an value a of type A and you just want to read the field a.b.c, you have to add a lot of if statements, or try accessing it and handle exceptions. In Swift you just call a?b?c which returns you can optional of type C. This is really nice because this kind of access is pretty common (for instance in protocol buffers).
  • Lot of syntactic sugar: nice loops, tuple decomposition, i.e let (x, y) = getCoordinates(), clean range expression [1..9], integers can contain underscore to be more legible like 1_000_000, string interpolation can contain arbitrary expressions (including function calls) "sin \(x) = \(sin(x))"

We will see how the language performs in practice, I suspect its impact will mostly be determined by the way Apple releases the language, if it is free, it might get wider adoption. Regardless of the success of Swift, I think many of the ideas in the language are good ones, and so I hope this will lend support to the languages which already have those features, and encourage other languages to adopt them.

Flattr this!

Drapeau Espéranto

Nouveaux Langages

Drapeau de l'Espéranto

J’avais largement oublié l’, jusqu’à ce que les évènements européens m’y fassent penser, la blague officielle européenne de ploum m’encourageant a écrire un billet dans cette langue.

En relisant les textes, notamment sur la grammaire de l’europanto (how to cause international English to implode), j’ai été frappé par la pertinence des reflections sur le rôle du language et la relation entre l’ et l’Anglais international, qui évolue indépendamment de l’anglais natif parlé dans les îles anglaises ou au États-Unis. Coïncidence curieuse, l’Esperanto figure aussi dans les coulisses des origines de l’aïkidō, sujet sur lequel je lis ces temps-ci.

En programmation, un langage qui a implosé, c’est C. Au boulot on utilise C++11, qui a importé de nombreuses constructions venues d’autres langages : boucles simplifiées, lambdas, inférence de type, fonctions pures. Personnellement, je trouve ce nouveau langage très agréable à l’utilisation, dans les faits, la relation avec le C originel est assez ténue : il reste la structure de bloc, les boucles et le contrôle de flots, les opérateurs de base et c’est à peu près tout. Naturellement, C++11 est un effroyable bazar, avec une myriade de concepts et de constructions.

La domination du langage C est similaire à celle de l’anglais : son succès est largement lié à la domination d’Unix, et le fait qu’il est assez facile d’apprendre à programmer mal en C, personne ne prétend réellement le maîtriser. Les failles de sécurité qui font régulièrement les nouvelles en sont le symptôme le plus apparent.

Depuis 40 ans, différentes personnes ont proposé des cathédrales pour remplacer C, des langages plus clairs, mieux structurés, moins prompts aux problèmes de sécurité, bref des Espéranti informatiques. Java est parvenu un temps à menacer C, mais le comportement d’Oracle et les problèmes de sécurité et de performance font que le langage a perdu de son attrait.

Le langage est une autre tentative, qui semble aussi chercher à se rapprocher du C originel, avec certains archaïsmes, comme l’utilisation généralisée de tableaux – une sorte de romantisme qui me rappelle l’existence de l’accusatif en Espéranto.

Flattr this!

Grammar for computer geeks

Grammar is one of those things you discover when learning a second language, even though you were using it with you first. Like many abstract way of thinking about stuff, you can live without, but it makes discussing stuff much easier. Instead of explaining those concepts using words, I’m going to explain them using C function pointers.

Transitive Verbs

They are functions that take two parameters, a subject and an object, like for instance the verb to beat. The first defines who does the action, the second defines what the action affects.

typedef void (*transitive_verb)(Object*, Object*);

Intransitive verbs

They are functions that take only one parameter, a subject, like for instance the verb to die.

typedef void (*intransitive_verb)(Object*);

Ambitransitive verbs

They are functions that can have both a transitive and an intransitive form, like for instance the verb to eat.

Flattr this!

C++ level

I realised something amusing about the C++ language. When I ask to people around me to estimate their level in C++ language, on a 1-10 scale, people who know how to code in this language will usually give themselves a 7. The thing is, I don’t think their level is the same, put their mindset regarding the language is the same: they can use it to code, but there is still a lot of stuff that they don’t fully understand.

I think this is a very good mindset, because it is one that acknowledges complexity, and the fact that one always learns. A path where there are few self claimed gods and the journey is more important than the goal.

Flattr this!

Floating point considered harmful

bool foo() {
  float a = 0.6;
  float b = 6.0;
  return (a == (b * 0.1));
}

bool bar(float c) {
  return (c != c);
}

When I learned coding on the C64, the two main tools where Basic, and direct memory access. Any advanced stuff was done in assembly. So basically, coding involved pretty much only pointer arithmetics and goto statements. Of course this was a long time ago and such constructs are now shunned, and many newer languages even prevent the code from doing such thing, which is probably a change for the better.

Strangely, there is one type of operations that is very dangerous, but which most languages do not restrict: floating point operations. Consider the snippet on the side, will foo return true? Maybe, but there is no guarantee that the bit representations of a and b will be equal. Will bar ever return true? Yes if c is NaN. Generally speaking, comparing bit for bit two floating points is a bad idea, and providing that operation to the programmer is a disservice. Floating point semantics are complicated, and only partially visible in the programming language: rounding, extended precision are typically not accessible.

A lot of the code I have seen just happily assumes that floats basically behave like integers, why would it not? Floating point numbers are the only types which in each and every language are allowed to have the same operators as integer. In most of the cases, using a fixed point (currencies) or fractional representation (computing averages and such) would be more appropriate, but such constructs are typically missing in the language, or are second class citizens – Python for instance only had fractions since version 2.6 and there is no shorthand notation to create them.

The only languages I used which had put some serious thoughts in their numerical representations where Ada and Smalltalk. The others seem to be happy to just clone C operations.

Flattr this!

long ratoi(const char* string) { if (NULL!=string) { const char c = *string ; const char *tail = ++string ; if ('-' == c) { return -1 * ratoi(tail) ; } else if (('+' == c) || isspace(c)) { return ratoi(tail); } else if (isdigit(c)) { long value = c - '0' ; if (isdigit(*(tail))) { // rest of string is number const long recurse = ratoi(tail) ; const int digits = (int) log10((double) recurse) ; // we shift to match the tail's result for(int i=0;i

Recursive atoi

One site I visit often is the , a web site discussing really bad programming (as seen in real everyday life). Today’s thread is about a bad implementation of the string to interger function atoi. A friend of mine dared me to do a recursive implementation of atoi. Doing this would be very stupid and innefficient, so it is really an exercice in futility. Of course I could not resist. So here it is, this is not nice code, simply something I whipped out to show it is possible.

long ratoi(const char* string) {
    if (NULL!=string) {
	const char c = *string ; 
	const char *tail = ++string ; 
	if ('-' == c) {
	    return -1 * ratoi(tail) ; 
	} else if (('+' == c) || isspace(c)) {
	    return ratoi(tail); 
	} else if (isdigit(c)) {
	    long value = c - '0' ; 
	    if (isdigit(*(tail))) { // rest of string is number 
		const long recurse = ratoi(tail) ; 
		const int digits = (int) log10((double) recurse) ; 
		// we shift to match the tail's result
		for(int i=0;i<digits+1;i++) {  
		    value*=10 ; 
		} // for 
		return value + recurse ; 
	    } else { 
		return value ; 
	    } 
	} // isdigit
    } // not null 
    return 0 ; 
} // ratoi

Flattr this!

Du C++ et des violonistes

Un des grand débat parmi les informaticiens est sur les préférences pour tel ou tel langage. Comme pour beaucoup d’autres choses, les préférences sont dictées par des considération techniques, esthétique, mais aussi culturelle et sociales. Les considération techniques sont de prime abord les plus simples à exprimer: certains langages permettent certaines choses que d’autres ne permettent pas. Il est impossible d’écrire un driver pour un système d’exploitation en Java par exemple.
Néanmoins ces contraintes techniques n’affectent en réalité qu’une minorité de programmeurs et les choix sont somme toute rarement dictés par des raisons techniques.

Les raisons esthétiques sont difficiles à définir, si la plupart des gens qui programment s’accordent à dire que certains codes sont abominables (en général celui des autres), la définition de ce qui est beau est plus complexe. Certains trouvent des codes compacts et efficaces sont la base de la beauté, alors que d’autres trouveront plutôt des langages aux structures minimalistes élégants. Souvent la définition de ce qui est beau est surtout conditionnée par la manière dont on a appris à programmer.

Car en fin de compte, l’aspect social est la partie dominante. Chaque communauté à ses us et coutumes, et sa manière de voir le problème. Par exemple, le CERN ou je travaille, est une communauté de physiciens, la culture informatique est de ce fait imprégnée par Fortran. En dehors de cette communauté, ce langage est considéré comme un archaïsme et personne ne voudrait plus l’utiliser, ici il est bien vivant et considéré comme adapté. Et même si la programmation ne se fait pas en Fortran, les gens programme toujours à la manière de Fortran, et les facilités de langages plus récents ont tendance à être ignorées.

Une autre composante sociale est l’élitisme. Il y a fondamentalement deux types de programmation, l’un consiste à écrire des algorithmes qui font de véritables calculs, le second consiste à écrire du glue code, c’est à dire ne fait pas réellement de calcul, mais qui traduit des données, les prépare pour l’utilisateur. Le premier type de programmation est passionnant et requiert d’être réellement malin, d’avoir des idées originales. Le second demande surtout d’être soigneux et productif. L’art et la besogne. Naturellement, toute la mythologie informatique tourne autours de la première catégorie.

Le violon est, paraît-il un instrument de musique difficile, ce qui fait aussi que les virtuoses du violon sont adulé. Il y a une raison pour laquelle on ne parle pas souvent des virtuoses du triangle. Le C++ est un peu comme le violon. C’est un langage très complexe, et rares sont les gens qui arrivent à le maîtriser. Par contre, il permet des abominations sans nom. Néanmoins ce langage reste très dominant simplement car il permettrait de faire du code très avancé, dans les faits, les génies du C++ sont rares. L’avantage du C++ c’est qu’il permet de nombeux styles de programmation, on peut le prendre comme un (mauvais) langage orienté objet, ou comme une vague copie de Fortran, voire même des choses plus exotiques.

Un collègue m’a prêté un livre sur le C++ Modern C++ Design: Generic Programming and Design Patterns Applied d’Andrei Alexandrescu qui illustre parfaitement ce problème. Ce livre est brillant et contient des perles d’ingéniosités qui sont autant d’abominations. En gros, l’auteur utilise les mécanisme des templates pour faire de la programmation qui s’exécute au moment de la compilation. Une sorte de programmation dans la programmation. Le fantasme de la programmation C++ est de détecter toutes les erreurs au moment de la compilation, et ce livre essaye d’aller dans cette direction. Le drame c’est que dans la bagare, l’auteur réinvente un autre langage (le Lisp), à force de templates sans jamais nommer ce langage donne une idée de l’étendue du drame.

Comme dans le monde de la musique classique, il ne faut pas sous-estimer le niveau de snobisme ambiant. Personne ne va réellement poser la question de pourquoi on doit bricoler un autre langage en martyrisant les structures du premier au lieu de faire un système de vérification plus intelligent, comme personne ne va réellement demander pourquoi on ne change pas les violons pour qu’il soit plus facile d’en jouer.

L’avantage du violon, c’est que si quelqu’un joue réellement mal, cela s’entend. Le mauvais code C++ est malheureusement beaucoup plus discret – bien qu’en fin de compte, il soit probablement responsable de votre prochain écran bleu.

Flattr this!