V est un langage récent (première version libre sortie en 2019) développé initialement par Alex Medvednikov pour ses propres besoins sur le logiciel volt.
Dans cette dépêche, j'aimerais vous le faire découvrir, et, je l'espère, vous donner le goût d'en découvrir d'avantage.
Sommaire
-
- Introduction
- Historique
-
Rapide tour d’horizon
- Installation
- Compiler et exécuter du code
- Hello World
- Des variables immuables par défaut
- Des fonctions typées avec plusieurs retours possibles
- Des conditions sans parenthèse
- Uniquement des boucles
for
- Des octets et des runes
- Un modèle objet par composition
- Les
match
un emprunt bien sympa - La programmation parallèle sans effort et sans danger
- Les sum types
- Une gestion d’erreur moderne
- Les génériques
- Le fonctionnement des modules
- Quelques sucres syntaxiques « magiques »
- Les grandes caractéristiques du langage
- Questions en vrac sur le langage
- Conclusion
Introduction
J’étais tombé, il y a quelque temps, sur un article sur developpez.com annonçant que le langage V venait d’être Open source. À l’époque, j’avais simplement été étonné par la légèreté et la rapidité annoncée du langage, tout en voyant qu’à peine sorti il était déjà beaucoup critiqué, nous y reviendrons.
Puis, je ne sais pas trop pourquoi, un jour je me suis rappelé de ce langage qui semblait vouloir tout réinventer, jusqu’à pouvoir même se passer de la libc.
Piqué par la curiosité, j’ai décidé de lui donner une chance. Comme commençait l’excellent « calendrier de l’avent du code », que je venais de découvrir, je me suis dit que j’allais le réaliser avec V.
Les puzzles des différents jours de ce challenge serviront d’exemple. Notez qu’ils ne se suffisent généralement pas à eux-mêmes et ne compileront pas. J’ai cependant préféré mettre des extraits de code réel que des bouts de code de démonstration. Autant que possible, j’ai mis un lien vers le code utilisé.
Historique
C’est, à la base, une sorte de « clone de go » qui génère du C (compilé ensuite en langage machine par un compilateur type tcc ou gcc, voir cette section pour plus de détail) qui a vite évolué pour devenir un langage à part entière.
Il tente de faire le grand écart entre la facilité d’utilisation d’un langage « haut niveau » tels que Python ou JavaScript et des performances que l’on retrouve généralement avec des langages plus « bas niveau » tels que C/C++ ou Rust. Après plusieurs versions alpha, le langage est aujourd’hui en phase de bêta avec une v0.4 sortie récemment (la 0.4.1 vient tout juste de sortir).
L’objectif étant, comme pour Go, qu’au moment de la sortie de la v1.0 le langage soit considéré comme stable et assure une rétro compatibilité de tous programme écrit depuis la v1.0.
Ah, j’allais oublier le plus important : V a une sympathique mascotte depuis quelques années !
Rapide tour d’horizon
Sans vouloir être aussi exhaustif que la doc officielle ou ce superbe guide, parcourons ensemble les éléments important du langage.
La syntaxe de V est quasiment identique à celle de Go avec quelques emprunts à Rust.
L’objectif étant de ne pas réinventer la roue, mais — justement — permettre aux développeurs d’appréhender ce langage le plus rapidement et sans surprises.
C’est une syntaxe de type « C » (avec les accolades), mais très épurée. Je crois que c’est une de mes syntaxes préférée. Très lisible avec peu de mots clés.
V n’est pas une révolution, mais s’inspire de beaucoup d’autres langages pour en prendre les meilleurs concepts et les intégrer dans une syntaxe à la fois accessible et pragmatique. Ce qui le fait s’écarter de la « pureté » de langage comme Zig ou Rust, qui préfèrent avoir une syntaxe souvent plus verbeuse, mais plus exacte. En résulte un langage aussi expressif que Python, Ruby ou Javascript, mais avec une compilation avant l’exécution (ce n’est pas un langage interprété), un typage fort et des performances proches du C.
Installation
Le langage s’installe facilement. La méthode la plus simple (peut-être la seule actuellement ?) est de cloner le dépôt git :
git clone https://github.com/vlang/v
cd v
make
Le tout compile en quelques secondes grâce à un binaire tcc
téléchargé pendant le make.
Il n’y a même pas de cible install
dans le makefile, juste un petit argument symlink
au binaire pour créer un lien symbolique vers le dossier des binaires de votre système (/usr/local/bin/v
sur les systèmes Unix).
sudo ./v symlink
Compiler et exécuter du code
La commande run
permet de compiler (générer un code C puis le compiler, voir plus bas) et exécuter du code contenu dans un fichier.
Exemple :
v run hello_world.v
Hello World
Le traditionnel « Hello world » peut s’écrire de manière simplifiée :
println("Hello world")
La fonction main
n’étant pas obligatoire dans les petits programmes.
La version plus verbeuse serait :
fn main() {
println("Hello world")
}
Des variables immuables par défaut
Les variables dans V sont immuables par défaut. C’est un choix fort du langage qui s’inspire ici des langages fonctionnels.
Autre choix important : il n’est pas possible de déclarer des variables en dehors d’une fonction, seules les constantes peuvent l’être (comme en Rust).
La déclaration de variables se fait de manière similaire à Go, avec un opérateur :=
qui se distingue de l’opérateur d’affectation =
.
Cette différence d’opérateur peut rebuter au premier abord, mais elle permet de ne pas accidentellement affecter une variable existante quand on voulait en créer une.
À noter que, contrairement à Rust, le shadowing (redéfinition d’une variable portant le même nom) n’est pas autorisé.
Le typage n’est pas nécessaire pour les types de base.
fn play_with_variables() {
// Nombre immuable en int32 par defaut
a := 5
// Interdit
a = 4
// unsigned 64 mutable
mut departure_values := u64(1)
// autorisé
departure_values = 2
// string
input := '8,13,1,0,18,9'
}
// les constantes se déclarent en dehors des fonctions avec une instruction
// spéciale et peuvent être utilisées dans tout le module et exportée
const (
n = 30000000
k = 6
i0 = k - 1
)
Des fonctions typées avec plusieurs retours possibles
La déclaration de fonctions est quasi identique à celle de Go, avec une petite nuance, le mot clé fn
est utilisé au lieu de func
(comme dans Rust).
Les types de paramètres sont obligatoires et positionnés à droite du nom (contrairement aux autres langages de type « C »).
fn parse_ticket(ticket_str string) []int {
return ticket_str.split(',').map(it.int())
}
// Il est possible de renvoyer plusieurs valeurs
fn get_pos(str_pos string) (int, int, int) {
pos := str_pos.split(',').map(it.int())
return pos[0], pos[1], pos[2]
}
x_pos, y_pos, z_pos := get_pos(str_pos)
À noter que, pour l’instant, il n’est pas possible de définir des valeurs par défaut pour les paramètres, ni de nommer les paramètres lors de l’appel de la fonction (comme en Python). Des discussions sont en cours, mais aucune décision n’a été prise.
Des conditions sans parenthèse
Tout comme en Go, la syntaxe des if/else
se fait sans parenthèse (sauf si nécessaire).
// Sans parenthèse
if letter_count >= policy_min && letter_count <= policy_max {
valid_password_count++
}
// Avec
if (value >= rule[0] && value <= rule[1]) ||
(value >= rule[2] && value <= rule[3]) {
valid = true
}
// if/else if
if f.ends_with('cm') {
return height >= 150 && height <= 193
} else if f.ends_with('in') {
return height >= 59 && height <= 76
}
Uniquement des boucles for
Comme en Go (et oui syntaxiquement V est très proche de Go), seul le mot clé for
permet de faire des boucles.
Il sert à tout : itérer sur des chaînes de caractères, des tableaux ou des maps, boucler un certain nombre de fois, boucler à condition, boucler indéfiniment, etc.
// sur une string
for l in password {
if l == letter {
letter_count++
}
}
// sur des tableaux
answers_group := answers_content.split('\n\n')
answers := answers_group.map(it.replace('\n', ''))
mut yes_count := 0
for group in answers {
yes_count += remove_duplicates(group).len
}
// sur des map
for index, line in toboggan_map[slope['down']..toboggan_map.len] {
if index % slope['down'] != 0 {
continue
}
x_pos = (x_pos + slope['right']) % line.len
if line[x_pos] == `#` {
tree_encountered++
}
}
// En itérant entre 2 écarts (la valeur de droite étant exclue)
// "_" n'était pas traité par le compilateur comme une variable non utilisée
for _ in 0 .. num_cycles {
grid = run_cycle(grid)
}
// Syntaxe plus classique, parfois utile
for i := i0; i + 2 <= n; i++ {
// ...
}
// Boucle infinie
for {
if program[cursor].executed {
break
}
// ...
}
Des octets et des runes
Le type string
en V est en fait un simple tableau d’octets immuable.
C’est très performant, mais si on veut travailler sur des chaînes UTF-8 par exemple, c’est un peu problématique étant donné que certains caractères sont codés sur plusieurs octets.
mut s1 := 'toto'
assert s1.len == 4
// Important les string sont immuables
s1[1] = 'a' // Ne compile pas
s2 := '한국/韓國'
assert s2.len == 13 // Et oui c'est la taille en octets
// L'iteration n'aura pas trop de sens non plus...
for b in s2 {
println(b)
}
Heureusement, V permet aussi de travailler à ce niveau-là grâce à la fonction .runes()
.
s2 := '한국/韓國'
assert s2.runes().len == 5
for b in s2.runes() {
println(b)
}
Comme en Go, V distingue les chaînes de caractère des runes via l’utilisation des accents graves.
rocket := `🚀`
assert typeof(rocket) == 'rune'
str := 'launch 🚀'
assert typeof(str) == 'string'
J’apprécie vraiment cette distinction, c’est un confort quand on travaille sur les chaînes de caractère.
Un modèle objet par composition
J’ai longtemps cru au paradigme objet avec tous ses beaux concepts : l’héritage, les accesseurs, le polymorphisme, j’en passe et des meilleurs.
Il faut dire que mes enseignants nous avaient vendu la programmation objet comme l’outil ultime de conception de code (oui l’UML tout ça)…
Comme beaucoup, j’ai déchanté en me cassant les dents avec des arbres d’héritage obscurs et trop complexes, en surchargeant sans m’en rendre compte (certains langages le permettent) des fonctions de la classe mère, en pensant « objet », là où il fallait plutôt penser « données », en écrivant des accesseurs inutiles, etc.
Le seul aspect « intéressant » de la programmation orienté objet est pour moi le fait de pouvoir associer des méthodes à une variable composée (disons une structure). C’est plus élégant et plus lisible.
Je préfère de loin écrire a.push(1)
que array_push(a, 1)
ou Array.push(a, 1)
.
V emprunte le même modèle « objet » que Go en permettant d’associer des fonctions à des structures et la composition de structure.
De cette manière on peut créer des structures qui « héritent » du fonctionnement d’autres structures, sans risquer de tomber dans les problèmes liés à la verticalité.
Plusieurs types peuvent partager une même signature en implémentant une interface. Étonnamment, il y a un mot clé pour définir une interface, mais pas pour l’implémenter.
À la différence de Go, les interfaces peuvent contenir des données et pas seulement des méthodes.
Les match
un emprunt bien sympa
match
est un mot clé visiblement issu du monde de la programmation fonctionnelle. J’ai découvert ce concept pour la première fois avec Elm (appelé case
), mais il venait très probablement d'Haskell, Rust aussi le propose.
C’est une sorte de « super switch/case », une syntaxe permettant d’enchaîner des conditions, tout en limitant au maximum le code à écrire.
Comparaison de chaîne, d’entier, inclusion d’une valeur dans un rang alphanumérique, type de la donnée, beaucoup des conditions que l’on pourrait écrire avec un if/else
sont plus simples à écrire avec match
À la différence d’un switch/case, il n’est pas nécessaire d’utiliser l’instruction break
pour éviter d’aller dans les branches du dessous et comme avec le default
de switch/case, on passe forcément dans une des branches avec ici une instruction else
obligatoire à la fin.
os := 'windows'
print('V is running on ')
match os {
'darwin' { println('macOS.') }
'linux' { println('Linux.') }
else { println(os) }
}
La programmation parallèle sans effort et sans danger
V a emprunté à Go le principe du fonctionnement du mot clé go
pour rendre n’importe quelle fonction parallélisable.
Pour l’instant V crée de vrais processus et non les fameuses « goroutines » qui sont, en quelque sorte, des processus allégés pouvant être créés par milliers. C’est pour ça que le mot clé go
a été remplacé par spawn
L’implémentation des « goroutines » est prévue dans les futures versions.
Il emprunte aussi à Go la notion de channel qui simplifie grandement la communication entre différents processus.
import sync
import time
fn task(id int, duration int, mut wg sync.WaitGroup) {
println('task $id begin')
time.sleep_ms(duration)
println('task $id end')
wg.done()
}
fn main() {
mut wg := sync.new_waitgroup()
wg.add(3)
spawn task(1, 500, mut wg)
spawn task(2, 900, mut wg)
spawn task(3, 100, mut wg)
wg.wait()
println('done')
}
Les sum types
Les « sommes de types » sont un concept encore emprunté au monde fonctionnel (en tout cas, je les ai aussi découverts avec Elm) qui, aujourd’hui, se démocratise, on les retrouve notamment dans Rust, Zig et TypeScript (et sans doute dans d’autres langages).
L’idée est simple : pouvoir définir des types de données « conditionnels ». Entendez par là, une variable peut avoir « tel ou tel type ».
Là où les structures sont des types de données « additionnels » (une personne a une chaîne de caractère prénom et une chaîne pour son nom), les sommes de type permettent de définir des types de données conditionnelles (exemples tiré de cet article, tous les exemples donnés ne sont pas valables en V) :
- Un dé peut avoir 6 ou 20 faces
- Une publication peut avoir un seul auteur (chaîne de caractère) ou plusieurs (tableau de chaîne)
- Un créateur peut être un artiste ou un auteur en fonction du domaine
- L’ouverture d’un fichier peut renvoyer le fichier ou une erreur
- L’accesseur d’un tableau peut renvoyer une donnée ou rien si on est hors du tableau
// Ici la valeur du token peut soit être une string ou un entier non signé sur 64 bits
type TokenValue = string | u64
struct Token {
kind TokenKind
val TokenValue
loc int
mut:
next &Token = 0
}
Une gestion d’erreur moderne
Comme Zig, V intègre la notion d’erreur dans le retour d’une fonction via le caractère !
au début de la déclaration de type ce qui force à gérer l’erreur directement dans la fonction appelante ou à faire remonter l’erreur plus haut.
Cette façon de faire évite d'avoir recours aux exceptions.
// Notez le `!` devant le type de retour pour spécifier que la fonction peut retourner une erreur
fn (r Repo) find_user_by_id(id int) !User {
for user in r.users {
if user.id == id {
return user
}
}
return error('User ${id} not found')
}
fn main() {
repo := Repo{
users: [User{1, 'Andrew'}, User{2, 'Bob'}]
}
// Le mot clé `or` permet de gérer le cas d'erreur
user := repo.find_user_by_id(10) or { User{-1, 'Unknown'} }
println(user)
// On peut aussi utiliser un if/else
if user := repo.find_user_by_id(10) {
println(user)
} else {
// Contrairement à Zig qui permet de « capturer » l’erreur via |err| ici la variable `err` est automatiquement créée
// C’est un choix critiquable, mais je trouve que ça force une convention de code
println(err)
}
// On peut aussi décider de propager l’erreur, dans ce cas le programme s’arrêtera vu qu’on est dans la fonction `main`
user := repo.find_user_by_id(10)!
}
V intègre aussi la notion de retour optionnel (Option/Result type, concept encore emprunté à la programmation fonctionnelle il me semble) via le caractère ?
lui aussi à placer au début de la déclaration de type de retour d’une fonction. Cela permet de spécifier qu’une fonction peut renvoyer un résultat potentiellement vide et permet notamment d’éviter d’avoir des pointeurs null.
// Ici au lieu d’une erreur on renvoie `none`, notez le `?` devant le type de retour
fn (r Repo) find_user_by_id(id int) ?User {
for user in r.users {
if user.id == id {
return user
}
}
return none
}
Ici aussi le compilateur force le développeur à gérer le cas.
Fort heureusement, des sucres syntaxiques bien pratique permettent de gérer facilement les cas où une valeur n’est pas disponible.
Les génériques
À la différence de Go (même si depuis go les a aussi intégrés finalement), V permet l’écriture de code générique.
Pour l’instant, seul un paramètre « template » est pris en compte, mais cette limitation va rapidement être levée.
struct Repo[T] {
db DB
}
fn new_repo[T](db DB) Repo[T] {
return Repo[T]{db: db}
}
// This is a generic function. V will generate it for every type it's used with.
fn (r Repo[T]) find_by_id(id int) ?T {
table_name := T.name // in this example getting the name of the type gives us the table name
return r.db.query_one[T]('select * from ${table_name} where id = ?', id)
}
db := new_db()
users_repo := new_repo[User](db) // returns Repo[User]
posts_repo := new_repo[Post](db) // returns Repo[Post]
user := users_repo.find_by_id(1)? // find_by_id[User]
post := posts_repo.find_by_id(1)? // find_by_id[Post]
Le fonctionnement des modules
Quelques sucres syntaxiques « magiques »
Des sucres syntaxiques « un peu magiques, mais bien pratiques » pour les fonctions map
, filter
et sort
avec des variables locales automatiquement créées :
a := [1, 2, 3, 4]
b := a.map(it + 1) // it représent l'item courant
println(b) // affiche [2, 3, 4, 5]
mut c := [2, 4, 3, 1]
c.sort(a < b) // a et b réprésente les deux items à comparer
println(c) // affiche [1, 2, 3, 4]
Ces sucres syntaxiques (appelés "compiler magic") sont utilisés à d'autres endroits, notamment dans la bibliothèque SQL (voir plus bas)
Les grandes caractéristiques du langage
Un langage plus transpilé que compilé
La première chose à savoir sur V est que par défaut, il ne fournit pas un véritable compilateur, mais qu’il s’agit plus d’un transpileur vers C. Le code est par la suite compilé via tcc (option par défaut) ou gcc (avec l’argument -prod
). Bien sûr, vous pouvez utiliser clang aussi.
Il existe une fonctionnalité, expérimentale pour l’instant, qui permet la compilation sans passer par du C, mais il semble que le C restera l’option par défaut si l’on veut avoir de bonnes performances et une prise en charge d’un maximum de plateformes.
Ce choix de la transpilation peut étonner au premier abord, mais, en réalité je le trouve extrêmement judicieux, il permet :
- d’avoir de très bonnes performances sans effort vu qu’on bénéficie de dizaines d’années d’optimisation des compilateurs C existants,
- une compatibilité « gratuite » avec toutes les plateformes existantes permettant un usage aussi bien sur nos ordinateurs, que sur ordiphone ou encore dans l’embarqué (j’ai pu par exemple compiler du V sur Nintendo DS sans trop d’effort),
- dans le cas de V, une intégration transparente et n’induisant pas un surcoût de performance avec les bibliothèques C existantes.
Bien sûr, d’autres langages y ont pensé, on pourra notamment citer Vala qui transpile une sorte de C# vers C, mais qui est très fortement lié au projet Gnome et ne semble pas avoir décollé en dehors de cet usage.
Il y a aussi nim, dont l’approche est très similaire à V.
La différence entre ces deux langages est résumée sur cette page :
- nim utilise clang comme compilateur par défaut alors que V se base sur TCC,
- Le code C généré par nim n’est pas fait pour être lu par des humains alors que V génère un code C plutôt lisible,
- la syntaxe nim est plus proche de Python que de Go,
- Nim utilise un ramasse-miette pour gérer la mémoire allouée sur le tas, alors que V vise une approche différente à terme (pour le moment il utilise aussi un ramasse-miette).
À noter que le langage zig s’est récemment doté d’un backend C
On dit du C qu’il est une sorte « d’assembleur glorifié », on peut ainsi dire de V qu’il est une sorte de « C glorifié ».
En ce sens, il se rapproche peut-être plus de bibliothèques comme Cello, tout en poussant le concept plus loin en proposant un vrai compilateur et tout un écosystème qui lui est propre.
Une ABI compatible avec C
Un des très bons choix du langage est d’avoir une ABI compatible avec celle du C.
Cela permet de pouvoir très facilement utiliser des bibliothèques C depuis V sans avoir besoin d’écrire du code de compatibilité (wrapper) entre les deux langages.
C’est un aspect du langage, que l’on retrouve dans zig aussi, que j’apprécie particulièrement, car il ouvre la voie à l’utilisation de tout un tas de bibliothèques fantastiques.
Et cela va dans les deux sens, on peut aussi écrire des modules ou bibliothèques en V utilisables dans un programme C.
Un langage minimaliste
Si on devait décrire V avec un seul mot, ce serait sans doute « minimalisme ».
Cet état d’esprit ne se retrouve pas que dans sa syntaxe, mais aussi dans la limitation des dépendances utilisées par la bibliothèque standard et dans la légèreté du code généré.
On revient aux sources en quelque sorte en limitant les couches d’abstraction (vous me direz, c’est déjà une abstraction du C), tout en ayant une approche moderne.
J’aime vraiment cette idée d’avoir un langage permettant de créer tout un panel d’applications facilement, tout en offrant des performances excellentes, une empreinte mémoire minimale et peu de dépendances.
Un des principes de V est qu’il ne doit y avoir qu’une seule manière de faire les choses.
Par exemple, V ne propose pas une syntaxe spécifique pour les ternaires (comme Go), mais utilise simplement l’instruction if/else
, le résultat pouvant être utilisé pour affecter une variable.
max = if current > max { current } else { max }
Un langage typé qui compile vite
C’est un point que V partage avec Go.
Ayant commencé ma carrière professionnelle sur une grosse base de code C++ qui mettait plus de 15min à compiler et ce, malgré une compilation distribuée sur plusieurs machines, je dois avouer que c’est un bonheur de compiler un projet en quelques secondes.
En outre, j’ai passé ces dernières années à coder avec des langages interprétés et faiblement typés (JavaScript, Python, PHP, Ruby, etc.) et il faut avouer que la compilation avant exécution, ça évite beaucoup de soucis. Et puis, on se dit c’est cool de ne rien typer, ça rend le code plus lisible, etc. Mais, quand on en vient à devoir rajouter partout des vérifications de type, des « cast » explicites pour s’assurer d’avoir les bons types, je crois que ça signifie que les types sont nécessaires en programmation.
D’ailleurs, les quelques langages cités plus haut évoluent tous vers des possibilités plus poussée de typage (PHP 7 et 8, JavaScript avec TypeScript, Python > 3.5, etc.)
On a ainsi le meilleur des deux mondes :
- une exécution quasi instantanée du code,
- une vérification de l’intégralité du code et pas seulement celui qui est exécuté.
C’est un aspect évident pour tous les développeurs, C/C++, Java, C# ou autres, mais qu’il est bon de rappeler.
Une gestion de la mémoire « basique », mais sans ramasse miette
C’est un aspect que je n’ai pas encore creusé, mais V propose une gestion de la mémoire qui me parait assez « basique ».
Par défaut, les variables de type scalaires et les structures sont allouées sur la pile. Donc, pour ces variables le compilateur n’a rien à faire, leur mémoire est désallouée à la sortie de leur portée.
Les variables de type tableau ou map
sont allouées sur le tas.
Il est aussi possible de forcer l’allocation sur le tas, cela sans mot clé explicite (comme malloc
en C ou new
en C++), il suffit juste de déclarer sa variable avec un &
devant, signifiant que l’on manipule une référence.
struct Point {
x int
y int
}
// Allocation sur le tas
p := &Point{10, 10}
// Comme en C++, les références ont la même syntaxe pour l’accès aux attributs
println(p.x)
Les mécanismes de gestion automatique de la mémoire dans V sont encore balbutiants. Jusqu’à il y a peu, il fallait libérer manuellement toute ressource allouée sur le tas. L’instruction free
étant considérée depuis le début comme non sécurisée (à utiliser seulement via le mot clé unsafe
), on comprend que le créateur de V a toujours eu l’intention de rendre la gestion de la mémoire transparente pour l’utilisateur.
Depuis quelque temps, un mécanisme de libération automatique de la mémoire commence à être mis en place .
Encore sous la forme d’une option à l’heure actuelle (-autofree
), il permet de ne plus avoir à se soucier de la mémoire et devrait être le mode par défaut dès la prochaine version.
Le compilateur utilise une stratégie hybride (appelée autofree
) qui mélange le rajout d’instructions de libération de la mémoire (free
) automatiquement lors des cas « faciles » à repérer et du comptage de références dans des cas plus complexes.
Il est encore trop tôt pour dire avec précision quel est le surcoût de ce comptage de références, dans quel cas il est utilisé et si cela constituera la seule stratégie utilisée.
Ce qu’on peut dire, c’est qu’après plusieurs années, cette technique de gestion automatique de la mémoire n’est pas encore au point et que V intègre par défaut un ramasse-miette écrit en C. Ce choix rajoute une dépendance non négligeable au projet, mais permet aux concepteurs du langage de se concentrer sur d’autres problématiques.
Un formateur de code strict
Tout comme Go ou Rust, V inclut un outil de formatage de code très strict qui rend tout code écrit en V semblable.
C’est vraiment une fonctionnalité que j’apprécie énormément dans un langage : on peut se concentrer sur le fond de l’écriture du code. Tout ce qui touche à la mise en forme est gérée automatiquement et on sait qu’on ne peut pas se tromper.
Puis, il faut bien avouer que ça évite les débats au sein d’une équipe :).
Un autre aspect important des formateurs de code est qu’ils permettent de faire évoluer automatiquement une base de code vers les nouvelles syntaxes du langage. Par exemple, le changement du mot clé go
vers spawn
a été traité automatiquement par v fmt
.
On peut noter quelques particularités :
- seul le style de nommage « snake_case » minuscule est accepté pour les variables et les constantes,
- pour l’instant toute ligne vide est supprimée (cela va changer).
Une bibliothèque standard ambitieuse
Le créateur du langage, Alex Medvednikov, est très ambitieux au sujet des bibliothèques qu’il souhaite proposer par défaut. L’envie est que V puisse être utilisé dans tous les domaines : de la programmation système à l’écriture d’application graphiques en passant par les services web.
Pour cela, V intègre dans sa bibliothèque standard :
- une bibliothèque 2D bas niveau (basée sur Sokol)
- une bibliothèque ui pour faire des interfaces graphiques. Très limitée (et buguée) pour l’instant, mais les ambitions sont d’être pleinement multiplate-forme par défaut, avec notamment une prise en charge d'iOS et Android prévue,
- un serveur web intégré,
- une bibliothèque d’accès aux bases de données SQL intégrant la possibilité de coder ses requêtes dans une sorte de SQL, cela grâce aux sucres syntaxiques mentionnés plus haut.
Pour l’instant, il faut l’avouer, tout est dans un état peu avancé. À croire que certaines des bibliothèques ont été commencées sans forcément être développées assidûment. Nous reviendrons en détail sur les critiques que l’on peut porter à V (car il y en a bien sûr).
Ce que j’apprécie c’est l’intention derrière : fournir une bibliothèque standard répondant à la plupart des besoins tout en étant légère et moderne.
Un peu à l’instar de python, mais je l’espère avec des outils d’interface graphique plus modernes que Tk.
Questions en vrac sur le langage
Qu’apporte V par rapport à Go ?
Ce sont des langages très similaires qui rentrent dans la même catégorie, à savoir des langages modernes, compilés et très facile à prendre en main.
Maintenant, si vous êtes frustré par certains manques dans la syntaxe de Go (notamment la gestion d’erreur) ou que vous souhaitez avoir des binaires plus petits et des performances au plus proche du C, V peut être intéressant.
Bien entendu, étant en période d’intense développement, il est encore proscrit pour un usage professionnel.
De plus, son écosystème est bien moins développé que Go.
On pourrait alors se demander pourquoi avoir fait un énième langage ?
Je ne suis pas dans la tête d’Alex, mais je pense qu’il aimait vraiment Go et voulait créer un langage encore plus minimaliste tout en apportant des idées intéressantes provenant d’autres langages. Puis, peut-être, tout simplement pour en apprendre davantage sur les langages de programmation.
Et personnellement, j’adore le résultat !
Est-ce que V est aussi sécurisé que Rust ?
V est décrit comme étant « safe », mais je ne crois pas que le compilateur aille aussi loin que celui de Rust.
Gestion de la mémoire
Un des point fort de Rust est la notion de « possession » (ownership) d’une donnée allouée sur le tas. En effet, seule une variable à la fois peut posséder une donnée allouée, et quand celle-ci sort de sa portée (scope), elle libère automatiquement la mémoire allouée.
Ce mécanisme très abouti permet de garantir que les ressources allouées seront toujours libérées et qu’il n’y aura de problème d’allocation multiple, ou d’accès hors de la mémoire, même en cas de programmation parallèle.
V me paraît sur ce point, moins précis que Rust et la stratégie d’allocation globale du langage n’est pas clairement définie.
Par exemple, dans la documentation, on peut lire que des tampons de mémoire pré-allouée sont utilisés.
C’est sans doute une optimisation bienvenue, mais qui ne conviendrait peut-être pas à tout le monde.
Autres aspects sécurisants
- Effectue des vérifications lors de l’accès au tableau via index et quitte le programme via un
panic
et un message d’erreur approprié, ce qui évitera de pouvoir accéder à des adresses mémoires hors de la mémoire du programme. - Une abstraction du code multi thread via les « goroutine » et les channels rendant l’implémentation de ce genre de code à la fois simple et sécurisée.
- Les variables immuables par défaut et l’absence d’état global évite aussi certains écueils.
- Afin d’éviter les erreurs dues à la parallélisation (« race condition »), un mécanisme de mutex, intégré à la syntaxe du langage (
rlock
) mais c’est encore expérimental.
Il me semble que le compilateur de Rust propose une analyse bien plus poussée et une sécurité accrue.
N’y a-t-il pas trop de « Buzz » autour du langage ?
Il y a beaucoup d’attention autour du langage.
Avec plus de 34 000 étoiles sur GitHub on peut dire que c’est un projet en vogue !
C’est sans doute beaucoup compte tenu de son niveau de maturité !
Aussi, certains critiquent le fait que V n’est pas à la hauteur de ce qu’il annonce.
Je trouve que c’est en partie vrai.
Un article intéressant liste tous les aspects « non conformes » à ce qui est affiché. L’auteur fait parfois preuve d’un peu de mauvaise foi, mais certaines critiques sont justifiées et constructives. Dommage que l’article ait été aussi mal reçu en interne…
En vrac :
- les fonctions sont annoncées comme « pures » par défaut, mais seulement pour dire que les paramètres sont immuables, ce n’est pas la définition de « pure » en programmation fonctionnelle,
- plusieurs éléments sont mis en avant comme la rapidité de compilation (qui est forcément relative à la complexité du code) et le caractère « safe » du langage,
- il est mentionné que la recharge du code « à chaud » (Hot code reloading) est possible, mais cela reste limité aux fonctions ayant un attribut spécifique. Ce n’est donc pas de la recharge à chaud « générique », comme on peut la trouver dans des langages comme Dart,
- V ui, la bibliothèque graphique mise en avant est tout de même très minimaliste et — pour l’instant — peu avancée,
- dans certains aspects, la documentation ne reflète pas l’état actuel du langage, mais ce à quoi il doit ressembler. Ça manque un peu de rigueur…
J’ai l’impression que le créateur du langage a lancé plein de pistes et a posé une intention et quelques bouts de code par-ci, par-là, mais rien de forcément fini.
Quand on voit qu’il code en même temps : un langage, un éditeur de texte, un client natif pour les plateformes de discussion instantanées, une bibliothèque graphique, un framework web, un ORM, un gestionnaire projet… et souhaite même s’attaquer à un navigateur web ! N’importe qui de sérieux se dit que chacun de ces projets nécessite à minima une personne à plein temps dessus.
Pour contrer ce portrait un peu négatif, ce qui est chouette, c’est de voir l’enthousiasme généré autour du langage et que rapidement beaucoup de personnes se sont mises à contribuer.
Il n’y a qu’à voir la liste des commits pour se rendre compte que V n’est plus développé par une seule personne et ça, c’est rassurant pour l’avenir du langage.
Disons qu’Alex a pris à cœur l’adage du libre « release soon, release often », le tout dans une bonne ambiance de « bazar" ». La rigueur pourra venir après :).
Personnellement, j’ai découvert plusieurs bugs dans le langage et ai pu contribuer facilement à leur correction. Soit en proposant du code quand cela me paraissait facile (j’ai, par exemple, réécrit la fonction split
des string
) ou en fournissant du code de test pour aider à la correction de bogue. Dans les deux cas, je me suis senti très bien accueilli et les contributions furent faciles.
Cette discussion reddit à propos des critiques sur V est intéressante.
Conclusion
V est un petit langage très sympathique. Extrêmement proche de Go, il s’en distingue néanmoins par des emprunts très bien choisis à d’autres langages (comme Rust) et d’autres paradigmes (notamment la programmation fonctionnelle).
Le fait qu’il ne nécessite pas de « runtime », ni de ramasse-miette (bon, c’est moins vrai aujourd’hui), le rendent sans doute plus intéressant quand les performances ou la taille des binaires est un enjeu.
Le tout fait un langage très moderne tout en étant incroyablement facile à apprendre et utiliser au quotidien.
Même s’il est encore jeune et avec un écosystème peu mature, il est rapidement devenu un langage que j’affectionne particulièrement. Il n’est bien entendu pas encore mature pour du code utilisé en production, mais vaut vraiment le détour.
De plus, V est un langage accessible (hackable) pour celui qui veut apprendre comment fonctionne un compilateur et expérimenter dans ce domaine.
Aller plus loin
- Site officiel du langage (104 clics)
- Github du langage (38 clics)
- Documentation officielle (28 clics)
- Guide complet (44 clics)
- Faire joujou avec le langage dans son navigateur (35 clics)
# variable immuable ?
Posté par Tit . Évalué à 8.
une variable ça varie tandis qu'immuable c'est pas censé bouger. Une variable immuable, c'est un peu paradoxal ;-)
je pense que je ne comprend pas bien le concept d'immuable dans ce contexte. par exemple dans la boucle for, on peut avoir i++, donc i varie, ça ne me semble pas immuable.
[^] # Re: variable immuable ?
Posté par Stéphane Bortzmeyer (site web personnel, Mastodon) . Évalué à 8.
En général, en programmation, le terme de variable immuable (qui peut effectivement faire rire) est destiné aux cas où la valeur n'est pas connue statiquement mais, une fois affectée, ne peut plus changer. Ce n'est effectivement pas le cas en Go (je n'ai pas essayé V).
[^] # Re: variable immuable ?
Posté par Andréas Livet . Évalué à 1.
Oui une variable immuable c'est pas très logique, mais c'est pour les différenciées des constantes comme ça a été dit.
Pour le cas du
for
, c'est un cas particulier où le compilateur ne nécessite pas le mot clémut
(voir le guide).[^] # Re: variable immuable ?
Posté par Thomas Douillard . Évalué à 8.
C’est le même nom qu’en math, pour les paramètres des fonctions par exemple. Pourtant les variables en maths sont immuables, si tu as le même nom de variable dans le même scope, en deux endroits différents leur valeur sera toujours égale.
[^] # Re: variable immuable ?
Posté par ǝpɐןƃu∀ nǝıɥʇʇɐW-ǝɹɹǝıԀ (site web personnel) . Évalué à 6.
Par exemple en python les int sont immuables.
Si on fait :
On s'aperçoit que la première variable a changé d'identité avec la réaffectation, alors que b…
Il faut bien avouer que les raisons sous-jacentes ne me semblent pas très évidentes. Peut-être un rapport avec le fait qu'il serait bizarre que tous les contenus d'un conteneur immuable puissent être changés.
« IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace
[^] # Re: variable immuable ?
Posté par reno . Évalué à 4.
Interessant l'utilisation de variable immutable sans "tricher" et autoriser le masquage de nom comme le fait Rust.
D'un coté c'est + clair, un nom == une valeur d'un autre je soupçonne que cela induit a creer beaucoup de nom et qu'on finit par faire toto := …; toto2 := … ;
[^] # Re: variable immuable ?
Posté par Colin Pitrat (site web personnel) . Évalué à 2.
Ça encourage peut-être à avoir des fonctions plus courtes …
[^] # Re: variable immuable ?
Posté par Aldoo . Évalué à 4.
Ce qui me choque plus, moi, c'est qu'à l'hôpital, on trouve intelligent de surveiller les constantes des patients…
[^] # Re: variable immuable ?
Posté par kalimba . Évalué à 7.
Ben la température c'est une constante physiologique, parce que le corps essaye de la garder toujours a la même valeur malgré les variations de l'environnement. Si elle s’écarte de sa valeur habituelle, c'est le signe qu'il y a un problème. De meme, si dans ton programme t'a déclaré une constante mais que tu t’aperçois qu'elle change de valeur, c'est signe qu'il y a un problème
# Merci pour cette description détaillée !
Posté par chimrod (site web personnel) . Évalué à 5.
Merci pour cette dépêche et cette découverte du langage, c’est vrai que les exemples sont parlants et donnent une bonne idée de ce que l’on peut faire avec !
Si je comprends, le langage ne contient pas de Null et passe par un type
['a] Optionnal
, est-ce que cela peut être représenté au niveau du pattern matching ? Leurs exemples n’indiquent pas comment décomposer le type en question.Le langage m’a l’air intéressant, (j’aime le ratio entre simplicité du code et garantie des types) et leur librairie standard semble bien fournie.
Je vais lui donner sa chance :)
[^] # Re: Merci pour cette description détaillée !
Posté par Andréas Livet . Évalué à 3. Dernière modification le 16 septembre 2024 à 20:22.
Oui c'est l'idée, après je ne suis pas allé dans le détail, mais comme V permet de travailler avec des bibliothèques C sans couche d'interopérabilité, la notion de
nil
est présente dans le langage, mais a utilisé avec précaution.Il est aussi possible de déclarer des champs de structure avec comme valeur par défaut 0 soit un pointeur
null
…J'ai un peu du mal à comprendre pourquoi un des cas doit être marqué
unsafe
et l'autre non.Personnellement, je n'aime vraiment pas cette notion de
unsafe
dans V, tout comme je ne l'apprécie pas dans Rust. Je préfère de loin l'approche de Zig sur ce point.Comme je le dis dans la dépêche, V cherche à faire un grand écart entre facilité d'utilisation, typage fort, rapidité et lien direct avec le C. Forcément, certains compromis doivent être fait, la notion de
unsafe
en est un.Oui, c'est peut-être mieux détaillé dans cette partie du guide (voir l'exemple à la fin).
Donc pas de pattern matching pour gérer les
Optional
mais soit viaor
, soit via unif/else
comme décrit dans cette doc.Exemple :
# curl|sh
Posté par devnewton 🍺 (site web personnel) . Évalué à 10.
Chaque fois qu'un projet fait ça, Dieu étrangle un chaton avec un fil de souris.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: curl|sh
Posté par Andréas Livet . Évalué à 4.
J'ai vérifié et en fait je me suis trompé ou c'est que ça a changé depuis que j'ai commencé la rédaction de la dépêche (il y a plus de 2 ans !).
En fait, une version transpilée du compilateur V est compilée avec gcc par défaut (voir le Makefile).
Par contre, tcc est bien utilisé pour compiler les binaire une fois que le compilateur V à transformé le code V en C.
Et il semble bien téléchargé par
make
(si on en croit la doc), je ne trouve juste pas où se fait ce téléchargement.En quoi est-ce si mal ?
[^] # Re: curl|sh
Posté par Christophe "CHiPs" PETIT (site web personnel) . Évalué à 10.
Que si la machine ou tu veux compiler V n'a pas d'accès à Internet, tu ne pourras pas le faire, en plus d'implications au niveau sécurité si tu récupères un TCC vérolé…
Et certainement un tas d'autres raisons !
[^] # Re: curl|sh
Posté par Andréas Livet . Évalué à 1.
Le fait d'installer V nécessite une connexion internet et il a sa propre version de tcc.
Mais même s'il pointait sur une release de TCC officielle par exemple, je ne vois pas en quoi ça serait plus dangereux.
C'est une question de confiance, si tu fais confiance à ce projet pour télécharger du code sur son dépôt, alors tu as aussi confiance au code dont il dépend.
A noté que V ne nécessite pas de droits super utilisateur pour s'installer.
C'est à la personne qui installe de prendre la responsabilité de réaliser le lien symbolique.
[^] # Re: curl|sh
Posté par mrlem (site web personnel) . Évalué à 9.
Ben vouloir pouvoir compiler un truc petit programme sans accès internet, c'est pas forcément un besoin atypique (rien que quand on est en déplacement).
Par ailleurs, ce mode de fonctionnement n'implique pas juste de faire confiance à l'auteur au binaire hébergé au moment où tu installes le soft, mais de considérer que ce binaire ne sera jamais corrompu, volontairement ou pas, et qu'il sera toujours disponible.
Par exemple, s'il était corrompu (genre fichier incorrect), tu ne peux plus bosser tant que l'auteur ne corrige pas le problème
Autre exemple, si l'hébergement s'arrête (facture non-payée, compte fermé par l'hébergeur pour n'importe quelle raison), tu ne peux plus bosser non plus.
De même, si le fichier hébergé se fait remplacer par un programme malicieux, ça veut dire que tu exécuteras malgré toi un binaire arbitraire sur ta machine sans forcément t'en rendre compte. Est-ce qu'il y a un check d'intégrité de ce programme à chaque exécution ?
Voilà des exemples de problèmes que ça pose, si j'ai bien compris le contexte :)
[^] # Re: curl|sh
Posté par Dring . Évalué à 2.
J'arrive un peu tard, mais je me demande si vous parlez de la même chose.
L'auteur de la dépêche dit que TCC est téléchargé pendant l'exécution du make. Mais c'est bien le make qu'on lance une fois pour compiler le transpileur V. C'est pas à chaque fois qu'on compile un programme écrit en V.
[^] # Re: curl|sh
Posté par Gil Cot ✔ (site web personnel, Mastodon) . Évalué à 2.
Si, si, il s’agit bien du téléchargement fait par le Make sans qu’on puisse garantir quoi que ce soit.
“It is seldom that liberty of any kind is lost all at once.” ― David Hume
[^] # Re: curl|sh
Posté par arnaudus . Évalué à 6.
Il y a encore plus rapide, quand tu fais "make" ça télécharge le binaire du logiciel! Compilation super-rapide si tu as la fibre.
# Go <-> V
Posté par wilk . Évalué à 4.
D'après cette excellente description il serait possible de générer du code Go à partir du V et inversement et plus facilement que du C, est-ce que ça a été tenté ?
[^] # Re: Go <-> V
Posté par Andréas Livet . Évalué à 4.
Oui c'est possible et ça a été tenté, il semble exister un backend Go (en tout cas il y a un canal discord sur le discord officiel), mais je ne crois pas que ce soit allé bien loin.
De manière générale, je trouve que V est pour l'instant tellement lié au C (certains attributs sont directement liés à C) que je ne pense pas qu'un autre backend viable verra le jour d'ici peu.
Ou alors, il faudra revoir certains éléments du langage.
# Variable magiques ?
Posté par xryl669 . Évalué à 5.
C'est l'
it
qui sort du bois dans le map, qui rencontre una
qui se croit supérieur aub
lorsqu'il sort, mais en cas de problème, ilerr
sans exception.Magnifique… Je suppose qu'écrire 'a,' ou 'it,' pour pouvoir choisir le nom de la variable dans une fonction lambda eu été trop de dépense d'énergie, résultat, il y a des variables magiques qui sortent de nulle part, qui empêche (du moins, je l'espère) l'utilisation de ces noms partout ailleurs (c'est clair que
it
,a
,err
sont jamais utilisées dans du code standard).Bref, c'est nul comme choix.
[^] # Re: Variable magiques ?
Posté par Andréas Livet . Évalué à 3. Dernière modification le 05 septembre 2023 à 12:29.
C'est sûr, c'est un choix contestable. Perso, ça m'a choqué au début, mais finalement j'aime bien, c'est très compact et comme c'est des variables qu'on nomme souvent de la même manière, ça force une consistance dans le code.
Non on peut les utiliser ailleurs.
Ce qui me fait dire que la redéfinition de variable est finalement possible dans ce cas là…
[^] # Re: Variable magiques ?
Posté par xryl669 . Évalué à 3.
Ah, c'est encore pire que ce que je pensais.
Dans cet exemple de code, comment accèdes-tu à la variable
err
"globale" dans le scope du else ?Si tu ne peux pas, dans ce cas, impossible d'utiliser une variable
err
oua
oub
nulle part, car le jour où la fonctiongen_ten_or_none
change de signature (suite à une maintenance de code par exemple) pour retourner une erreur, une variableerr
vient "shadow aliaser" tes propres variables sans aucun message d'alerte.Autant dans ce cas, définir
err
etit
eta
etb
comme mot clé du langage. C'est assez déroutant en fait.De plus
map
prend un "fonction scope" comme argument et pas un "parameter list" du coup, ce qui fait un peu mélanges d'effluves, car les autres fonctions attendent toutes un "parameter list".Comment faire pour avoir un code plus long dans un map ? (Genre 2 lignes, ou assigner une variable externe lors de l'itération?).
[^] # Re: Variable magiques ?
Posté par Andréas Livet . Évalué à 1.
Il est possible de passer aussi une fonction callback à map.
Après sinon je suis d'accord, ces "compile magic" sont déroutant et ça donne un côté très bidouille au langage, mais dans l'histoire des langages, c'est pas forcément les langages les mieux défini (ou les plus pures) qui ont eu les faveurs des programmeurs.
Dans le cas de V, les concurrents sont bien en place, je doute qu'il arrive un jour à devenir mainstream.
Quoiqu'il en soit, c'est une belle expérimentation, j'aime notamment l'idée de vsh. Poussé un peu plus loin, ça peut donner quelque chose de très séduisant.
Perso, je verrai bien une sorte de zx mais codé en V. J'avais commencé un truc, mais sans aller bien loin…
[^] # Re: Variable magiques ?
Posté par barmic 🦦 . Évalué à 4. Dernière modification le 06 septembre 2023 à 08:09.
Pour
err
je demande à voir, mais pourit
ça existe en kotlin, en groovy, en perl (bon$_
va bien plus loin) et probablement dans d'autres. C'est plutôt agréable à utiliser en pratique. Ça peut se rapprocher desthis
etself
de la majorité des langages objet.https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Variable magiques ?
Posté par Tit . Évalué à 3.
Err ça existe aussi en VB
[^] # Re: Variable magiques ?
Posté par ß ß . Évalué à 6.
Je ne suis pas sûr qu'on puisse comparer V et Perl pour se faire un avis sur la pertinence ou pas des variables magiques.
Le contexte n'est pas vraiment le même.
Perl a été à l'origine conçu surtout pour être un remplaçant sous stéroïdes de sed+awk. Bref, c'est parfait pour faire des oneliners dans le terminal, mais pas forcément pour faire des longs scripts.
En ce sens, les variables magiques telles que $_ (mais aussi $", $!, etc.), ont du sens. Le but étant de taper le moins de caractères possibles histoire de gagner de la place (les écrans n'étaient pas larges) et du temps (en cli, on est plus souvent en RO qu'en RW).
Par ailleurs, les noms de variables sont quand même assez exotiques. Il y a plus de chances de spontanément nommer une variable
a
,b
,err
ouit
que $_ ou $!. Ceci dit, on pourrait parler des noms longs. Par exemple $_ peut aussi s'écrire $ARG, $! peut s'écrire$ERRNO
ou$OS_ERROR
. Ce qui est d'ailleurs recommandé quand on écrit un script.Ça peut également être source de confusion, c'est vrai. Mais globalement si on n'utilise pas de variables en majuscules ça passe.
Tout ça pour dire que même si en Perl également, le principe des variables magiques peut être critiqué (et il l'est depuis des dizaines d'années), je trouve quand même ça moins gênant que pour V.
Mais c'est un jugement tout à fait subjectif.
[^] # Re: Variable magiques ?
Posté par barmic 🦦 . Évalué à 3.
Je pourrais entendre ce que tu dis si 15 ans plus tard en ayant du recul sur le langage et en s'autorisant à tout casser ils n'auraient pas accouchés de Raku qui a lui aussi des variables magiques de ce genre : The $ variable.
Mon argument n'est pas de dire est-ce que c'est bien ou mal, mais que ce n'est pas objectivement et fondamentalement mauvais. Il n'est pas du tout le seul langage à le faire et ces langages vivent très bien. C'est un choix de fonctionnalité du langage comme tant d'autres.
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
# Taptempo
Posté par pamputt . Évalué à 10.
La seule question qui importe est « existe-t-il une version de TapTempo écrite en V » ?
Il semble que non.
[^] # Re: Taptempo
Posté par Ysabeau 🧶 (site web personnel, Mastodon) . Évalué à 7.
Yapluka !
« Tak ne veut pas quʼon pense à lui, il veut quʼon pense », Terry Pratchett, Déraillé.
[^] # Re: Taptempo
Posté par Andréas Livet . Évalué à 4. Dernière modification le 07 septembre 2023 à 21:22.
Et bah voilà !
J'ai codé ça rapidement, j'utilise une petite bidouille avec le raw mode du module readline, mais ça fonctionne.
J'essaierai de voir si je peux pas faire plus simple au niveau de la récupération des inputs et du mode raw.
Pas encore pris le temps d'en faire un journal, mais ça va venir.
# À propos de la programmation orientée objet
Posté par SpaceFox (site web personnel, Mastodon) . Évalué à 10.
Ce qui est décrit ici n’est principalement pas de la programmation orientée objet :
Ceci n’est pas une attaque contre l’auteur, car comme il le dit lui-même, c’est ainsi que la POO est présentée dans beaucoup trop de cas.
Une définition plus exacte de la POO serait :
Je vous renvoie à ce billet pour plus de détails quant à ce que ça implique, et si comme moi il y a quelques années ou comme l’auteur de la présente dépêche vous avez été déçus par ce qu’on vous a appris, vous pourriez être surpris.
La connaissance libre : https://zestedesavoir.com
[^] # Re: À propos de la programmation orientée objet
Posté par Andréas Livet . Évalué à 4.
Oui, mais c'est aussi ainsi qu'elle est mise en pratique dans certains langages comme tu le dis bien dans ton billet.
Franchement, j'ai du défaire tout l'enseignement que j'ai eu à ce sujet, ça été douloureux, car j'y ai cru à toutes ces choses !
Je crois que le pire c'est les design pattern, j'ai essayé de m'y mettre ! J'y ai mis du cœur, mais dans bien des cas, je trouve que ça complexifie le code…
[^] # Re: À propos de la programmation orientée objet
Posté par Toufou (site web personnel) . Évalué à -6.
Cool !
Ah beh non, pas cool : le mec d'entrée confond encapsulation et masquage…. => /dev/null
[^] # Re: À propos de la programmation orientée objet
Posté par SpaceFox (site web personnel, Mastodon) . Évalué à 10.
« le mec » c’est moi. Merci pour ce retour pertinent et constructif (non).
Pour répondre quand même à ta remarque : le fait qu’il y ait, ou non, une différence forte entre « encapsulation » et « masquage » n’est pas un consensus du tout. Par exemple, si Wikipedia FR semble faire une différence, Wikipedia EN mentionne le fait qu’en pratique les termes sont souvent interchangeables et que tout le monde n’est pas d’accord pour faire une distinction et ce dans les deux articles. Dans les faits, quand on parle d’encapsulation dans le cadre de la POO, c’est pratiquement toujours avec masquage, d’où ce choix dans mon article – notamment parce qu’une information non masquée a toujours un risque d’être utilisée (au moins lue) hors de son contexte d’encapsulation.
Maintenant si tu veux pinailler sur des détails, je te conseille de le faire de façon constructive et ça a une chance d’être effectivement pris en compte (le message que je pointe l’a été) plutôt que de prétendre que tout est bon pour la poubelle parce qu’un détail ne t’a pas plu. Ce conseil est valable à plus grande échelle que celle de ce billet.
La connaissance libre : https://zestedesavoir.com
[^] # Re: À propos de la programmation orientée objet
Posté par Toufou (site web personnel) . Évalué à -5.
Ok, je vais détailler ça sera peut-être utile et moins frustrant.
Mais bon, Tu fais un billet d'humeur (non constructif) sur la POO, son usage et son enseignement pourris selon toi, je fais un post d'humeur sur ton billet d'humeur pourri selon moi => où est le problème ?
Les deux phrases m'ayant déclenché cette réaction :
et
plus le rapide survol des titres :
Donc ça balance sévère et paf, d'entrée une confusion entre deux concepts, l'un fondamental en POO (l'encapsulation), l'autre accessoire (le masquage), je trouve que ça part assez bien pour qu'il ne soit pas nécessaire de continuer et faire savoir que ça vaut pas plus qu'une discussion de comptoir avec Raymond au PMU.
Ça c'est pour expliquer la forme succincte de ma critique dont le fond a semble t'il parfaitement été compris : j'ai pas été mauvais sur le coup en termes de com.
Sur le fond :
Le masquage est un autre concept comme la notion de classe ou de propriété.
Et quand on parle de POO on parle pratiquement toujours dans un contexte de langage à classe (C++, Java, C#…. ) : ça rend la classe implicite ou obligatoire quand on parle POO ? Fuck les prototypes ?
Donc ok, c'est proche et ça va souvent ensemble mais ce n'est ni implicite, ni obligatoire il me semble.
Et alors ? En pratique c'est presque impossible de l'empêcher donc bon…
Le masquage c'est comme la notion de classe ou d'encapsulation (bundling, que j'utiliserai comme terme ensuite, pour éviter la confusion) : un concept.
Après tu l'implémentes (outils) comme tu veux :
- mot clef et mécanisme du langage (ex : private)
- convention de nommage et savoir vivre des codeurs
- menace de mort de l'ordinateur (comme certains registres du TI99 ;) )
Tout pareil pour le bundling :
- mot clefs et mécanismes du langage (ex : class)
- convention de nommage / structures particulières
- il y a surement d'autres méthodes que je ne connais pas
Donc soit tu parles du concept (on peut cacher des choses) soit tu parles des outils (on le rend private), soit tu parles des pratiques (c'est bien/c'est mal).
Là tu nous parles de POO et d'encapsulation au sens concept car c'est dans une définition.
Je ne vois pas du tout ce que la morale ou les outils viendraient faire la dedans.
Surtout, la POO n'interdit pas d'aller utiliser les propriétés et autres comportements : elle se base justement la dessus (via les messages).
Ta définition en deux phrases est d'ailleurs incomplète : il manque les messages, mais pour ça il fallait mieux lire entre les lignes WP que tu as résumées, car il y a une proposition clef : "ils savent interagir entre eux".
Et il fallait la comprendre : ce n'est pas leur comportement qui fait qu'ils savent interagir entre eux, c'est le mécanisme de messages qu'ils utilisent, généralement via l'appel de méthode (une implémentation possible).
Donc non ce n'est pas tout, merci Captain pas si Obvious que ça.
C'est peut-être aussi un détail mais c'est souvent là où se cache le diable : le fait que les objets utilisent un mécanisme de communication pour interagir entre eux me semble légèrement plus nécessaire que le masquage dans une approche POO…
Il se peut, ma mémoire étant ce qu'elle est et ma littérature de référence sur le sujet étant perdue dans les limbes, tu as peut-être raison. En tous cas, même WP FR semble te donner raison.
Et je me demande bien alors comment on appelle le bundling en français…. Pas des structures : il n'y a pas de comportement dedans.
Des paquetages ?
J'instancie des paquetages en python et en perl ? Vraiment ?
Pour moi intégrer le masquage dans l'encapsulation n'est ni plus ni moins qu'un abus de langage par anglicisme (eux ont les 3 mots : encapsulation, bundling, information hiding). Dommage qu'il se répande dans la littérature.
Quitte à jouer sur les mots et les consensus, est-ce qu'on est toujours dans de la POO quand l'instance d'une classe n'a ni toutes les méthodes ni tous les attributs de sa classe ? On encapsule, on a bien un objet issu d'une 'classe' et pourtant y a comme un truc qui pue….
Je relève les copies dans 3 mois, bon courage pour aller chercher un consensus dans la littérature.
Un concept central n'est pas un détail dans un papier dont c'est le sujet. J'aurais lu ça dans Marie Claire, je n'aurais probablement relevé.
Vois le bon côté des choses, j'ai lu un peu le reste pour te répondre et d'ailleurs j'ai deux questions :
- le coup des List qui intègrent des méthodes de modification => implémenter List pour faire un truc immuable ça me semble complètement con (sauf contexte étrange, genre hack moisi pour se sortir d'un mauvais pas en loucedé), tu as un exemple de classe dans la StdLib java qui fait ça ? Avec 15 ans d'XP tu as surement ça sous le coude.
- tu parles de Kotlin comme 'Langage a JVM' : j'ai cru comprendre que Kotlin se compilait / transpilait pour différentes archi (JVM, natif, JS notamment). Tes mesures ne concernent donc que quand on le fait tourner l'exe sous JVM, mais quid pour les autres supports ? Ou j'ai pas bien capté ce qu’était Kotlin ?
Pour le reste, de mon point de vue ton billet d'humeur me fait penser que
- tu n'a pas bien compris certains concepts de base (encapsulation/bundling, masquage, message)
- tu mélanges concepts (POO), bonnes pratiques (LSP, SOLID, traits) et outils de la POO intégrés au langage (la notion de private, les Enums qui sont des classes de Java)
- tu aurais pu parler des friends ou d'héritage en diamant : la aussi y a du lourd dans la série bonnes pratiques :D
- j'ai l'impression que tu galères parce que tu n'as pas bien compris, gênant après 15 ans de Java… Mais bon JBoss-like, Spring, Hibernate et autres machineries du type ne sont pas Java …. Si ça fait 15 ans que tu fais du légo avec ça, ça peut se comprendre et je compatis pour la frustration…
- tu repompes joyeux les phrases vides de sens de WP (ou sa source), exemple : le laïus sur la conception qui est primordiale en POO => parce que la conception c'est secondaire dans les autres paradigmes ?
- tu balances des dogmes (LSP, SOLID) qui ont les mêmes problèmes que ceux que tu critiques dans l'enseignement de la POO => ils sont aussi potentiellement des freins à la qualité et à la robustesse (notions bien subjectives) de ton code.
- après 15 ans de métier, je trouve étonnant que tu parles de code sans parler de contexte, pourtant le contexte, quand il change, c'est ce qui fait que tu vas tout péter, bonnes pratiques ou non, POO ou spaghetti style. C'est surtout ce qui fait qu'un choix est pourri sur papier, mais qu'en fait c'est pas si con IRL. Qu'il est malin aujourd'hui et complètement débile demain.
Donc, après avoir lu vaguement, ça confirme ma première évaluation : un truc où en quelques lignes je détecte déjà des problèmes sur le cœur du sujet alors que je ne suis pas un cador du domaine => /dev/null. Le reste ne vaudra très probablement pas mieux. C'est pour ça que d'habitude je ne lis pas les billets d'humeurs : les avis de Raymond sur les ZFE et le changement climatique ne valent pas mieux que les miens. J'ai déjà une analyse moisie du monde : la mienne. Pourquoi aller en chercher ailleurs ? Là je me suis fait avoir dans un moment de faiblesse :D
Mais bon, ça m'a permis de réviser mes classiques en m'amusant, en cela, ça n'a pas été totalement inutile donc merci.
Allez pour décrisper, j'avais lu un truc qui m'avait fait marrer (sans doute ici) : le code c'est comme le pet, on ne supporte que le sien :D
[^] # Re: À propos de la programmation orientée objet
Posté par barmic 🦦 . Évalué à 8.
C'est une réflexion de mauvais développeur ça (on en reconnaît certains à leur pédanterie, leur positionnement sur la courbe Dunning-Kruger ne leur permet plus d'apprendre ou leur manque de confiance les pousse à rabaisser, mais ça n'est pas une fatalité).
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: À propos de la programmation orientée objet
Posté par SpaceFox (site web personnel, Mastodon) . Évalué à 9. Dernière modification le 07 septembre 2023 à 00:48.
Wow. Ce pavé est incroyable de mépris et de condescendance. J'ose espérer que tu en étais conscient en l'écrivant et que tu n'es pas persuadé avoir écrit un message constructif, parce que ça n'est pas le cas. Une astuce pour faire la différence quand tu rédiges ce genre de réponse à un texte : quand tu contredis le message, c'est une bonne chose (surtout si tu le fais avec des arguments et des sources). Quand tu attaques l'auteur voire que tu l' insultes (ton message souvent très proche de la limite, et parfois du mauvais côté), tu es juste inutile et tu perds ton temps. Pareil quand tu hasardes des hypothèses sur mon parcours ou sur ce que je développe, ou sur les langages que tu ne connais pas (comme Kotlin).
Oh, à propos de Kotlin, je te conseille de regarder la doc le leur implémentation standard de
List
: elle est immuable (source : https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/). Le langage s'est créé pour avoir une version moderne et pragmatique de Java (à l'époque où ce dernier stagnait), la notion de "liste immuable par défaut" était assez importante pour la mettre au cœur du langage. Et à l'usage tu n'as pas tant besoin que ça des listes modifiables.La connaissance libre : https://zestedesavoir.com
[^] # Re: À propos de la programmation orientée objet
Posté par Thomas Douillard . Évalué à 6. Dernière modification le 07 septembre 2023 à 10:29.
Ne te plains pas il t'a quand même jugé digne d'avoir une réponse de lui ! To pourrais peut être tirer quelque chose de son intervention pleine de sagesse, manifestement ça n'a pas l'air d'être le cas de toit le monde.
[^] # Re: À propos de la programmation orientée objet
Posté par SpaceFox (site web personnel, Mastodon) . Évalué à 6.
Le pire c’est que oui, il y a sans doute des trucs intéressants à tirer de tout ça, ne serait-ce qu’une précision en note de bas de page sur la notion d’encapsulation et comment elle s’articule avec celle du masquage.
Mais j’avoue que j’ai un peu la flemme à retrouver les passages pertinents entre les passages méprisants et/ou injurieux pour ensuite essayer de retrouver des sources (non fournies) qui s’y rapportent pour ensuite voir ce que j’aurais à mettre à jour dans mon article. Et c’est bien dommage.
La connaissance libre : https://zestedesavoir.com
[^] # Re: À propos de la programmation orientée objet
Posté par Toufou (site web personnel) . Évalué à -4.
Le dernier pour la route, après j'arrête, c'est en effet totalement inutile ce genre de flamewar. Tu ne comprends pas que je critique ton billet, ta méthode d'argumentation qui porte les biais que tu critiques et non toi en tant qu'humain.
un exemple sur ta méthode vaut mieux qu'un long discours alors je te cite :
Donc, dans le paragraphe au titre respectueux de "Des langages qui font n’importe quoi", on a
suivi de
suivi de
La note n°2 dit :
Ce qui m'amène à te poser la question suivante dans mon post précédent :
et tu me réponds dans le post précédent :
Bon, soit tu ne comprend pas ma question (peu probable, enfin j'espère), soit tu ne prends pas la peine de te documenter pour me répondre (très gentil, merci), soit tu as dit de la merde dans le billet d'origine, tu t'en es aperçu et ouille ça pique.
Mais tu en rajoutes une couche surréalistement péremptoire :
Source : "c'est connu Khalessi"
non franchement, tout ton billet est sur le même moule, tu craches ta frustration, ta confusion entre les choses … => /dev/null
Et là tu décales le problème sur une attaque ad hominem, crois moi il n'y en a pas vraiment. Je critique principalement le fait d'avoir produit un contenu de merde parce que tu ne cherches même pas avant publication à vérifier si tu dis de la merde ou non, le principe même du billet d'humeur.
C'est ce qui fait la différence entre une doc et Raymond au PMU : la première bénéficie d'un travail de relecture.
La seule attaque 'personnelle' que j'assume c'est que tu craches sur les autres 'qui font n'importe quoi et ça c'est cool mais que bien sur la réciprocité est agressive…
import java.lang.reflect;
# Joie
Posté par Psychofox (Mastodon) . Évalué à 8. Dernière modification le 05 septembre 2023 à 14:20.
Je n'utilises pas et n'ait pas besoin de Volt, et çapusaipalibre mais ceci me réjouit:
et
[^] # Re: Joie
Posté par Andréas Livet . Évalué à 4.
Oui c'est cette approche minimaliste qui m'a plu dans V.
Après, la bibliothèque d'interface graphique n'est vraiment pas du tout au point.
J'ai essayé de faire un petit logiciel d'édition de sprite avec il y a quelques année et je m'étais bien cassé les dents.
Y a de bonnes idées, mais pas assez de réflexion sur la notion d'état de la vue, ce qui aujourd'hui est dommage quand on voit les apports de la programmation réactive.
Récemment j'ai découvert une mini lib Javascript qui permet de faire un peu la même chose que du React mais tellement plus simplement. J'adorerai voir ce genre de concept porté dans d'autres langages comme V par exemple.
# if sans parenthèses
Posté par Toufou (site web personnel) . Évalué à 5.
Je dois avoir l'esprit tordu (bon, ok c'est une certitude) mais je trouve que ce passage va être nominé dans catégorie 'le détail mis en avant qui ne sert à rien'…
Les parenthèses sont souvent obligatoires car séparant la condition du code à exécuter. Dans le cas de V, ça semble être l'accolade délimitant le code qui est obligatoire, rendant inutiles les parenthèses pour la condition.
Parce que je ne vois pas trop la différence entre
et
Du coup, à par satisfaire les accoladophiles parenthèsophobes, je ne vois pas trop la killer feature ….
[^] # Re: if sans parenthèses
Posté par Andréas Livet . Évalué à 5.
Ce n'est pas une killer feature, juste un choix de syntaxe issue de Go.
Disons que c'est plus cohérent, car l'exemple sans accolade ne fonctionne que si on a qu'une seule instruction.
[^] # Re: if sans parenthèses
Posté par Toufou (site web personnel) . Évalué à 2.
Bah ça les dérange pas pour le main facultatif hein…
M'enfin, les goûts et les couleurs toussa….
[^] # Re: if sans parenthèses
Posté par srb (site web personnel) . Évalué à 3.
Le choix de forcer l'usage des accolades dans Rust est d'éviter des bogues dus à l'ajout d'une nouvelle instruction à la suite de la première, sans se rendre compte que cette seconde instruction sera exécutée inconditionnellement car elle n'est pas entourée d'accolades (cf. une discussion sur rust-lang). Peut-être que c'est aussi la raison qui a guidé ce choix en Go ?
Avec l'outil de formatage automatique, l'erreur va être évidente au programmeur car la seconde instruction sera réindentée et donc ne semblera plus être dans un bloc qui n'existe pas. Dans ce cas, l'argument est moins convaincant.
[^] # Re: if sans parenthèses
Posté par steph1978 . Évalué à 10.
L'absence d'accolade autour d'une clause
then
- car d'une seule ligne - est la source de nombreux bugs enC
. Imposer les accolades est donc une bonne chose IMHO.Si tu imposes les accolades, les parenthèses autour de la condition ne sont donc plus nécessaire puisque le parsing n'est plus ambiguë : la condition est ce qu'il y a entre le
if
et le prochain{
.# Sather
Posté par Sytoka Modon (site web personnel) . Évalué à 3. Dernière modification le 05 septembre 2023 à 16:04.
L'auteur devrait regarder du côté de Sather https://fr.wikipedia.org/wiki/Sather. Il y avait dans ce langage tout ce qui était amusant avec des API chouettes. Héritage de structure et inclusion de code, interface… Une gestion contravariante (donc sure) des paramètres et surtout des iterators (en pratique comme les coroutines) avec la notion de yield et de paramètres once (évalué juste la 1er fois et non les suivantes). Je n'ai jamais revu un autre langage avec des itérateurs aussi esthétiques et pratiques.
Autre chose amusante en Sather, on pouvait ajouter un noeud dans l'arbre des classes après coup. Ainsi une classe système pouvait dériver d'une classe que l'utilisateur définie et que le concepteur n'avait pas pensé. Rare sont les langages à le permettre or toutes les arbres de classe sont imparfaits et nécessitent un jour de définir une classe virtuelle maître à différent endroit pour son utilisation spécifique.
[^] # Re: Sather
Posté par reno . Évalué à 2.
Sather avait un GC alors que là on parle d'un C-like.
[^] # Re: Sather
Posté par Andréas Livet . Évalué à 2.
Non V a utilise aussi un ramasse miette. Il cherche aussi à développer d'autres méthodes de gestion automatique de la mémoire, mais ce n'est pas un langage où l'on est responsable de la mémoire.
[^] # Re: Sather
Posté par reno . Évalué à 3.
Ah? Dans ce cas je n'en vois pas l'intérêt D est bien + mature..
[^] # Re: Sather
Posté par steph1978 . Évalué à 3.
OMG que c'est laid ! 🤮
Oui je sais, les goûts les couleurs. Mais ce mélange de syntaxe Pascal (
end
) et C (;
), ça me fout la gerbe.Et puis à quoi bon un débat sur les langages de prog si on peut pas parler de la beauté de la syntaxe 😉
[^] # Re: Sather
Posté par Tit . Évalué à 3. Dernière modification le 06 septembre 2023 à 15:34.
Pascal a aussi des ;
[^] # Re: Sather
Posté par Gil Cot ✔ (site web personnel, Mastodon) . Évalué à 2.
Tout à fait, il n'y a pas de mélange de genres. L'exemple
se traduit en (plus verbeux pour ce cas simple)
Bien noter le
;
sauf après :type
,begin
,var
, les commentaires.Et en prime Pascal a le fameux
end.
final…“It is seldom that liberty of any kind is lost all at once.” ― David Hume
[^] # Re: Sather
Posté par Gil Cot ✔ (site web personnel, Mastodon) . Évalué à 2.
J'aurais cru que le marqueur est
end;
(une seule instruction et non deux), mais en regardant d'autres source je comprends juste que;
est requis …sauf- fin de ligne de commentaire introduit par
--
- après les mots clé
is
,then
,else
.Ce dernier point que j'ai d'abord vu comme des exceptions (donc surprenant) fait sens quand on sait qu'une instruction ne peut pas se terminer abruptement dessus…
(exemple en 2.4 du manuel sur l'essentiel…) peut s'étaler comme suit (qui t'a choqué)
ou même se compacter comme suit (je suppose, mais le
is if
est piquant)“It is seldom that liberty of any kind is lost all at once.” ― David Hume
[^] # Re: Sather
Posté par srb (site web personnel) . Évalué à 2.
Pour les curieux qui voudraient voir à quoi ça ressemble:
la page du manuel Sather sur les itérateurs
Le
once
est à la section 3.2.4. Lisez ce qu'il y a avant pour mieux comprendre.Je ne suis pas habitué à ce type de syntaxe donc ça doit jouer sur le fait que je ne trouve pas ça très limpide.
[^] # Re: Sather
Posté par Andréas Livet . Évalué à 2.
Merci pour la découverte (ou peut-être redécouverte je ne sais plus :)) de ce langage.
Souvent, les bonnes idées viennent de langages académiques qui n'ont pas percés (par exemple la notion de channel de Go vient de Limbo il me semble).
[^] # Re: Sather
Posté par Andréas Livet . Évalué à 2.
En lisant un peu plus sur l'historique de Go, ça semble même venir du langage Newsqueak de Rob Pike
# go good enough
Posté par devnewton 🍺 (site web personnel) . Évalué à 5.
J'ai du mal à voir un vrai avantage par rapport à Go.
Même en tant que Go light, il y a déjà Tinygo…
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: go good enough
Posté par abriotde (site web personnel, Mastodon) . Évalué à 4.
Oui et non.
L'avantage serait potentiellement d'avoir du C pour lequel beaucoup de logiciels existent (analyse formelle entre autre) ou pour un besoin client qui demanderait du C (tu écris du V et lui livre du C (plus productif).
Mais oui il n'y a pas d'avantages majeur au V (performance équivalentes et compilation plus lente) qui permette de lui donner une grosse communauté à terme et beaucoup "d'inconvénient".
Cela reste un projet intéressant pour de la recherche ou pour le fun et utile dans de rare cas.
Sous licence Creative common. Lisez, copiez, modifiez faites en ce que vous voulez.
[^] # Re: go good enough
Posté par erdnaxeli (site web personnel) . Évalué à 5.
J'avais un peu suivi ce langage au début, et l'avantage principal (promis) c'était d'avoir l'expressivité du go mais avec des variables immutables par défaut (ce qui apporte plus de garanties) et sans garbage collector (ce qui améliore les perfs).
Malheureusement j'ai l'impression après la lecture de cette dépêche qu'une bonne partie du langage est encore à l'état de promesses.
Il existe deux catégories de gens : ceux qui divisent les gens en deux catégories et les autres.
[^] # Re: go good enough
Posté par Andréas Livet . Évalué à 5. Dernière modification le 07 septembre 2023 à 09:22.
Oui, il y a un "déjà là" fonctionnelle et tout de même plutôt abouti, mais l'écart entre ce qui est annoncé et la réalité est assez important.
C'est pour moi la plus grosse erreur des concepteurs du langage : de mettre en avant certains aspects qui sont encore très très expérimentaux (gestion de la mémoire, ui etc.).
# Une gestion d’erreur moderne ?
Posté par erdnaxeli (site web personnel) . Évalué à 5.
Effectivement les exceptions qui ne sont pas rattrapées et remontent implicitement la stack trace ne sont pas une solution satisfaisante. Mais je ne trouve pas que la solution proposée soit plus moderne. Ça ressemble plus à du sucre syntaxique avec des conventions implicites, ce qui le rendent moins lisible pour un novice, ce qui est un mauvais point selon moi.
C'est dommage parce que le langage s'inspire du go dont j'aime beaucoup la gestion d'erreur :
* c'est un type comme un autre, il n'y a pas de notion d'erreur dans la syntaxe du langage, c'est une convention, mais une convention explicite
* la gestion des erreurs est elle aussi explicite : si on veut tester si une erreur a été retournée, on teste si l'erreur est différente de nil. Il n'y a pas de "if" magique qui teste implicitement ce cas. Un "if" fonctionne uniquement avec un booléen.
Ça donne du code plutôt verbeux j'en conviens, mais tout est explicite. Et le fait que ça ne soit pas une feature de la syntaxe du langage fait une feature de moins à apprendre.
Le problème restant, et commun à toutes ces gestions d'erreur, c'est la question de comment savoir quelles erreurs peut retourner une fonction. Pour l'instant peu importe le modèle, je n'ai jamais rien vu de satisfaisant.
PS : je suis allé voir la gestion des erreurs en zig, c'est de l'implicite couplé à la gestion implicite des optional, ça me file la nausée ^
Il existe deux catégories de gens : ceux qui divisent les gens en deux catégories et les autres.
[^] # Re: Une gestion d’erreur moderne ?
Posté par David Delassus (site web personnel) . Évalué à 8. Dernière modification le 06 septembre 2023 à 14:32.
Je trouve la gestion d'erreur de Go atroce, pour ne pas dire inexistante.
Le langage ne te force pas à la traiter, rien ne t'empêche d'écrire :
Il peut quand même y avoir des données dans le résultat, même si
err
estnil
:Dans ce cas, on fait quoi de
res
?Il faut utiliser des modules tiers pour garder les informations qu'une stacktrace d'exception a par défaut, car :
Ici on pert complètement l'information, la bonne pratique c'est d'encapsuler l'erreur dans une nouvelle, en utilisant par exemple le module
xerrors
.Le type
error
est concrètement juste une chaîne de caractères, sans module tiers tel quexerrors
ou autre, impossible de déterminer le type de l'erreur, alors qu'avec une exception, on peut au moins faire du pattern matching sur son type.Au final, je préfère un type monadique, comme
std::expected<T, E>
en C++ ouResult<T, E>
en Rust.Ici:
Les exceptions pourraient être du sucre syntaxique pour un tel type monadique. D'ailleurs, l'opérateur
?
en Rust ressemble beaucoup à ça :C'est tout de suite plus propre.
TL;DR: Les gens qui vantent les mérites de la gestion d'erreur en Go, je les comprends pas :(
https://link-society.com - https://kubirds.com - https://github.com/link-society/flowg
[^] # Re: Une gestion d’erreur moderne ?
Posté par Bruno Michel (site web personnel) . Évalué à 6.
Non, c'est une interface :
Source : https://go.dev/doc/effective_go#errors
En pratique, les erreurs sont souvent des chaînes de caractères, mais on peut trouver d'autres types d'erreurs. Par exemple, la bibliothèque standard a un type
PathError
dansio/fs
défini ainsi :Source : https://pkg.go.dev/io/fs#PathError
De nos jours, on peut faire ça avec le module
errors
fourni avec la bibliothèque standard : https://pkg.go.dev/errorsEst-ce que faire un
unwrap
, ça compte vraiment comme traiter l'erreur ? Mon avis personnel est que ce n'est ni mieux ni pire queres, _ := foo()
. Dans les deux cas, on ignore explicitement l'erreur sans la traiter.Perso, je trouve la gestion des erreurs en Go assez bof, mais pas atroce non plus.
[^] # Re: Une gestion d’erreur moderne ?
Posté par David Delassus (site web personnel) . Évalué à 4.
My bad, je le savais en plus, mais j'ai vu tellement de codebases Go ou c'était juste des strings que j'ai fait un raccourci un peu trop rapide.
Oui car
unwrap
sur unResult::Err(E)
çapanic!
. Alors que ne pas faire deif err != nil
en Go, le programme continu comme si de rien n'était.Ben non :
La c'est pas explicite du tout.
Alors qu'en Rust :
En gros :
Chacun ses goûts. Pour ma part, je défend l'idée que "fournir un type/interface 'error'" ce n'est pas de la gestion d'erreur.
En fait, je ne vois même pas de différence avec le C dans ce cas là :
Au moins, la GLib (pas gnu libc, mais bien GLib de GTK), on a
GError
et compagnie :Verbeux, peu pratique, mais déjà un peu mieux qu'un int.
https://link-society.com - https://kubirds.com - https://github.com/link-society/flowg
[^] # Re: Une gestion d’erreur moderne ?
Posté par wilk . Évalué à 4.
Je trouve que la confusion vient du terme "error" qu'on aurait plutôt du appeler "status" ou quelque chose comme ça. C'est une simple information, pas forcément une erreur.
Par exemple io.EOF, sql.ErrNoRows, j'ai des handlers peuvent renvoyer une "erreur" de type Redirect etc.
Du coup c'est une valeur retournée comme une autre et donc traitée comme n'importe quelle valeur.
Comme Go est au départ utilisé pour du réseau le fait que cette "erreur" doit pouvoir renvoyer un string permet de faire transiter tout ça facilement.
C'est aussi comme les retours de commandes unix qui renvoient 0 1 -1…
Y a un copain qui m'a dit récemment, mais tu gérais les erreurs aussi comme ça en Python !
Les véritables erreurs c'est plutôt les panics qu'on rattrape avec recover.
[^] # Re: Une gestion d’erreur moderne ?
Posté par David Delassus (site web personnel) . Évalué à 3.
Et quelle est la différence entre panic/recover et des exceptions avec try/catch ?
https://link-society.com - https://kubirds.com - https://github.com/link-society/flowg
[^] # Re: Une gestion d’erreur moderne ?
Posté par wilk . Évalué à 3.
C'est un peu pareil à part que c'est du catchall.
Dans le fond ça revient au même, qu'on "lance des exceptions" qu'on "rattrape" ou qu'on renvoi des "erreurs" qu'on traite comme des valeurs…
[^] # Re: Une gestion d’erreur moderne ?
Posté par Andréas Livet . Évalué à 2.
Ce point est à mon avis important.
La force de Go est d'être épuré au maximum (je crois qu'il n'y a que 18 mots clés) et donc de reduire au maximum l'effort cognitif pour appréhender le langage : pas trop de nouveaux concepts (bon, les coroutines et les channels c'est déjà pas mal) et un syntaxe claire et explicite.
Là où V se démarque, c'est justement dans ces petits choix syntaxiques qui apportent beaucoup de fluidités à l'écriture. Alors c'est vrai, c'est pas toujours très explicite (les variables "magiques"
it
,err
etc.), mais ça rend le code assez léger.Il y a un aspect moins formel que l'on retrouve généralement plus dans des langages comme python et javascript. Je viens personnellement du C++ à la base et j'ai rapidement été écœuré par le côté ésotérique de la syntaxe et les lenteurs de compilation, puis après j'ai plus codé dans des langages de scripts et ce qui m'écœure aujourd'hui c'est le manque de compilation en amont, le typage faible.
V tente de continué dans la lancé de Go, tout en allant peut-être plus loin dans l’expressivité du code et j'aime bien le résultat.
Après, je code "peu" en V, je lis beaucoup dessus, suit son développement de près, mais ça reste au stade d'expérimentation. Je comprends à 100% que l'on ne veuille pas s'y mettre.
Ah c'est assez étonnant comme remarque, car Zig est justement connu pour être explicite. Dans ce sens où il n'y a pas d'appel de fonction caché, pas d'allocation implicite.
Je trouve le choix d'intégré la gestion d'erreur comme un élément de la syntaxe plutôt judicieux. Cela limite la verbosité du code et rend la gestion d'erreur plus confortable.
J'ai tout de même l'impression qu'avec ces notions de Optional/Result on arrive à une sorte de consensus (ou plutôt de convergence) où beaucoup de langages récents ont fait le choix de traiter les erreurs et les retours de fonction de cette manière.
[^] # Re: Une gestion d’erreur moderne ?
Posté par greendev . Évalué à -3.
If, Goto, def pour la déclaration d'objets (variables, fonctions). C'est tout ce qui compte. On fait bien plus qu'avec n'importe quel langage soit disant moderne.
Pour Go y'en a un peu plus :
https://www.gladir.com/CODER/GO/reservedword.htm
Faudrait aussi prendre en compte les éléments syntaxique pour bien faire (délimiteurs de blocs, affectation, le ? en C, etc.), car ils ont une sémantique. Le système de type (trop de pauvreté n'aide pas) : faute de formation théorique poussée ça tient rarement la route en informatique (au moins les langages à la C ne trichent pas en assumant leur orientation bas niveau). Le système de type ne devrait même pas être imposé par le langage mais proposé en lib standard.
C'est souvent un compromis. Langage complexe ~ code simple vs. langage simple ~ code complexe.
# Quelques notes
Posté par alfu64 . Évalué à 2.
Notes:
L’installation (compilation) se poursuit sans problèmes et le temps dependent de la performance du système , j’ai essayé :
Ubuntu 22 x86_64 temps ~2-5 secondes
Ubuntu 20 aarch64(Samsung/proot) temps quelques bonnes minutes, mais toujours sans faute.
Attention!
a.p.d. La version 0.4.0 les annotations sont balisées différemment ( par @[] )
il faut dire que l’utilisation des []
est fort surchargée :
- pour accéder l’index d’une array
- pour accéder la clé d’un map.
- pour la définition des paramètres génériques
- pour faire référence à des variables externes au contexte d’appel d’une expression lambda.
- jusqu’à v0.4.0 pour définir des annotations.
[^] # Re: Quelques notes
Posté par Andréas Livet . Évalué à 3.
Il faut savoir que la compilation du binaire
v
se fait viagcc
par défaut. En revanche la compilation des binaire issue de fichier écrit en v via la commandev
ouv run
se fait par défaut avectcc
et est extrêmement rapide. Le fait que tout le code se retrouve dans un fichier.c
doit aider un peu je pense.Tu veux dire les attributs (genre
[inline]
etc.) non ?Je viens de le voir dans la release note, dommage que la doc ne soit pas mise à jour en conséquence. Bon en même temps c'est en 0.4.1 qui est sortie la semaine dernière.
# Génial
Posté par alfu64 . Évalué à 3.
C’est un langage qui promet beaucoup.
Par difference au C, les macros sont matérialisés par du code écrit en V, qui est interprété au pas de compilation. La réflexion sur les metadonnees du code se fait ainsi toujours à l’étape de compilation.
Ça été super facile à écrire un Serializer pour json ou xml ( a la base quelques dizaines de lignes du code sans traiter les erreurs d’une manière très profonde), ce qui démontre la puissance de ce mécanisme.
La librairie standard est bien garnie avec le tout nécessaire à la programmation système ou bien pour les applications graphiques ou web.
il existe un gestionnaire des paquets applicatifs (la commande v install ) qui sert à installer des paquets V dans le système ou de publier des modules V sur https://vpm.vlang.io/.
le projet est financé et extrêmement actif ( des ordres de magnitude par rapport à des autres projets OSS )
[^] # Re: Génial
Posté par Andréas Livet . Évalué à 2.
Je suis aussi assez enthousiaste par rapport à ce langage.
C'est un des aspect du langage que je n'aborde pas dans la dépêche, mais il est en effet possible d'avoir du code qui s'exécute à la compilation, un peu à l'instar de
comptime
en Zig mais beaucoup moins générique. Ça reste néanmoins un outil de méta programmation assez puissant et un moyen de remplacer l'usage des maccros dans certains cas (cross compilation). La notion de file embedded est particulièrement intéressante je trouve. Voir la doc à ce sujet. Ce qui est marrant c'est que Zig a exclus cette possibilité danscomptime
, car ce n'est pas cross platform.As-tu des informations la dessus ? J'ai l'impression que la situation est moins claire que pour d'autres projets qui sont sous l'égide de fondation par exemple.
# decouverte
Posté par gaia . Évalué à 1. Dernière modification le 12 septembre 2023 à 07:46.
Salut
Decouverte de ce langage depuis la depêche du 05/09
Vraiment sympathique à pratiquer. Les exemples sont plus qu'utile pour s'y mettre
Langage reste très technique; Heureusement qu'il y a des commentaires içi
J'espère qu'au fure et à mesure qu'il sera à nouveau découvert par certains, comme moi, on pourra partager de nouveaux codes
sinon le fait que ce langage soit open source, permet à la lecture des en tetes ( par exemple string.js.v ), d'optimiser l'utilisation des méthodes …
dans les baba que je n'ai pas vu transpirer dans les commentaires :
déclaration d'une fonction avec un retour :
Pour generer une GUI facile, partir du code user.v (manque de commentaires mais ont s'y retrouve)
Bref avec un peu d'huile de coude facile de s'y mettre
# sssssssss....
Posté par fcartegnie . Évalué à 3.
Avec un nom comme 'V', il tente vraiment de nous faire croire que c'est pas un coup des pythons ?
[^] # Re: sssssssss....
Posté par Gil Cot ✔ (site web personnel, Mastodon) . Évalué à 3.
Attention qu’il s’agissait de la victoire des intras sur les hôtes extras… C’est vrai que c’est à double versant cette lettre ;-)
“It is seldom that liberty of any kind is lost all at once.” ― David Hume
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.