Some languages are more equals than others

27 Oct 2012

In my last three posts, I’ve ended my Java example with a comment to indicate that I won’t write extra methods. equals is one of them. Today, we’re going to write what we need to test equality of two people.

Fill in the blank

Today’s scenario is really basic, so we can dive directly into the code. We start with the Person class in Java from the previous post:

public class Person {

    private final String  firstname;
    private final String  lastname;
    private final Integer age;
    private final Person  father;

    public Person(String  myFirstname,
                  String  myLastname, 
                  Integer myAge,
                  Person  myFather) {
        this.firstname = myFirstname;
        this.lastname  = myLastname;
        this.age       = myAge;
        this.father    = myFather;
    }

    /* Feed it with any expected extra-methods */
}

And the Haskel version:

data Person = Person { firstname :: String
                     , lastname  :: String
                     , age       :: Maybe Int
                     , father    :: Maybe Person
                     }

Painfull equality and useful shortcuts

It is so boring to build equality that most Java IDE have a shortcut for it. Fortunately we have only one equals method to write and the class is quite short. Of course, we also have to provide an appropriate hashCode method, but as it doesn’t change anything to this example, its code is left to the reader. In general, there is no need to bind the implementation of equals and hashCode. It is often seen as mandatory for Java developer because both function are implemented in Object. But you may need to test equality without providing an hashing function, or the converse. So let’s continue with Java equals function:

 public boolean equals(Object o) {
     if (this == o) return true;
     if (! (o instanceOf Person)) return false;
     Person other = (Person) other;
     return Objects.equal(firstname, other.firstname) &&
            Objects.equal(lastname, other.lastname) && 
            Objects.equal(age, other.age) && 
            Objects.equal(father, other.father); 
}

Objects class was introduced in Java 7 and is very very incomplete at the moment (in my opinion) but that’s out of scope. At least, its introduction allow us to avoid the use of ternary operators to check nullity. If you use an older version of Java, you should use stuff like father == null ? other.father == null : other.father.equals(father) in your code but verbose code is easier to maintain, right?

Lets do it in Haskell. It’s also painful. Aside the type declaration, you have to claim that you have an instance of equal for your Person type:

instance Eq Person where
  (Person fn1 ln2 age1 father1) == (Person fn2 ln2 age2 father2) =
    fn1     == fn2    &&
    ln1     == ln2    &&
    age1    == age2   &&
    father1 == father2
  _ == _ = False

Yes, its only a bit shorter. The test of different “fields” is a bit easier. The main reason is that we don’t have the differentiation of pointer equality and object equality. The only kind of equality that can be defined in Haskell is object equality. Another reason is that we don’t have to bother with null but we have already talked about it. There is a third reason. Try to guess what it could be, the answer is in the next part of this post.

Haskell could have stick to this solution and wait for solutions provided by IDE to simplify the life of the developers. Instead, they propose a keyword, deriving. With this keyword, we can add equality (and other typeclasses) to a type quite easily. In our specific case, we have to add the following line right below the definition of the Person type: deriving (Eq). This time, it’s shorter:

data Person = Person { firstname :: String
                     , lastname  :: String
                     , age       :: Maybe Int
                     , father    :: Maybe Person
                     }
              deriving (Eq)

Type safety everywhere

So, what is the third difference between the “long implementation of equality in Haskell and its Java counterpart? The short answer is there is no explicit type check in the Haskell version. The complete answer is there is no type check at runtime in the Haskell version. In Haskell, when you use equal, the compiler requires that both arguments have the same type. It’s not better or worse, it’s different. The motivation for this choice is as follow: Haskell ask you to know which are the exact types of the values you manipulate. So, if you come with two values of different types and compare them, it considers it as an error. Most of the time, it works similarly in Java. Most of the time… We will see what happens in the other case in a next post.

Haskell Bonus Point

In the Haskell snippets, where does this Eq comes from and what means this instance keyword? Eq is what we called a typeclass. For any type, you can provide an instance of a typeclass, providing the function required by it. In the Eq cases two function are defined: (==) and (/=). The complete definition is the following:

class  Eq a  where
    (/=)             :: a -> a -> Bool
    x /= y           =  not (x == y)
    (==)             :: a -> a -> Bool
    x == y           =  not (x /= y)

As you can see, there is already a minimal definition of (==) and (/=), which allows you to define only one of the two functions when you create an instance. A first remark about type signature ((/=) :: a -> a -> Bool and (==) :: a -> a -> Bool). As often in Haskell, the signature is here for documentation purpose. It can be read as: function (==) (and respectively (/=)) takes an a to produce a function that takes an a to produce a boolean. Its a bit different than a function that takes two a to produce a boolean, but we will focus on it another day. Actually, it can be used as if it was a two a argument function. a is a type variable, which must be replace by the correct type when you declare your instance. In our example, it was replaced by Person in our declaration. Some other little Haskell things. The use of parenthesis around a function with two parameters indicates that you can use the function without the parenthesis in an infix manner. To test equality of two values a and b, you can either write a == b or (==) a b.

Typclasses can be seen from a Java developer point of view as interfaces. It’s not totally accurate since you can’t build a one-to-one mapping between the two approach. There are some analogies between the imperative and the functional paradigm, but they fail at some point. I’m giving you two major differences (there are certainly more of them):

  • You can define a default implementation for some method in a typeclass, not in an interface.
  • You can add instance to a type whenever you want. Not only when you introduce it in your code. If my type doesn’t have an instance of Eq, I can add it when I need to.

Null and Option, fire and ice

22 Oct 2012

ML, Haskell or Erlang, does not have null and they don’t miss it. Tony Hoare himself consider the introduction of null as an error. A billion dollar error more precisely. As a consequence, many languages try to work around null. Groovy has its safe navigation operator (.?), Scala has its Option and Java has… well Java has if (x != null) … else …. As this last solution is neither concise nor elegant, some programmers support the introduction of an equivalent to Option in Java. In the Java 8 perspective, Mario Fusco’s article is certainly one of the most interesting on this subject. The idea is simple and straightforward: as it seems cool to avoid using null, let’s provide a way to avoid it more often.

A few words about the Groovy solution. x?.foo is basically a shortcut for: x == null? null : x.foo you can achieve almost the same with a macro in your text editor. It is useful because it saves a lot of typing and makes code denser but it doesn’t provide any type safety.

We should agree that the main goal of avoiding null is to be sure that we handle the lack of information properly. Properly means that if there is an uncertainty, I have to deal with it either by propagating it (as the .? groovy operator or the null object pattern does), but also by providing a default value or by doing a different process depending on the case. Option/Maybe comes with a lot of handy function to do it.

So far, so good. Except that Scala and Java do have null. Let’s come back to what happen in a null-free world. Suppose that you’re writing a function and you’re not sure you can provide the expected result. In this case, you only have two options:

  • Use an Option/Maybe and claim explicitly that your function doesn’t know if it can provide a result.
  • Throw an exception, saying that something was not expected at all directly.

It’s clear. I’m not sure it can be clearer. Let’s come back to the world of null and look how we deal with the same situation, without taking into account the Option alternative:

  • Return null if your function can compute a result. In the best case, you will say it explicitly… in the documentation. The compiler isn’t aware of it. Other devs will know about it only if they read the doc. But the program continues.
  • Throw an exception, exactly like in the previous case.

Adding Option to the second case, people expect to get back to the first one. Ahem… No! Here is what you get instead:

  • Return null if your function can compute a result. In the best case, you will say it explicitly… in the documentation. The compiler isn’t aware of it. Other devs will know about it only if they read the doc. But the program continues.
  • Use an Option/Maybe and claim explicitly that your function doesn’t know if it can provides a result.
  • Throw an exception, saying that something was not expected at all directly.

Yes, it’s almost an automatic merge. Do you see where I’m going with that? When I call a function, I can’t know if the programmer hasn’t decide to use null if the function don’t have a result. Worse, even if I see an Option, I can’t tell if this guy isn’t bad enough to return a null instead of a real Option. Yes you can expect that other programmers respect a kind of best practice and stick to the Option/exception alternatives. But best practices aren’t statically typed.

It leads us to a difficult choice. Shall we add this third solution or not. Due to the feedbacks I’ve read about Mario’s article about Option in Java, I tend to understand that the community thinks so. After a long discussion between myself and I, I tend to agree with them. But I keep it mind that it doesn’t resolve at all the null issue. It’s just a patch.

Maybe: You want something more?

17 Oct 2012

So, you’re now convinced that type safety is far better from these null things to avoid insidious bugs. If you’re not, read the previous article again. So, we have a nice type to avoid nullity, but how do we use it? When we want to access them, update them, compose them, is it more or less convenient than using null?I could say that category theory answers this question. It does, but I guess you came here because you wanted proof.

Make everything optional

Back to our person data again. Suppose that finally the age of a person is now optional. But unfortunately we are still going to deal with it when it’s available. Yes, as usual dealing with non-mandatory elements sucks. So here are our starting point in Java:

public class Person {

    private final String  firstname;
    private final String  lastname;
    private final Integer age;
    private final Person  father;

    public Person(String  myFirstname,
                  String  myLastname, 
                  Integer myAge,
                  Person  myFather) {
        this.firstname = myFirstname;
        this.lastname  = myLastname;
        this.age       = myAge;
        this.father    = myFather;
    }

    /* Feed it with any expected extra-methods */
}

and in Haskell:

data Person = Person { firstname :: String
                     , lastname  :: String
                     , age       :: Maybe Int
                     , father    :: Maybe Person
                     }

And you know these data mining guys with their odd queries? Here they are! You were asked to dig for a person’s father’s age. Of course, you can only provide this information if the person’s age, father and the father’s age are available. In any other case, you won’t be able to provide a better result than null or Nothing depending whether you use a poorly designed language or a cool one.

Running out of the null hell

There are so many optional values that we have a hard time with them, for example, here is the Java version:

public class FamilyQuery {
    public static Integer fathersAgeAtBirth(Person p) {
        Integer currentAge = p.getAge();
        if (currentAge == null)
            return null;
        Person father = p.getFather();
        if (father == null)
            return null;
        Integer fathersAge = father.getAge();
        if (fathersAge == null)
            return null;
        else
            return fathersAge - currentAge;
    }
}

Hopefully, multiple returns make things a bit easier. Without them, you would have to used an ugly nested-if structure. The main issue with this piece of code is that you have to interrupt your navigation to check for nullity, and then continue with it. Well you know, criticism is easy, can we do better? You can judge it by yourself, here is the Haskell version:

fathersAgeAtBirth :: Person -> Maybe Int
fathersAgeAtBirth p =
  do
    currentAge <- age p
    pFather <- father p
    fathersAge <- age pFather
    return $ subtract fathersAge currentAge

The do notation is a way to dive into the content of Maybes. Each time you use the left arrow, you try to extract the content from right side into the left side variable. If it isn’t possible you stop and return Nothing. You don’t have to worry anymore whether a field is defined or not, Maybe has the power to deal with it.

Haskell bonus point

For operator lovers (idiomatic Haskell)

I must confess. The above version is a light, sugar free Haskell solution. Actually, dealing with value enclosed in a structure (here, the Maybe structure) is done many time in a program. Thus, we have some special functions to do it more efficiently. It can lead to the following code.

fathersAgeAtBirth :: Person -> Maybe Int
fathersAgeAtBirth p =
  subtract <$> fathersAge <*> currentAge
  where
    fathersAge = father p >>= age
    currentAge = age p

Yes, most of the time, it is where we lost most of the imperative programmers, especially those who prefer verbose code with clear, literal function names. Indeed, perl lovers shouldn’t be concerned. I don’t have the willpower to explain it for now, because I would need to introduce many new functions and concepts to do it right. Just look how the first line of the function subtract <$> fathersAge <*> currentAge looks like what we expect to code if we just have to manipulate integers. It’s a central idea in functional programming: add a concept thanks to an adequate data structure and provide function to make the introduction of this concept as little intrusive as possible.

Back to pattern matching

Remember the first post on pattern matching? We can inpsect a complex data structure with it. Here, we need to check that:

  • the age of the person is defined;
  • the father is defined;
  • the father’s age is defined.

In any other case, we won’t be able to produce another result than Nothing. Here is the result:

fathersAgeAtBirth :: Person -> Maybe Int
fathersAgeAtBirth (Person _ 
                          _ 
                          Just(currentAge) 
                          (Person _ _ Just(fathersAge) _) =
  Just (fathersAge - currentAge)
fathersAgeAtBirth _ = Nothing

This kind of pattern matching is a bit too complex to be considered as idiomatic, but it’s another illustration of how powerful it can be.

Nothing, Just, Call me Maybe!

10 Oct 2012

Today, we will talk about null pointer exception. Or more precisely the lack of null pointer exception in functional programming. Please hold your trolls, we are analyzing facts. It’s not that functional programming doesn’t like null, it’s just that we actually don’t have this concept. Yes we can live without it, wanna see how?

But what happens when a Haskell programmer wants to express that a function has no result? Well, it’s quite simple, we use Maybe. It’s a monad but I’m not going to bother you with the monad stuff at the moment, a lot was already written on this topic, in many cases by very clever people. The Internet doesn’t need my 2 cents on it. More than that, telling you what a monad is may be insufficient to help you getting why it’s useful, especially at this stage.

So, we have the Maybe type, which has two constructors Nothing and Just with the following definition:

 data Maybe a = Just a
              | Nothing

The a here is the way we introduces polymorphism in Haskell. Shortly, we can either have a value boxed of type a in a Just object or Nothing. Imagine you boxed your result type in Java: if it’s a null, you return an object of class Nothing; if it’s a non null result, boxed it in a Just object. If you can imagine it, you get the whole idea.

At this stage, you may wonder how it can help. Here we are:

A bit of genealogy

We’re completing our Person class, adding a father field to it. Unfortunately, all of our people aren’t really into our big brother approach, and some of them refuse to fill the information.

Suppose that given a person, we want to produce the list of its known ancestors’ name (the list order is up to you). How would you do that? Of course, this example is totally stupid, but it ilustrates a classical scenario of navigation between 0-1 cardinality properties, which happens quite frenquently in the real world. Here is how we represent a person in Java:

public class Person {

    private final String firstname;
    private final String lastname;
    private final int    age;
    private final Person father;

    public Person(String myFirstname,
                  String myLastname, 
                  int myAge,
                  Person myFather) {
        this.firstname = myFirstname;
        this.lastname  = myLastname;
        this.age       = myAge;
        this.father    = myFather;
    }

    /* I still won't write getters and equals/hashCode.
     * And I still thinks it's stupid to have to.
     */
}

And in Haskell:

data Person = Person { firstname :: String
                     , lastname  :: String
                     , age       :: Int
                     , father    :: Maybe Person
                     }

Ok, the type signature of father in haskell is a bit more complex than the java one, I admit. Let’s look to the solution to our example.

The billion dollars mistake

Let’s start ith Java. We build a Genealogy class with an ancestor method, like so:

public class Genealogy {
    public static List[Person] ancestors(Person myPerson) {
       Collection<Person> result = new LinkedList<Person>();
       Person father = p.getFather();
       while (father != null) {
           result.add(father);
           father = father.getFather(); 
       }
    }
}

It looks pretty and neat. Mostly because the example is simple and because my solution is correct. Let’s try a faulty version:

public class Genealogy {
    public static List[Person] ancestors(Person myPerson) {
       Collection<Person> result = new LinkedList<Person>();
       Person father = myPerson;
       do {
           father = father.getFather(); 
           result.add(father);
       } while (father != null);
    }
}

You see what happens in the above version if myPerson.getFather() is null? Yes, it crashes and yes, it’s a bug. The issue with null is that nobody will warn you in this case. You’ll have to wait for the tests (the best case) or the bug (the worst case) to see it, thanks to a wonderful null pointer exception.

Ok, move on to Haskell:

ancestor (Person _ _ _ Nothing ) = []
ancestor (Person _ _ _ (Just p)) = p:(ancestor p)

So, as you might have noticed, I propose a recursive definition. It can be read as: if no father is defined, returns the empty list. Otherwise return a list made of the content of the father field and the list of the father’s ancestors (: is the prepending operator in Haskell). As we have to unbox the content of father to get the person’s value, we can’t do it wrong. Typing saves you from using a null value. Thanks to the “Maybe boxing” we have a type safe version.

So Maybe provides you a convenient solution to avoid some bugs, catching errors at compile time instead of doing it at runtime. Unfortunately, as old Lulu used to say, “you can’t spend good time with me and keep your 200 bucks”. Here type safety has a performance price. we will see later that the Maybe type is very convenient to use in many scenarios, but that’s enough for today.

Haskell extra point

Here, I would like to introduce some precision about the non-nullpolicy and boxing issues. We agree that boxing might be painful when you know that something will suceed. You often want to let it go. You can but not with null. Instead, we have exceptions. The idea is that if you don’t provide the expected value to a function, the function may throw an exception. Yes, we don’t have a typesafe failure anymore. Hey, that’s what you asked for! The main difference here is that: we won’t silently continue with the non-existing value. We just stop the computation and throw an error.

As an example, you can have a look at the standard head function that returns the first element of a list and how it behaves on a non-empty list:

Prelude> head [1,2]
1

and on an empty list:

Prelude> head []
*** Exception: Prelude.head: empty list

The big switch

02 Oct 2012

Pattern matching is often put forward as a first feature example when we introduce functional programming. And there is maybe a first misunderstanding there. Actually, when we talked about pattern matching, we don’t talk about regular expressions. No, pattern matching in functional programming is closer to a switch case… on steroid. The kind of steroids that gives to Suzanne Boyle the opportunity to be faster than Usain Bolt.

Java programmers have started to love it with primitive types, then with enumeration and more recently with String. In many situations, it allowed them to refactor their code in a more comprehensive way. Do you think we can go further? The short answer is: Yes.

Say “Hi!”

It’s our first example. In this blog, I will use most of the time toy examples. The goal is to add as few noise as possible around the concept I will try to introduce.

Here is the scenario. We deal with people. A person has a first name, a last name and an age. Yes, welcome back to CS 101. Yes, it is stupid to store the age as an integer and not as a date, I never said my examples would be clever. At this stage neither the Haskell nor the Java version are complex. Here is the Java version:

public class Person {

    private final String firstname;
    private final String lastname;
    private final int    age;

    public Person(String myFirstname, String myLastname, int myAge) {
        this.firstname = myFirstname;
        this.lastname  = myLastname;
        this.age       = myAge;
    }

    /* Forgive me, I won't write getters/setters.
     * I'm a poor lazy functional programmer.
     */
}

And there is the Haskell one:

data Person = Person { firstname :: String
                     , lastname  :: String
                     , age       :: Int
                     }

May be I should explain a few things here. Haskell is definitely not object oriented. As a consequence, the field names given in the Person definition are actually function names to access these fields. For example, if you have a value tom that contains a Person, you can write age tom to access tom’s age. I know,

Ok, so far, so good. Haskell is more concise, but who cares? Everybody loves typing, right? And if you don’t, you have these lovely code generation features. Actually, I don’t like them but it’s a matter of taste.

Suppose now that we want to greet a person. The function greet should return “Hi, ” followed by the person full name. Unfortunately we work in a naughty environment and we want to protect young people (below 18). To them we’ll answer “Thou shall not pass”. Except for this little guy, Isaac McMillen, because we don’t really care if he gets hurt. For him we have a special message: “Welcome home, Isaac”.

Check fields, write too many things

Let’s build our Java greeting class (we can as well add a greet function to the Person class but it doesn’t really match the single responsibility principle)! To do so I assume that you’ve added a getFullname function to the person class. I can leave it to you as an exercise, you’re allowed to find it insulting.

public class Greetings {
    public static String greets(Person myPerson) {
        if (isIsaac(myPerson) 
             return "welcome home, Isaac";
        else if (isOverEighteen(myPerson))
             return "Hi, " + myPerson.getFullname();
        else
             return "Thou shall not pass";
    }

    /* Helper functions */

    private static boolean isIsaac(Person myPerson) {
        return myPerson.getFirstname().equals("Isaac")
            && myPerson.getLastname().equals("McMillen");
    }

    private static boolean isOverEighteen(Person myPerson) {
        return myPerson.getAge >= 18;
    }
}

I know you, sweet little troll! You wanna talk about multiple returns, string concatenation, parenthesis and code convention. It’s not the point here! We don’t want to talk about it at the moment. So relax and stay focus on the algorithmic part. We have an if … else if construct, and we have a lot of access to the fields. Look especially at the isIsaac function. It’s so cumbersome! And we just want to test two fields! Let’s compare it to the Haskell version:

greet :: Person -> String
greet p = 
  case p of 
    (Person "Isaac" "McMillen" _) -> "Welcome home, Isaac"
    (Person _ _ age)
      | age < 18                  -> "Thou shall not pass"
      | otherwise                 -> "Hello " ++ (fullname p)

It’s denser, yes. The first line give us the type of the function (it takes a person, it returns a string). We can as well omit it, since Haskell is able to work out the type on its own. But look how we have separated the three cases. This is pattern matching in action. Instead of the painful isIsaac function, we have a clean pattern matching, that inspect the fields of our person. Similarly we use the same trick to extract the age field. It’s a minor improvement, but most of the functional programmers find it quite interesting.

How many time did you extract some fields of a variable to inspect them? Pattern matching let you to do it in an efficient way, without having to struggle with accessors.

I know it might seem a minor improvement. You can even think it’s not an improvement at all. As I claimed in my previous post, you don’t have to be convince that functional programming is better. But, for us, it’s full of those kind of minor change that simplify our work as developers, and I hope it helps you get into it.

Haskell bonus point

Haskell folks love pattern matching so much that they allow you to use it directly in the function definition. Like so:

greet :: Person -> String
greet (Person "Isaac" "McMillen" _) = "Welcome home, Isaac"
greet (Person f l age) | age < 18   = "Thou shall not pass"
                       | otherwise  = "Hello " ++ (fullname (Person f l age))

If you compare it to the first version, you can notice that the last case is more verbose. With this version, we had to rebuild a Person to obtain its fullname. How stupid is this?! Well Actually, the stupid one isn’t Haskell in this case, it’s me, since pattern matching can do better than the previous version:

greet :: Person -> String
greet (Person "Isaac" "McMillen" _)   = "Welcome home, Isaac"
greet p@(Person _ _ age) | age < 18   = "Thou shall not pass"
                         | otherwise  = "Hello " ++ (fullname p)

The part p@(Person _ _ age) means that we’re looking for a person, we assign this person to the p value and we assign the person age to the age value. Concise, efficient, functional.

Pattern matching is so useful in functional programming that we often don’t use accessors present in our datatype. A straightforward consequence is that we often omit the accessors wen we define types. For example, another possible definition of Person might be: data Person = Person String String Int. Short enough?

Introduction to "Make it functional"

13 Sep 2012

I started the “Make it functional” category of my weblog to help imperative programmers to understand some of the reasons that make us, functional programmers, love this approach and find it more convenient than the imperative one in most situations. My goal is not to start a flame war or to claim that one point of view is better than the other (even if… No, ok, forget about it) but to show through examples how convenient functional programming can be in many situation.

I know there exists many introductions and documentations for functional programming but I haven’t seen any that introduces functional programming concepts comparing them with the imperative object oriented world (ok, I didn’t spend too much time searching).

This weblog is especially dedicated to those aren’t especially interested in how things work but rather on how things can help.

Oh, by the way, the examples in the next post will be in Haskell and Java but I’m going to introduce them in the most language agnostic way.

Finally, English is not my native language (as you may already have noticed), so feel free to mail me any correction.

Un troisième premier billet

12 Sep 2012

J’ai peu écrit ces derniers mois et j’ose espérer que c’est en grande partie à cause de l’outil. Ne pas avoir la main sur l’outil que j’utilise, utiliser des interfaces lourdes pour gérer la publication. Tout cela ne me convenait pas. J’essaie aujourd’hui de recommencer tout cela de manière plus efficace. Plus structurée. Bref, j’essaie de retrouver les émois de mes débuts, 10 ans après.

Par rapport à ce que j’ai eu l’habitude de faire, j’espère quelques changements. Tout d’abord, je vais me mettre à rédiger un peu plus en anglais, notamment sur les sujets techniques. Il y a de fort risques que cela représente une grosse partie de mon activité. Moins de billet généraux sociétaux, etc. Plus de billets techniques et ou ciblés sur mes hobbies. On parlera de code et de jeux de société notamment, ce qui explique le nouveau titre. L’idée est aussi de séparer aussi clairement que possible les différentes parties, pour que vous puissiez suivre facilement ce qui vous intéresse.

Pour ceux qui sont curieux de savoir comment tout cela tourne, quelques informations sur la solution choisie. Ce blog est hébergé sur github. L’idée est d’avoir une solution rapidement déployée, dirigeable depuis un repository git. Les billets sont écrits directement avec la syntaxe markdown et le passage à un site web est assuré par jekyll. Pour les commentaires, c’est externalisé chez disqus. Pour les deux inquiets du fond, l’ancien blog est toujours disponible.