Comparaison de la syntaxe de plusieurs langages de programmation
Cette page est inspirée par la démarche de Pascal Rigaux qui a produit un document bien plus complet portant sur bien plus de langages. Il existe aussi le site Hyperpolyglot qui compare la syntaxe de différents langages. De mon côté, je vais me concentrer sur les 4 langages que j'utilise le plus souvent :
- JavaScript
- Java
- Python
- Ruby
- Lua
Mon but est de faire un aide-mémoire pour savoir comment la fonctionnalité X marche avec le langage Y, de repérer les différences de comportement et enfin de produire une syntaxe pour un petit langage personnel.
Attention : parfois, sous une syntaxe proche se cache parfois une gestion ou une conception complètement différente d'une fonctionnalité. Quand c'est le cas, nous essayerons de le préciser brièvement.
Sommaire :
- Généralités
- Éléments de base
- Contrôle du flux
- Séquence
- Sélection
- Répétition
- Types de données
- Chaînes de caractères
- Nombres
- Booléens
- Tuples
- Littéral
- Listes
- Dictionnaires
- Opérateurs
- Sous-programmes
- L'orienté objet
- Modules
- Bibliothèques de base
- Bibliothèques externes
Fonctionnalité | JavaScript | Java | Python | Ruby | Lua | |
---|---|---|---|---|---|---|
Généralités | ||||||
Site officiel | Fondation Mozilla | https://www.java.com/fr/ | https://www.python.org/ | https://www.ruby-lang.org/ | https://www.lua.org | Notes personnelles |
Aide-mémoire |
Naissance | Décembre 1995 | Janvier 1996 | Février 1991 | Décembre 1995 | 1993 | |
Découverte personnelle |
2004 | 2005 | 2005 | |||
Numéro de version utilisée |
ES6/ECMAScript 2015 | 8 | 3.7.0 | 2.5.3 | ||
Implémentations (gras = utilisée) ( |
|
|||||
Outil REPL (invite) |
python (>>>) | irb (irb(main):LIGNE:NIVEAU>) | lua (>) | |||
Manager de bibliothèques |
LuaRocks | |||||
IDE | Eclipse, Netbeans, IntelliJ IDEA | PyCharm | RubyMine | ZeroBrane | ||
Éléments de base | ||||||
Commentaire monoligne |
// comment | // comment | # comment | # comment | -- comment | |
Commentaire multiligne |
/* comment */ |
/* comment */ |
=begin comment =end |
--[[ comment ]] Tips: use --]] to close to easily switch between commenting/ uncommenting. |
||
Instruction nulle | pass | |||||
Bloc | { } | { } | begin ... end | do ... end | ||
Référence | var id = expression ; let id = expression ; |
type id = expression ; | id = expression | id = expression | id = expression | |
Fonction principale | public static void main( code } |
if code |
||||
Quitter programme | exit() exit(expr) | exit() exit exit(expr) exit expr |
os.exit() | |||
Contrôle du flux | ||||||
Séquence | ||||||
Suite d'instructions | retour à la ligne ou ; | retour à la ligne ou ; | ||||
Sélection | ||||||
Sélection conditionnelle simple |
if (condition) { code } else if (condition) { code } else { code } |
if (condition) { code } else if (condition) { code } else { code } |
if condition: code elif condition: code else: code |
if condition then | \n code elsif condition then | \n code else code end |
if condition then code [ elseif condition then code ] * [ else code ] ? end |
|
Post-sélection conditionnelle |
action if condition | |||||
Répétition | ||||||
Boucle pré- conditionnelle |
while (condition) { code } |
while (condition) { code } |
while condition: code |
while condition do | \n code end |
while condition do code end |
|
Boucle post- conditionnelle |
repeat code until condition |
|||||
Boucle sur intervalle |
for indice in range(in_min, out_max): code |
for id = début, fin [ , pas ] do code end |
||||
Boucle sur liste |
for (let valeur of liste) { code } |
for indice in liste: code |
for indice, valeur in ipairs(table) do code end |
|||
Boucle sur dictionnaire |
for clé in dico: code for clé, valeur in dico.items(): code |
for clé, valeur in pairs(table) do code end |
||||
Quitter une boucle |
break ; | break ; | break | break | break | |
Aller à l'itération suivante |
continue ; | continue ; | continue | next | rien | |
Types de données | ||||||
Chaînes de caractères | ||||||
Nombres | ||||||
Booléens | ||||||
Littéraux | true false | true false | True False | true false | ||
Valeurs considérées comme fausses |
0, -0, null, false, NaN, undefined ou "" |
False | false nil | |||
Tuples | ||||||
Littéral | (elem1, elem2, ...) (elem1,) |
|||||
Listes | ||||||
Littéral | [elem1, elem2, ...] | [elem1, elem2, ...] | {elem1, elem2, ...} | |||
Dictionnaires | ||||||
Littéral | {key1: val1, key2: val2, ...} | {key1: val1, key2: val2, ...} | {key1 => val1, key2 => val2, ...} | {key1 = elem1, key1 = elem2, ...} identifiers are allowed as keys |
||
Accès | id[key] | id[key] | id[key] ou id.key | |||
Opérateurs | ||||||
Mathématiques | + - / * % | + - / * % | + - / * % # division entière // # puissance ** |
+ - / * % # puissance ** |
+ - / * % -- division entière -- puissance ^ ou |
|
Comparaison | < <= == != >= > | < <= == != >= > | < <= == != >= > | < <= == != >= > <=> (renvoit 3 valeurs) |
< <= == ~= >= > | |
Booléens | && || ! | && || ! | and or not | and or not | and or not | |
Affectation | = | = | = | = | = | |
Affectation combinée | += -= /= *= | non gérée | ||||
Concaténation de chaînes | + | .. | ||||
Sous-programmes | ||||||
Déclaration | def name(par1 [: typ1], ... ) [ -> retyp]: code |
|||||
Orienté objet | ||||||
Classes et instances | ||||||
Déclaration | class ClassName { code } |
class ClassName { code } |
class ClassName: code |
class ClassName code end |
non géré | |
Héritage | class ClassName extends SuperClass { code } |
class ClassName extends SuperClass { code } |
class ClassName(SuperClass): code |
class ClassName < SuperClass code end |
non géré | |
Encapsulation | public (rien = niveau package) protected private |
__ # au début d'un membre le masque | public protected private |
non géré | ||
Constructeur | code } |
public ClassName(params) { code } |
def code |
def code |
non géré | |
Création d'une instance | let i = new ClassName(params); | ClassName i = new ClassName(params); | i = ClassName(params) | i = ClassName.new(params) | non géré | |
Tester si a est une instance de A ou une de ses sous-classes | // test si a est une instance de A ou d'une de ses sous-classes a instanceof A // test si a est une instance de A uniquement a.getClass() == A.class |
// test si a est une instance de A ou d'une de ses sous-classes a instanceof A // test si a est une instance de A uniquement a.constructor.name === "A" A.prototype.isPrototypeOf(a) |
# test si a est une instance de A ou d'une de ses sous-classes isinstance(a, A) # test si a est une instance de A uniquement a.__class__ == A |
# vrai si c'est une instance de la classe ou d'une sous-classe # vrai seulement si c'est une instance la classe |
non géré | |
Copie d'une instance | public class ClassName implements Cloneable { } try { ClassName i1 = new ClassName(); ClassName i2 = (ClassName) i1.clone(); } catch (CloneNotSupportedException cne) { code } |
# Copie non profonde from copy import copy, deepcopy i1 = ClassName() i2 = copy(i1) # Copie profonde i3 = deepcopy(i1) |
||||
Destruction d'une instance | delete a | ne peut être fait explicitement | del i | |||
Attributs | ||||||
Définition | # Avec les slots, on ne peut pas ajouter ou enlever des attributs des instances class ClassName: __slots__ = ('a', 'b') def |
|||||
Méthodes | ||||||
Définition d'une méthode | methodName(params) { code } |
encapuslation methodName(params) { code } |
def method_name( code |
def method_name(params) code end |
non géré | |
Accès à l'objet courant | // obligatoire this |
// implicite this |
# obligatoire # toujours en 1er paramètre |
# attribut accessible avec @ self |
non géré | |
Appel d'une méthode | obj.method(params) | obj.method(params) | obj.method(params) | obj.method(params) | obj:method(params) | |
Appel d'une méthode via son nom | Object.getOwnPropertyDescriptors(ClassName.prototype)['method'].value(params) | getattr(obj, 'method')(params) | obj.send('method', params) # Alternativement method_object = obj.method(:length) method_object.call(params) |
|||
Surcharge d'une méthode (overloading) On peut avoir 2 fonctions avec le même nom et des paramètres différents |
non gérée | oui | non gérée | non gérée | non gérée | |
Redéfinition d'une méthode (overriding) |
directement | directement, optionnellement : encapuslation methodName(params) { code } |
directement | directement | non gérée | |
Test si une instance a une méthode | 'methodName' in obj && typeof obj.methodName === "function" | obj.respond_to? :fun obj.respond_to? "fun" |
||||
Obtenir toutes les méthodes d'une instance | // via la classe de l'instance Object.getOwnPropertyNames(ClassName.prototype) Object.getOwnPropertyDescriptors(ClassName.prototype) |
// via la classe de l'instance import java.lang.reflect.Method; try { Class cls = Class.forName("ClassName"); Method m[] = cls.getMethods(); for ( System.out.println(m[i]); } } catch (ClassNotFoundException cnfe) { System.out.println("Class not found."); } |
# via une instance [x for x in |
# via une instance a.methods |
non géré | |
Accès la super méthode | # class de l'objet COURANT (et pas la superclasse) |
non géré | ||||
Membres statiques | ||||||
Définition d'une méthode statique |
static methodName(params) { code } |
static encapuslation methodName(params) { code } |
def method_name( code |
def ClassName.method_name(params) code end |
non géré | |
Classes et méthodes abstraites | ||||||
Définition d'une classe abstraite |
class ClassName { if (this.constructor === ClassName) { throw new } } } |
abstract class ClassName { code } |
from abc import ABC class ClassName(ABC): code |
class ClassName def raise end end |
non géré | |
Définition d'une méthode abstraite |
methodName(params) { throw new } |
abstract encapuslation methodName(params) { code } |
# Façon propre from abc import ABC, abstractmethod class ClassName(ABC): def method_name( code # Façon pas propre def method_name( raise |
def method_name(params): raise end |
non géré | |
Réflexivité | ||||||
Modules | ||||||
Interfaces | interface Name { définitions } |
|||||
Imports | import name import name1 as name2 from name import elem1, ... from name import * |
|||||
Bibliothèques de base | ||||||
Is it defined? | # attribut # variable ou fonction locale 'name' in # variable ou fonction globale 'name' in |
|||||
Intervalles | range(max_non_inclu) range(min, max_non_inclu) |
min..max min...max_non_inclu |
||||
Get/change working dir |
import os os.getcwd() os.chdir(path) |
Dir.pwd | ||||
Lister répertoire |
import os os.listdir(path) |
Dir.glob("*") | ||||
Test si un fichier existe et est un répertoire |
import os.path os.path.isfile(path) os.path.isdir(path) |
File.exist?(path) | ||||
Obtenir extension |
import os.path os.path.splitext(path) (Attention : '.log' => '.log', '') |
|||||
JSON Writing | import json f = open('pipo.json', 'w') data = { 'a' : 'abcd', 'b' : 5, 'c' : True} json.dump(data, f, indent=" ") f.close() |
|||||
JSON Reading | import json f = open('pipo.json') data = json.load(f) f.close() |
|||||
XML Writing | import xml.etree.ElementTree as ET e = ET.Element('tag') e.set('attr1', '5') e.attrib['attr2'] = '6' ET.dump(e) ET.ElementTree(e).write('pipo.xml') |
|||||
XML Reading | import xml.etree.ElementTree as ET # From file tree = ET.parse('pipo.xml') elem = tree.getroot() # From string elem = ET.fromstring('<tag attr1="5" attr2="6"/>') # Access elem.tag # string of the tag elem.attrib # dict of attributes |
|||||
Bibliothèques externes | ||||||
Générales | ||||||
GUI | ||||||
Parsing | ||||||
Format de données |
import xlwt book = xlwt.Workbook() sheet = book.add_sheet("Sheet1") data = ['a', 'b', 'c', 'd', 'e'] for irow in range(10): row = sheet.row(irow) for icol, val in enumerate(data): row.write(icol, f"{val}{irow}") book.save("out.xls") |