Non, finalement il n'y aura pas de fiche sur les matrices et les déterminants parce que c'est trop lourd et pas particulièrement utile.
Mais il y en a une sur l'intégration. Elle comporte aussi un récapitulatif (très succinct) de la partie sur l'intégration de fractions rationnelles et des fonctions avec du sqrt(a*x^2+b*x+c), ainsi que quelques primitives usuelles. J'ai sauté toute la partie sur les fonctions en escaliers, et les sommes de Riemann aussi, parce que franchement c'est pas ça qui pose problème.
Soit dit en passant, je suis aussi tombé sur une mine d'or ce matin. C'est bien, je suis content.
Salutations,
Aujourd'hui fut une journée de grand avancement pour PIF. En effet, nous pouvons maintenant compiler et exécuter la fonction suivante, qui donne un résultat plutôt juste :
func integrate : (f : &(x : float) -> float, x0 : float, x1 : float, n : int) -> float {
## Calcul approché d'une intégrale par la méthode des trapèzes
if x1 == x0 return 0
let dx = (x1 - x0) / (n : float)
var sum : float = 0
var i = 0
while i < n {
let x = x0 + (i : float * dx)
sum = sum + (f(x) + f(x + dx)) / 2 * dx
i = i + 1
}
return sum
}
Ou sinon j'ai ça en stock - qui tourne et qui affiche des nombres premiers, bien sûr :
func find_primes : (max : int) -> {
var i = 1
while i < max {
i = i + 1
if !is_prime(i) continue
print_int(i)
}
print_nl()
}
func is_prime : (num : int) -> bool {
var d = 2
while d*d <= num {
if num % d == 0 return false
d = d + 1
}
return true
}
(Remarque : print_int et print_nl sont des fonctions externes aux programmes, mais intégrées au compilateur)
À ceux que ça choque le if sans then et sans crochets non plus : en fait, j'ai choisi d'être le plus laxiste possible sur la syntaxe, c'est à dire que tant que le compilateur est capable de comprendre ce que vous voulez dire, alors c'est ok. Dans des cas plus délicats il peut être nécessaire de rajouter de la ponctuation, mais de manière générale vous mettez ce que vous voulez, comme vous voulez pour que ça soit à votre goût. Moi je voulais mettre des if sans then, et en l'occurrence ça ne pose pas de problème donc je me le suis permis.
En bref, les poins importants qui rendent tout ça possible :
for pour l'instant, j'aimerai faire un joli for qui soit intégré avec la POO, mais ça va être un peu compliqué je le sens)Ce qui sera fait bientôt :
Le code du compilateur est bien au chaud chez moi pour l'instant. Si quelqu'un en veut, je peux le mettre sur un GitHub. Il suffit de demander.
Je suis en train de réfléchir à PIF, aux variables, aux types, aux références, et j'ai décidé de tout changer.
En fait, on ne fait que changer quelques mot-clefs. J'ai renommé let en var et const en let, ce que fait que l'on aura donc maintenant deux mot-clefs super proches, dont j'espère que la dénomination est suffisamment explicite, et dont il sera impératif de comprendre la distinction et le fonctionnement sous-jacent.
J'oublie ici tout ce qui était avant pour expliquer ce que je propose maintenant.
letLorsque l'on utilise un let, on crée juste un nouveau nom pour la valeur que l'on a donné. On n'a pas de référence sur cette valeur, ce qui signifie que l'on ne peut pas la changer.
let a = 42 # a est du type int, c'est à dire une valeur entière
a = 43 # invalide, ne compilera pas
C'est un peu comme ce que l'on fait en caml ou dans d'autres langages fonctionnels.
Remarquez en passant que les arguments d'une fonction sont immuables, c'est à dire que c'est comme s'ils avaient été déclarés avec un let.
varLorsque l'on utilise un var, on crée un nouvel espace mémoire que l'on remplit alors avec la valeur proposée, puis on attribue au nom donné la valeur d'une référence vers cet emplacement mémoire.
var a = 42 # a est du type &int, c'est à dire une référence sur un entier
a = 43 # ok ça marche
Définissons le type suivant :
type Complex [
re, im : float
]
Le problème vient des deux syntaxes suivantes, qui sont identiques :
var a : Complex = [12, 23]
var a = [12, 23] : Complex
Dans cette syntaxe lors de l'initialisation de l'objet avec les crochets, on crée un emplacement mémoire pour les données de l'objet de type Complex, obtenant ainsi une référence, c'est à dire un &Complex. On donne alors des valeurs aux variables de cet objet, puis (s'il y en a un), on appelle le constructeur sur cet objet, cela étant permis par le fait que l'on a une référence. Puis on déréférence ensuite l'objet pour obtenir une valeur de type Complex, qui est ensuite copiée dans un emplacement mémoire créée par le var pour obtenir une nouvelle référence. Que de complications.
Peut-être que ceci serait optimisé par LLVM, c'est d'ailleurs probable, celui-ci étant plutôt bien foutu. Mais fondamentalement, ça reste vraiment foireux. Mais heureusement, on peut aussi faire ça :
let a : &Complex = [12, 23]
# ou
let a = [12, 23] : &Complex
On crée ici une référence sur un Complex, qui n'est pas déréférencée mais bien attribuée telle quelle au nom a.
Lorsque l'on veut définir des objets que l'on souhaite bidouiller par la suite, il est donc impératif d'utiliser la deuxième syntaxe, avec un let et en spécifiant explicitement que l'on veut une référence, et pas la première.
Peut-être faudrait-il, pour que cela soit encore plus parlant, introduire un constructeur de copie pour les types, c'est à dire une méthode qui serait appelée à chaque fois que l'on copie un objet dans un nouvel emplacement mémoire, que ce soit lors d'un var, lors du passage d'un objet comme paramètre, ou lors d'une affectation quelconque. On verrait alors bien que avec la première syntaxe présentée ci-dessus utilisant un var, on fait le cheminement suivant : construire A, copier A vers B, détruire A, alors que la syntaxe meilleure avec un let ne fait que construire A et le garder.
Salutations camarades, amis proches ou éloignés, de tous bords, de tous genres, de toutes origines, de tout penchants religieux ou politiques, de toutes orientations sexuelles, et bien plus que ça.
Je suis actuellement en train de travailler sur un nouveau langage de programmation, non pas pour faire un langage populaire, mais plutôt comme une expérience personnelle. J'ai choisi le chemin facile, à savoir que je laisse le gros de l'optimisation et de la compilation à LLVM.
Il y a plusieurs objectifs à un tel projet :
Je l'ai déjà dit, mais il y a aussi un non-objectif : celui de concurrencer les langages existants.
Mais j'oublie un point important : ce langage s'appelle PIF, ce qui est un acronyme pour Programming Is Fun - ce qui montre bien l'état d'esprit du projet. Il s'agit d'un langage pour apprendre la programmation en s'amusant dans son coin, mais pas particulièrement prévu pour des gros projets. Comprendre aussi : c'est mon langage, c'est mon compilateur, alors je fait ce que je veux (et je vous emmerde - sauf votre respect).
Mais dans la pratique, ça ressemble à quoi ?
J'ai commencé à écrire les spécifications sur mon bloc-notes ici (document principal).
Il n'y a que six types de bases : void, bool, byte, int, float, string (cf les spécifications).
On pourra aussi utiliser des types de taille différentes pour les nombres entiers, mais globalement j'encourage à la simplicité et donc à n'utiliser que les six types de base, les autres n'ayant leurs utilité que lorsqu'il s'agit de communiquer avec le monde extérieur (comprendre : appel de fonctions de bibliothèques en C par exemple).
Il y aura aussi des types pour les tableaux. Ceux-ci fonctionneront d'une manière similaire aux tableaux de Go. Mais chaque chose en son temps, les tableaux ne sont pas du tout dans mes priorités pour l'instant. Les string non plus, d'ailleurs, parce que c'est vraiment un gros morceau.
Je m'attend à ce que personne ne comprenne pourquoi j'ai choisi une telle syntaxe. En gros, il y a toujours à peu près deux raisons pour tel ou tel choix :
Voici donc, sans attendre, des exemples de code :
################# MATH LIBRARY ###################
# BECAUSE YOU LOVE MATH AND SO DO I
##################################################
######### BASIC MATH #########
## packages/pif/math/math.pif
Attention : non seulement s'agit-il ici d'un extrait de code de la bibliothèque pour faire des maths - qui en fait fait essentiellement appel aux fonctions de la libm - mais c'est surtout du code non réaliste, qui concrètement sera écrit autrement. C'est vraiment juste pour l'exemple. En passant, remarquez que les commentaires commencent par un #.
const pi : float = 3.1415926536
let tau = 2 * pi
Les deux lignes précédentes étaient assez explicites, je laisse le soin au lecteur de les comprendre. Remarquez l'utilisation du mot-clef let pour déclarer ses variables. Je l'ai choisi car var et def sonnaient très mal, défaut rédhibitoire pour mon idée - let est tout aussi conventionnel et compréhensible à mon avis. Remarquez aussi l'organisation de la déclaration de pi : le signe deux-points (:) indiquera toujours que ce qui suit est le type à considérer pour l'objet qui précède - il est donc utilisé dans toutes les déclarations, définitions de structures, etc.
func abs : (x : float) -> float {
if x >= 0 then return x
else return -x
}
C'est un dilemme pour moi : dois-je écrire la fonction abs qui prend un float pour renvoyer un float, ou dois-je l'écrire avec des int ? Vais-je devoir en écrire deux ? En tout cas, il n'est pas question d'implémenter de surcharge des fonctions, c'est bien trop lourd et anti-principes-fondamentaux-décrits-plus-haut.
Mais examinons ces lignes un peu plus en détail, car elles sont très révélatrices. D'abord, constatez que la fonction abs est du type noté (x : float) -> float, à comprendre qu'elle prend en argument un float appelé x, et renvoie un float. C'est plutôt clair, non ? Le nom de l'argument (ici x) prend son importance lorsqu'on a une fonction qui prend vraiment tout plein de paramètres, et que ceux-ci sont optionnels, et que l'on veut en préciser juste quelques-uns. Sinon, c'est pas trop grave.
Ensuite, il y a le if. Peut-être le classique if...then...else... vous fait penser trop à du vieux QBasic foireux - dans ce cas, tout peut s'arranger, parce que dès que l'on veut mettre plus qu'une seule ligne dans le corps du if, il est nécessaire d'utiliser des accolades pour délimiter un bloc de code, ce qui nous dispense alors d'écrire le then (mais vous pouvez aussi le mettre si ça vous fait plaisir, franchement je m'en fous). Dans ce cas précis, ça peut donner un truc comme ça :
# AUTRE VERSION, JUSTE POUR L'EXEMPLE
func abs : (x : float) -> float {
let ret = x
if ret < 0 {
ret = -ret
}
return ret
}
C'est mieux ? Bien, passons à la suite :
func sqrt : (x : float) -> float
extern sqrt
func cos : (x : float) -> float
extern cos
Ces deux exemples illustrent typiquement la référence à une fonction externe, en l'occurrence on définit les fonctions sqrt et cos, toutes les deux du même type, et faisant références aux fonctions du même nom dans la libm.
func sin : (x : float) -> float {
return (extern sin : (x : float) -> float) (x)
}
La fonction ci-dessus montre une autre façon de référencer une fonction externe. Ici c'est tout à fait inutile, mais c'est pour l'exemple. Remarquez que l'on a tout simplement importé la fonction sin en précisant son type, sans lui donner de nom particulier dans notre programme (c'est donc une fonction anonyme), puis on l'a appelée directement.
Maintenant, parlons un peu des pointeurs de fonction. Attention : les pointeurs sur fonction, c'est pas encore au point et je suis pas convaincu que ça va se faire exactement comme ça au niveau syntaxe, même si ça a l'air plutôt pas mal. Ce n'est pas encore rentré dans les spécifications.
func tan : (x : float) -> float {
let externTanPtr : (x : float) -> float = extern tan
return externTanPtr(x)
}
Cette fois c'est un peu pareil, sauf qu'on a utilisé un pointeur de fonction, auquel on a attribué une référence à la fonction externe tan. On a ensuite utilisé ce pointeur pour appeler la fonction.
Finalement, pour illustrer les fonctions anonymes et les pointeurs de fonctions, du code cette fois vraiment inutile :
let func_ref = func (val : float) -> float {
return sqrt(val)
}
let sqrtOf2 = (func (val : float) -> float { return sqrt(val) }) (2)
Dans ce premier exemple, on définit un pointeur de fonction et on lui donne comme valeur une fonction qui a été créée sur le champ. Si le let avait été un const, cela aurait été l'équivalent approximatif d'une définition de fonction classique. Mais c'est moche et inutile, en fait, donc on préfère faire comme tout le monde et déclarer ses fonctions normalement.
Dans le deuxième exemple, on crée une fonction qui renvoie la racine carrée de l'argument, que l'on applique immédiatement avec l'argument 2, pour donner la valeur récupérée à la variable sqrtOf2.
Je ne suis moi-même pas tout à fait convaincu de ce nouveau langage que j'imagine aujourd'hui - et dont j'avais déjà commencer à coder un bout de compilateur, mais la syntaxe a changé depuis, alors je vais devoir modifier plein de trucs. Bref, voilà.
Dans le prochain épisode, s'il y a lieu, on parlera un peu des structures, des classes, des méthodes, etc.
Yo.
À partir de maintenant, le blog est ouvert aux commentaires. Je sais que personne ne va en poster, mais peu importe.
Je vous rappelle aussi que n'importe qui peut venir se créer un compte ici et poster sur le blog - j'invite tous les gens que ça intéresse à y participer. Si ce que vous écrivez est intelligent, il y a une chance pour que je m'y intéresse, et même que j'y réponde. Sinon, non. Si c'est débile - ou si c'est du spam, ce qui pourrait arriver - alors ça sera l'occasion pour moi de modifier quelques lignes de code pour me permettre de supprimer vos messages - plus facilement qu'à la main en trifouillant la BDD.
Bon bref voilà.
Pour ceux que ça intéresse (c'est à dire personne - en effet, les personnes que ça risque d'intéresser ne se baladent sûrement pas par ici), je met en ligne mes fiches de révision pour mon cours de maths à cette adresse. La plupart du temps, il s'agit globalement de recopier les théorèmes, définitions et propriétés du cours - mais en plus joli. La dernière en date concerne le cours sur la dimension finie, il y en a aussi une sur les plolynômes et les fractions rationnelles, les développements limités, la dérivation, ainsi qu'une cheat sheet avec toutes les formules de trigo qu'il faut impérativement savoir par cœur, sous peine de rater sa vie et de mourir non seulement sans avoir rien achevé de grand et mémorable pour l'humanité, mais aussi tout simplement en ignorant la vérité profonde - et pourtant toute simple - des mathématiques. Je vais probablement en faire une sur les matrices et les déterminants aussi, parce que c'est un cours plutôt compliqué. Sinon, il y a aussi les DM que je rédige à l'ordi, ce qui n'a aucun intérêt même pour moi, si ce n'est que... *ahem*, bref ça ne vous regarde pas.
... on dessine des fractales (à la main bien entendu).
Voici le résultat : dossier de fractales
Pour ceux que ça intéresse, le code en Caml qui a permi de les générer :
#open "graphics";;
open_graph " 1024x768+0-0";;
(* HSV to RGB *)
let hsv h s v =
let c = v *. s in
let hh = (h mod 360)/60 in
let hhf = (mod_float (float_of_int h) 360.) /. 60. in
let x = c *. (1. -. (abs_float (mod_float hhf 2. -. 1.))) in
let m = v -. c in
let cc = int_of_float ((c +. m) *. 255.) in
let xx = int_of_float ((x +. m) *. 255.) in
let mm = int_of_float (m *. 255.) in
match hh with
| 0 -> rgb cc xx mm
| 1 -> rgb xx cc mm
| 2 -> rgb mm cc xx
| 3 -> rgb mm xx cc
| 4 -> rgb xx mm cc
| 5 -> rgb cc mm xx
| _ -> rgb mm mm mm;;
(* complex numbers *)
let zeroC = (0., 0.);;
let addC (a, b) (c, d) = (a+.c, b+.d);;
let mulC (a, b) (c, d) = (a*.c -. b*.d, a*.d +. b*.c);;
let absC (a, b) = sqrt(a**2. +. b**2.);;
(* drawing *)
let pos (xmin, xmax, ymin, ymax) (x, y) =
int_of_float((x-.xmin)*.(float_of_int(size_x()))/.(xmax-.xmin)),
int_of_float((y-.ymin)*.(float_of_int(size_y()))/.(ymax-.ymin));;
let pos_inv (xmin, xmax, ymin, ymax) (x, y) =
float_of_int(x)*.(xmax-.xmin)/.(float_of_int(size_x()))+.xmin,
float_of_int(y)*.(ymax-.ymin)/.(float_of_int(size_y()))+.ymin;;
(* mandelbrot & julia fractal *)
let iter = 300;;
let color_frac n =
if n = iter then set_color black
else set_color (hsv (n*4+200) 0.7 0.6);;
let mandel_pt c =
let rec aux z n =
if n = iter then n
else if absC z >= 2. then n
else aux (addC (mulC z z) c) (n+1)
in
aux zeroC 0;;
let mandel repere =
for i = 0 to size_x() do
for j = 0 to size_y() do
let x, y = pos_inv repere (i, j) in
let n = mandel_pt (x, y) in
let px, py = pos repere (x, y) in
color_frac n;
plot i j
done
done;
set_color black;
moveto 10 10;
draw_string ("mandelbrot iter = " ^ (string_of_int iter)) ;;
let julia_pt c z0 =
let rec aux z n =
if n = iter then n
else if absC(z) >= 2. then n
else aux ((addC (mulC z z) c)) (n+1)
in aux z0 0;;
let julia repere (a, b) =
(* clear_graph(); *)
for i = 0 to size_x() do
for j = 0 to size_y() do
let x, y = pos_inv repere (i, j) in
let n = julia_pt (a, b) (x, y) in
let px, py = pos repere (x, y) in
color_frac n;
plot i j
done
done;
set_color black;
moveto 10 10;
draw_string ("julia " ^ (string_of_float a)
^ " + " ^ (string_of_float b)
^ "i iter = " ^ (string_of_int iter));;
let repere = (-.1.6, 1.6, -.1.5, 1.5);;
mandel repere;;
julia repere (0.3, 0.01);;
julia repere (0.3, 0.024);;
julia repere (0.33, 0.024);;
julia repere (0.18, 0.7);;
julia repere (-.0.54, 0.55);;
julia repere (-0.4, 0.6);;
julia repere (0.285, 0.01);;
julia repere (-0.70176, 0.3842);;
julia repere (-0.835, 0.2321);;
julia repere (-0.8, 0.156);;
Pour pouvoir profiter du spectacle, je vous invite à utiliser ce code avec un IDE permettant l'execution pas-à-pas du code (LinCaml, WinCaml ou autre MacCaml), ou à le rentrer directement à l'invite OCaml.
L'utilisateur lambda, c'est tout à fait normal qu'il se tourne vers les solutions privatrices que tout le monde connaît (pour ne pas les citer, Windows et Mac OS X). Et pourquoi ? Parce que ces systèmes sont meilleurs, d'un point de vue technique et fonctionnel. En effet, les systèmes d'exploitation alternatifs libres souffrent de défauts majeurs, que je tenterai de développer ici :
Pour résumer vite fait : les systèmes d'exploitation aujourd'hui sont soit bordéliques et inadaptés au grand public, soit privateurs. Dans un tel contexte, ce n'est pas tout à fait anormal que la majorité des utilisateurs renoncent à leurs libertés pour utiliser un système qui leur convient mieux.
Développons un peu, point par point :
Oui, c'est le bordel du côté des systèmes GNU/Linux. Déjà, il y a une infinité de distributions, toutes avec des outils différents pour faire, au final, globalement la même chose. Par exemple :
Mais considérons que, tant que les distributions restent cohérentes en elles-mêmes sur ces points, ça peut encore aller - d'autant plus que chaque distribution peut avoir un objectif précis, qui ne peut être réalisé qu'à l'aide d'un outil en particulier. En fait, il y a beaucoup plus gênant :
Personnellement, j'ai déjà voulu coder des "petites" applications de bureau, et j'étais complètement perdu dans le choix du langage de programmation et des bibliothèques et toolkits à utiliser, tant bien que j'ai la plupart du temps abandonné mon projet avant même de le commencer.
Globalement, j'aurai tendance à dire que dans le mouvement du logiciel libre, le développeur lambda tendance à coder son projet chacun dans son coin, en suivant ses tendances personnelles, ce qui de toute évidence n'aide pas à résoudre les problèmes ci-dessus.
Il serait beaucoup plus intéressant que, au lieu de vouloir promouvoir chacun son projet et sa manière de faire, les développeurs de tous bords aient une volonté commune d'avancer vers un idéal, un système qui ait une certaine forme de cohérence. Cela n'implique pas forcément que l'on impose une hiérarchie aux développeurs, c'est plutôt une prise de conscience globale, qui permettrait que chacun réfléchisse à ce qui est mieux pour la globalité, et oriente son travail dans cette direction là, plutôt que de partir chacun dans son coin.
Un exemple très simple devrait vous permettre de comprendre globalement où je veux en venir : où sont, mais bordel de merde où sont les logiciels de reconnaissance vocale pour Linux ? Ah ben non, il n'y en a pas. Pourtant, c'est sacrément utile, dans certains cas. En tout cas, l'utilisateur lambda, lui, il fait de la bureautique, et selon ses activités il peut être très content, voir même avoir besoin, de pouvoir dicter ses documents, pour toutes les raisons que vous pouvez imaginer. (Je connais plusieurs personnes qui ne pourraient pas vraiment se passer de ça).
Je n'ai plus d'idées pour développer ce point. Veuillez m'en excuser.
Moi je dis, regardez : le système le plus populaire, et qui semble largement satisfaire (quand même hein, il faut le dire!), n'est pas basé sur Unix. Oui, c'est pour moi une preuve flagrante qu'Unix n'est peut-être tout simplement pas adapté à l'utilisateur lambda. Ou en tout cas, sous sa forme actuelle de GNU/Linux, il ne l'est pas. Remarquons quand même qu'Apple a réussi à en faire quelque chose d'orienté grand-public, et franchement je pense qu'ils ont réussi.
En fait, le problème vient essentiellement du fait qu'Unix, encore une fois, est multiple : il y a plein de systèmes d'init, plein d'interpréteurs de commandes différents, plein d'implémentations de la libc qui varient sur des poins fondamentaux, mais qui au final offrent nombre de différences parfois subtiles dans les interfaces offertes au programmeur, obligeant l'utilisation d'un système appelé autotools, qui alourdit considérablement le processus de développement d'applications.
En fait, il faut effectivement admettre que jeter tout Unix à la poubelle et repartir sur autre chose, ça risque d'être très difficile. On peut peut-être s'en contenter, mais il faut voir aussi où sont les problèmes, et essayer de faire avec pour construire, encore une fois, quelque chose de cohérent.
Il y a deux types de programmeurs, et j'aurai tendance à les différencier selon la génération à laquelle ils appartiennent :
En fait, l'augmentation exponentielle des performances des systèmes conduit à un certain laisser-aller de la part des développeurs, se disant que s'ils ne codent pas bien, ce n'est pas grave parce qu'un algorithme en O(n²) s'exécutera aujourd'hui (sur des petits ensembles de données) aussi rapidement qu'un algorithme en O(log n) sur du matériel d'il y a 10 ou 20 ans. En fait, je crois même qu'il y a une portion de programmeurs qui ne s'en rendent même pas compte, tout simplement car comme ils ne voient pas la lenteur de leurs programmes (ou alors celle-ci leur parait négligeable), ils vont rester sur un algorithme inefficace, se disant que ça ira bien.
De manière générale, on peut donc dire que les gens qui codent ne codent pas forcément bien, ce qui conduit au principe suivant, bien connu de tous (ou pas ?) : les logiciels deviennent plus lents (bloatware, mal codés, etc.) plus vite que les ordinateurs deviennent plus performants et plus rapides.
En toute logique, les applications que l'on avait déjà il y a 20 ans (mail, traitement de texte, etc.) devraient être soit vraiment vraiment plus rapides, soit vraiment vraiment plus riches en fonctionnalités aujourd'hui qu'à l'époque. En pratique, certes on a plus de fonctionnalité, mais pas forcément tant que ça, et surtout on n'a pratiquement pas gagné en vitesse d'exécution de ces programmes. C'est un peu problématique, vous en conviendrez.
En fait, le problème vient aussi des langages de programmation que nous avons à disposition. Globalement, il y a deux options : * Coder en C (ou en C++ éventuellement), ce qui implique de se faire chier à un certain degré dès que l'on veut coder des trucs un peu complexes * Coder dans un langage interprété, par exemple Python, qui offre plein d'outils et de bibliothèques pour programmer simplement des applications assez complexes, mais finalement Python étant un langage interprété il n'est pas adapté non plus pour des projets qui doivent traiter une masse de données.
C'est pourquoi je suis sidéré aujourd'hui de voir que l'on a écrit Tribler, un client BitTorrent aux fonctionnalités certes révolutionnaires, mais en python quoi, bordel de merde ! J'avais à peine lancé le logiciel et effectué quelques recherches que celui-ci me bouffait quelques centaines de Mo de RAM. C'est absolument inadmissible, je n'ai que 2Go moi ! Au secours !
Dans le même genre, j'ai essayé plein de lecteurs de musique, et finalement la plupart étant écrits effectivement en Python, ils avaient tendance à ramer (un peu) quant à la gestion de ma bibliothèque, qui n'est pourtant pas si grosse que ça. (Enfin si, mais même : c'est normalement le propre de ces logiciels que de savoir gérer une collection importante de musique. Je me trompe ?). Mais ça dépend des logiciels, certains sont mal écrits, d'autres pas si mal, et j'ai plus ou moins fini par trouver une solution satisfaisante. Mais je me suis fait chier. Sous Windows, j’aurai tout simplement utilisé le Windows Media Player, et sous Mac OS X je me serai contenté d'iTunes, qui niveau fonctionnalités et vitesse d'exécution sont franchement satisfaisant, le principal défaut étant celui que vous êtes tous là à me pointer du doit - ce sont des logiciels privateurs.
Mais les fautifs dans l'histoire, ce sont peut-être les langages de programmation eux-même : il est difficile (voir impossible, et même s'il existait, alors il est bien trop peu connu) de trouver un langage qui réunisse les avantages suivants : * Rapidité d’exécution (ce qui implique globalement qu'il soit compilé, éventuellement JIT) * Retour rapide pour le développeur (temps de compilation nul ou négligeable, ce qui n'est pas le cas avec C, C++, Vala, etc.) * Facilité d'écriture (orienté objet, ramasse-miettes, librairie standard fournie, syntaxe pas trop lourde). Remarquez que cela n'implique pas pour moi que le langage n'est pas typé, au contraire, je défend le typage fort pour imposer un peu de rigueur chez le programmeur. Mais même, on peut faire un langage qui soit plus facile à utiliser tout en étant assez fortement typé. * Possibilité de s'intégrer avec la majorité des bibliothèques C ou C++ dont tout le monde à besoin (GTK ou QT, bibliothèques multimédia, etc.)
Du côté du grand public, vu que de toute évidence les logiciels libres ne sont pas prêts, il est tout à fait naturel que les utilisateurs préfèrent les solutions privatrices bien connues de tous. Pourtant, le but du logiciel libre n'était-il pas de permettre à tout un chacun (même les plus incompétents et imperméables à l'informatique) de reprendre le contrôle de son PC ? J'aurai tendance à dire : RMS fail. Mais ça n'engage que moi (comme tout cet article, d'ailleurs).
Du côté des développeurs, l'esprit qui règne dans la communauté des logiciels libre n'est pas vraiment satisfaisant, comme je l'ai déjà dit, chacun voulant avancer dans son coin à faire son projet avec ses idées et la méthode qui lui parait à lui la plus satisfaisante (parfois d'un point de vue qui ne prend en compte que ce qu'il connaît déjà, donc voilà quoi). Il en résulte donc que pour l'instant, on est dans un plutôt gros merdier (c'est franchement pas très agréable) qui n'a pas l'air d'avancer beaucoup.
Déjà, il faudrait que tout le monde se rende compte qu'il y a un problème. On pourrait en discuter un peu sérieusement, plutôt que de troller (enfin ceci dit je n'ai pas dit que troller c'est mal, d'ailleurs je suis probablement moi-même en train de troller, et c'est une bonne chose car ça me permet de dire ce que j'en pense. Là où il y a un problème, c'est quand le débat n'avance pas et qu'il en résulte de la merde).
Déjà, moi je pense qu'il faudrait que tout le monde s'impose de coder bien, proprement, avec rigueur, etc. Le problème, c'est que parmi les gens que je fréquente (comprendre : parmi les autres élèves de prépa maths/physique), même parmi ceux qui s'intéressent à l'informatique et à la programmation, aucun ne semble avoir le goût du code bien écrit, ni la clarté d'esprit requise pour coder bien. C'est dommage. Et ce n'est pas notre prof d'informatique qui aide à développer ça. C'est dommage aussi.
Sinon, sur un ton plus radical, et c'est ce que j'aurai bien envie de faire - malheureusement, tout seul je ne vais pas aller bien loin - il y aurait la possibilité de faire table rase et de concevoir un nouveau système d'exploitation, basé sur un nouveau langage de programmation (ou deux éventuellement, si on veut séparer le vraiment bas niveau, c'est à dire le noyau, les périphériques, et les systèmes de fichiers, et le moins bas niveau, ce qui semble effectivement logique ; mais essentiellement toutes les applications seraient alors écrites avec le langage de haut niveau, qui sera de toute façon totalement optimisé aussi bien pour les performances que la facilité d'écriture), le tout étant planifié à l'avance pour avoir une cohésion globale, c'est à dire qu'il faudrait, à défaut d'imposer le totalitarisme au développeur, au moins débattre et décider une fois pour toute de comment le système sera organisé, et ensuite gérer le projet de manière à n'accepter que le code qui suit cette organisation - et accessoirement, qui satisfait des critères de bien-écriture que l'on définira aussi à ce moment. Mais c'est peut-être un peu utopique (voir beaucoup), donc voilà, globalement je ne sais pas si on peut faire grand chose.
Plop.
Un petit mot pour anoncer au gens que j'ouvre ici un blog, parce que j'en avais envie. Il s'agit d'un blog à écriture publique, c'est à dire que n'importe qui peut poster en créant un compte. Je modère les posts merdiques, bien entendu. Mais si vous venez pour critiquer le capitalisme, discuter de questions métaphysiques, annoncer vos exploits de programmation, partager vos lectures de manga, ou autres sujets potentiellements intéressants, je vous en prie.
Commençons donc par les modifications que j'ai apportées au code du site :
Ce qu'il reste à faire :
Désolé, mais je n'ai pas vraiment le temps de poster aujourd'hui. Je serai bientôt de retour avec un billet scientifique/philosophique/anarcho-communiste/geek/otaku/autre.