OK ? Eliminer la complexité inutile des langages de programmation actuels

Par:
fredericmazue

mer, 31/08/2022 - 13:07

OK ? est un nouveau langage de programmation à typage dynamique. Son concepteur le décrit comme un langage avec une vision pour l’avenir, et comme un langage qui élimine la complexité inutile des langages de programmation d'aujourd'hui et qui vous permet de vous concentrer sur ce qui compte : écrire du code qui fait la différence.

Encore un langage mieux que les précédents... Toutefois quand on lit sa présentation sur GitHub, on ne peut s’empêcher de penser qu’il s’agit plus d’une plaisanterie que d’autre chose. Mais cela vaut le détour :-)

Ca commence assez raisonnablement pourtant. L’auteur justifie l’absence d’opérateur ternaire. Donc en OK ? pas de chose comme ceci :

let a = isprod ? 'prod' : 'dev';

mais

let a = switch isprod {
  case true: "prod";
  case false: "dev";
}

Nous apprenons ensuite que OK ? a des instructions switch lisibles :

// INVALID:
switch x {
  case true:
    z = z + 2
  case false:
    x = x + 1;
    y = y - 1; // <-- ERROR: switch blocks can only contain a single statement
}

// VALID:
let onfalse = fn() {
  x = x + 1;
  y = y - 1;
};

switch x {
  case true: z = z + 2;
  case false: onfalse();
}

Cela garantit la séparation des préoccupations : la logique spécifique au cas par cas est éliminée, amenant les cas eux-mêmes au premier plan, écrit l’auteur. Admettons :-)

En OK ? il n’y a pas de valeurs nulles. Celles-ci sont remplacées par NO :

let x = NO!
puts(ayok?(x)) // prints 'false'

let y = 10
puts(ayok?(y)) // prints 'true'

(ayok est une fonction intégrée du langage)

L’auteur a mis en place un traitement des erreurs dans lequel ces dernières sont 'simplement' des valeurs :

let divide = fn(a, b) {
  return switch b {
    case 0: [NO!, "cannot divide by zero"];
    default: [a / b, ""];
  };
};

result = divide(5, 0)
switch result[1] {
  case "": puts(result[0])
  default: puts(result[1]) // prints "cannot divide by zero"
}

Pas de magie, juste des tableaux et des chaînes, précise l'auteur.

OK ? ne dispose que d’un opérateur de comparaison. L’auteur explique : Vous êtes-vous déjà retrouvé à tourner en rond à la recherche du bon opérateur de comparaison ? Au lieu de perdre du temps à mémoriser les hiéroglyphes de ==, !=, >, <, >=, et <=, et si nous vous disions que vous n'en avez besoin que d'un seul ?

Autres languages

Avec OK?

a >= b

a >= b

a <= b

b >= a

a > b

!(b >= a)

a < b

!(a >= b)

a == b

let x = a >= b; let y = b >= a; x && y

a != b

let x = !(a >= b); let y = !(b >= a); x || y

Il est vrai qu’à partir de cela, il suffit d’écrire une fonction que la bibliothèque standard ne propose pas

let equals = fn(a, b) {
  let x = a >= b;
  let y = lazy b >= a;
  return x && y;
}

:-)

OK ? met également fin à la priorité des opérateurs :

Dans OK ? 5 + 2 * 3 vaut 21, et non 11, car l'addition et la multiplication ont la même priorité d'opérateur. Si vous souhaitez évaluer votre expression dans un autre ordre, il vous suffit d'utiliser des parenthèses : 5 + (2 * 3).

Cette simple valeur par défaut de gauche à droite vous évite de fouiller sur Internet à la recherche d'un tableau de priorité des opérateurs et vous permet de garder les yeux sur le code, souligne l’auteur.

OK ? n’a qu’une seule construction de boucle : la fonction map, qui a comme caractéristique d’être concurrente.

Ainsi Map se comporte de la même manière que les fonctions map dans d'autres langages, à une exception près : les rappels sont toujours exécutés simultanément.

Par exemple, l'extrait de code suivant renvoie un résultat en une seconde :

let doubled = map([1,2,3], fn(e) {
  sleep(1); // sleep one second
  e * 2
}); // [2,4,6] obtained in one second

Si vous souhaitez simplement calculer deux valeurs coûteuses simultanément, vous pouvez utiliser map avec un commutateur :

let result = map([0,1], fn(e, i) {
  switch i {
  case 0:
    return expnsiv1();
  case 1:
    return expnsiv2();
  }
});
let value1 = result[0];
let value2 = result[1];

Avec l'union de la concurrence et de l'itération, le ciel est la limite, ajoute l’auteur

let every = fn(arr, check) {
  let passed = true;
  map(arr, fn(e) {
    switch check(e) { case true: passed = false; } }
  )
  return passed;
};

result = every([5,2,4,1,3], fn(e) { return e >= 2 }); // false

OK ? a aussi une approche particulière de la programmation objet. Ainsi les classes ne supportent pas l’héritage et ce sont plus des structures que de classes au sens d’autres langages. Pour bien marquer la différence avec les autres langages, le mot clé pour déclarer une classe est notaclass (ou nac) :

notaclass person {
  field name
  field email

Tous les champs sont privés, et il n’y a pas de constructeur en OK ? On écrit donc simplement une méthode pour initialiser les champs :

notaclass person {
  field name
  field email

  public init fn(selfish, name, email) {
    selfish.name = name;
    selfish.email = email;
  }
}

let p = new person()
p.init("Jesse", "jesse@test.com")

OK ? est lui même écrit en Go. Quelle est exactement la vision pour l’avenir de OK ? évoquée par son auteur ? Continuer à nous amuser, probablement :-)

OK ? est un logiciel libre sous licence MIT, disponible sur GitHub. 

Commentaires

On sent une énorme inspiration Rust et C++ dans ce langage trollesque :^)
Merci pour la découverte !