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 :

  1. JavaScript
  2. Java
  3. Python
  4. Ruby
  5. 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 :


FonctionnalitéJavaScriptJavaPythonRubyLua
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)
(barré = abandonnée)
  • CPython (bytecode interpreter written in C)
  • Jython (to jvm bytecode, written in java)
  • IronPython (to clr bytcode written in C#)
  • PyPy (interpreter written in Python)
  • Cython (compiler to C then machine code, written in Python)
  • Pyrex (older Cython)
  • Shed Skin(compiler to C++ then machine code, written in C++)
  • Stackless
  • Unladen Swallow
  • Psyco
  • MRI (interpreter written in C)
  • YARV/KRI (bytecode interpreter written in C)
  • JRuby (interpreter written in java)
  • IronRuby (to clr bytecode written in C#)
  • Rubinius (interpreter written in Ruby)
  • Tiny RB
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(String[] args) {
    code
}
if __name__ == '__main__':
    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
math.floor(a / b) ()
-- puissance
^ ou math.pow(i, power)
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 constructor(params) {
    code
}
public ClassName(params) {
    code
}
def __init__(self, params):
    code
def initialize(params):
    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
is_a? kind_of?
# vrai seulement si c'est une instance la classe
instance_of?
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 __init__(self, a, b):
        self.a, self.b = a, b
Méthodes
Définition d'une méthode methodName(params) {
    code
}
encapuslation methodName(params) {
    code
}
def method_name(self, params):
    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
self
# 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 :
@Override
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" hasattr(obj, 'method_name') 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 (int i = 0; i < m.length; i++) {
        System.out.println(m[i]);
    }
} catch (ClassNotFoundException cnfe) {
    System.out.println("Class not found.");
}
# via une instance
[x for x in dir(ClassName) if callable(getattr(a, x))]
# via une instance
a.methods
non géré
Accès la super méthode super(params) // pour le parent constructor
super.fun(params) // pour une fonction parente
super(params) // pour le parent constructor
super.fun(params) // pour une fonction parente
# class de l'objet COURANT (et pas la superclasse)
super(ClassName, self).method_name(args)
super(params) non géré
Membres statiques
Définition d'une méthode
statique
static methodName(params) {
    code
}
static encapuslation methodName(params) {
    code
}
@staticmethod
def method_name(self, params):
    code
def ClassName.method_name(params)
    code
end
non géré
Classes et méthodes abstraites
Définition d'une classe
abstraite
class ClassName {
    constructor(params) {
        if (this.constructor === ClassName) {
            throw new TypeError('Abstract class ClassName cannot be instantiated directly');
        }
    }
}
abstract class ClassName {
    code
}
from abc import ABC
class ClassName(ABC):
    code
class ClassName
    def initialize
        raise NotImplementedError, 'Not implemented'
    end
end
non géré
Définition d'une méthode
abstraite
methodName(params) {
    throw new Error('Not implemented');
}
abstract encapuslation methodName(params) {
    code
}
# Façon propre
from abc import ABC, abstractmethod
class ClassName(ABC):
    @abstractmethod
    def method_name(self, params):
        code
# Façon pas propre
def method_name(self, params):
    raise NotImplementedError
def method_name(params):
    raise NotImplementedError, 'Not implemented'
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
hasattr(obj, 'name')
# variable ou fonction locale
'name' in locals()
# variable ou fonction globale
'name' in globals()
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 # Write Excel
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")
2005 ❤ 2017