100 Languages Speedrun: Episode 96: Langage Linotte
Tags: french, programming, education
Published: 2022-02-19 00:37:34

I've done [programming in Portuguese](https://dev.to/taw/100-languages-speedrun-episode-85-linguagem-potigol-3829), and [in Tamil](https://dev.to/taw/100-languages-speedrun-episode-94-ezhil-6k5), now it's time for some French with [Langage Linotte](https://github.com/cpc6128/LangageLinotte).

There are very few modern programming languages not based on English. There's a bunch of long-forgotten Pascal of Fortran clones from 1970s and 1980s, and a few one-hackathon throwaway projects, and a small number of educational languages. I don't think anyone created a non-English-based language meant for serious production use since the Cold War.

There are no packages, so to run it you'll need to git checkout and compile it yourself (but I also included the `jar` with episode's code). Langage Linotte is meant to be used primarily in its IDE, but to make it easier to blog I'll be running it from the console.

### Hello, World!

After building `Atelier.jar`, we can create this file:

```
affiche "Bonjour le monde!"
```

And run in like this:

```
$ java -jar Atelier.jar -c bonjour.liv
Bonjour le monde!
```

There's no way to do a `#!`.

If you're wondering where the `.liv` extension comes from, it's from "livre" (book), as everything gets renamed in Langage Linotte. Variable is "acteur", type is "role", and so on.

### User input

```
nom est un texte
affiche "Quel est votre nom?"
demande nom
affiche "Bonjour " + nom + "! Bienvenue à Paris!"
```

```
$ java -jar Atelier.jar -c bonjour2.liv
Quel est votre nom?
>Emily
Bonjour Emily! Bienvenue à Paris!
```

Step by step:

* we can declare variables with `<variable> est un <type>`
* there's no string interpolation, so we need to `+` them together
* we can ask for user input with `demande <variable>` - it prints default prompt `>`

### Loop

Before we start a loop we need to declare type of the variable, sorry, "role" of the "acteur".

The loop can be declared with `pour <variable> de <start> à <end> ... ferme`.

```
i est un nombre
pour i de 1 à 20
  affiche i
ferme
```

```
$ java -jar Atelier.jar -c circuit.liv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
```

### FizzBuzz

Langage Linotte only has decimal numbers, no `%`, no integer division, and apparently no way to round numbers, so the usual way to do FizzBuzz won't work. Instead we'll use counters.

```
i est un nombre
fizz est un nombre valant 0
buzz est un nombre valant 0

pour i de 1 à 100
  incrémente fizz
  incrémente buzz
  si (fizz == 3) et (buzz == 5)
    affiche "FizzBuzz"
    fizz prend 0
    buzz prend 0
  ferme
  sinon si buzz == 5
    affiche "Buzz"
    buzz prend 0
  ferme
  sinon si fizz == 3
    affiche "Fizz"
    fizz prend 0
  ferme
  sinon
    affiche i
  ferme
ferme
```

Stey by step:

* we declare `i` as the main counter, and a few extra counters `fizz` and `buzz`
* we can declare and assign initial value with `<variable> est un <type> valant <initial value>`
* all counters increase by `1` every iteration
* we could also do `fizz = 0` instead of `fizz prend 0`; or `fizz += 1` instead `incrémente fizz`, but this seems more in the spirit of the language
* whenever `fizz` counter hits `3` or `buzz` counter hits `5` we print something else and reset that counter to `0`
* `si / sinon si / sinon` is `if / if else / else` - but each such block needs to end with `ferme`

### Fib

Somehow functions need to be placed after main body, otherwise the program doesn't work. There's string interpolation, so that's nice:

```
i est un nombre
pour i de 1 à 20
  affiche "fib(${i})=${fib(i)}"
ferme

fib : n
	si n <= 2 retourne 1
	sinon retourne fib(n-1) + fib(n-2)
```

```
$ java -jar Atelier.jar -c fib.liv
fib(1)=1
fib(2)=1
fib(3)=2
fib(4)=3
fib(5)=5
fib(6)=8
fib(7)=13
fib(8)=21
fib(9)=34
fib(10)=55
fib(11)=89
fib(12)=144
fib(13)=233
fib(14)=377
fib(15)=610
fib(16)=987
fib(17)=1597
fib(18)=2584
fib(19)=4181
fib(20)=6765
```

### Wordle

I got some French wordlist [from this repository](https://github.com/Taknok/French-Wordlist/blob/master/francais.txt), and here's a French Wordle:

```
mots est un casier de textes depuis "french-wordle.txt"
index est un nombre
index prend mots.taille()
mélange index
mot est un texte valant mots{index}
devine est un texte

tant que devine != mot
  questionne devine sur "Devine un mot:"
  si devine.taille() != 5
    affiche "Le mot doit être 5 lettres"
  ferme
  sinon
    affiche wordle(mot, devine)
  ferme
ferme

wordle : mot, devine
  i est un nombre
  j est un nombre
  résultat est un texte
  pour i de 0 à 4
    j prend mot.position(0, devine{i})
    si (mot{i}) == (devine{i})
      résultat += "🟩"
    ferme
    sinon si j != -1
      résultat += "🟨"
    ferme
    sinon
      résultat += "🟥"
    ferme
  ferme
  retourne résultat
```

```
$ java -jar Atelier.jar -c wordle.liv
Devine un mot:
>route
🟨🟥🟥🟥🟨
Devine un mot:
>elire
🟨🟥🟥🟨🟨
Devine un mot:
>nager
🟨🟩🟥🟩🟩
Devine un mot:
>paner
🟥🟩🟩🟩🟩
Devine un mot:
>faner
🟩🟩🟩🟩🟩
```

There's a lot going on here:

* `mots est un casier de textes depuis "french-wordle.txt"` - declares `mots` as array of strings, but it also reads it line-by-line from a file, something not really seen in most languages
* to get random number from 0 to N-1, we need to assign N to something, then `mélange` that thing - N obviously being size of `mots` (`mots.taille()`)
* `tant que <condition> <body> ferme` is a while loop
* `questionne <variable> sur <prompt>` is another way to input like `demande <variable>`, it still displays extra `>` prompt
* printing appends newline, so we build a string character by character in `résultat` and print it at the end
* declaring `résultat est un texte` initializes it to an empty string

### Should you use Langage Linotte?

Langage Linotte is really good at protecting the user from any English, even better than Linguagem Potigol where it occasionally slipped through, so at least that's working.

Overall I found it much less fun than Linguagem Potigol. Linguagem Potigol felt like a real programming language which just happened to be in Portuguese, Langage Linotte felt like French AppleScript. Far too much focus on "natural language" side, so it was always a mystery how to do something even slightly different.

Error messages were quite weak (`Impossible d'analyser syntaxiquement la ligne. Ligne : 4` is about how much you'd get), priority of operators was weird (all those weirdly placed parentheses are all necessary), and for example if I tried to print the result instead of returning it, the program would mysteriously just exit after one loop instead of telling me what's wrong.

I know it sounds silly, but Linguagem Potigol had far better documentation. Sure, both of them were in languages I don't speak (beyond "un croissant s'il vous plait" and such key phrases), but Linguagem Potigol has ANTLR grammar file, and at least I could see 100% of its grammar there, and all the methods were listed in a few Scala files per type, and overall it seemed to have more logic to what it was doing. If class `Textos` contains `def contem(a: Caractere): Lógico = _lista.contains(a)`, you can tell exactly what's going on even if your Portuguese is nonexistent. Not to mention Linguagem Potigol's standard library was far closer to complete, so most of the methods I wanted were there.

With Langage Linotte I had to bounce between documentation, really verbose Java source code, limite examples, and Google Translate to get anywhere.

Overall all such languages make sense if you want to learn programming, and you refuse to learn any English first, but they really vary in quality.

### Code

[All code examples for the series will be in this repository](https://github.com/taw/100-languages-speedrun).

[Code for the Langage Linotte episode is available here](https://github.com/taw/100-languages-speedrun/tree/master/episode-96-langage-linotte).