DEV Community

Tomasz Wegrzanowski
Tomasz Wegrzanowski

Posted on

100 Languages Speedrun: Episode 96: Langage Linotte

I've done programming in Portuguese, and in Tamil, now it's time for some French with Langage Linotte.

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!"
Enter fullscreen mode Exit fullscreen mode

And run in like this:

$ java -jar Atelier.jar -c bonjour.liv
Bonjour le monde!
Enter fullscreen mode Exit fullscreen mode

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!"
Enter fullscreen mode Exit fullscreen mode
$ java -jar Atelier.jar -c bonjour2.liv
Quel est votre nom?
>Emily
Bonjour Emily! Bienvenue Γ  Paris!
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
$ 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode
$ 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
Enter fullscreen mode Exit fullscreen mode

Wordle

I got some French wordlist from this repository, 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
Enter fullscreen mode Exit fullscreen mode
$ 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
🟩🟩🟩🟩🟩
Enter fullscreen mode Exit fullscreen mode

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.

Code for the Langage Linotte episode is available here.

Top comments (0)