• [^] # Re: Trou de mémoire

    Posté par (site web personnel, Mastodon) . En réponse au lien Go 1.18 Beta : la généricité enfin !. Évalué à 2.

    Je comprend bien ce que sont les interfaces et les types génériques.
    Mais le problème n'est pas tant que le code soit plus ou moins compliqué, ça dépend vraiment des cas, mais le fait qu'il crée une dépendance.
    Si c'est un tri par exemple c'est bénéfique car une fois bien codé on n'y touchera plus, et surtout on n'ajoutera jamais de fonctionnalité.
    En revanche si on passe à un niveau plus élevé, comme dans mon cas d'une lib qui génère un pdf, c'est bien plus délicat car il y a potentiellement des fonctionnalités qui vont s'ajouter et impacter tout le monde (problème classique des dépendances et de l'héritage).

    Je ne vois pas de fermeture dans l'exemple que tu donnes par contre ?
    J'en vois sur l'exemple de sort.Slice où la fonction less utilisera probablement un tableau en dehors.

    people := []struct {
     Name string
     Age int
     }{
     {"Gopher", 7},
     {"Alice", 55},
     }
    sort.Slice(people, func(i, j int) bool { return people[i].Name < people[j].Name })

    L'intérêt des fermetures est de faire en sorte que l'algo central ne dépende d'aucun type particulier, même pas un type générique mais de la plus petite interface possible, par exemple func(i, j int) bool. Le code dépendant du type est dans la fonction avec fermeture et propre à chaque utilisation et donc en dehors de la lib.
    Dans mon cas par exemple j'ai un tableau composé de lignes composées de cellules.
    Il me faut faire un pdf de tout ça.
    L'algo appelle chaque cellule et lui demande son rendu, pour ça une interface Rendu marche très bien. La où ça devient casse tête c'est quand une des cellules a besoin de ses cellules voisines pour calculer son rendu, par ex cellule 2 = cellule 0 + cellule 1
    En Python la méthode Rendu de la cellule un = cellule.parent.cellules[0] + cellule.parent.cellules[1]
    En Go tintin car cellule.parent.cellules[x] correspondra simplement à une cellule ayant l'interface Rendu. Il faudrait éventuellement faire un cast et perdre l'intérêt du typage statique, ce que je ne voulais pas.
    Avec les fermetures la méthode rendu de ma cellule est appelée avec l'index de la ligne et c'est avec cet index que je vais chercher les cellules voisines (donc un tableau en dehors de ma méthode). Je n'ai même plus besoin de cellule.parent.

    Bref, avec cette méthode de fermeture mon code de lib est réduit au strict minimum en manipulant uniquement des indexes, par rapport au Python où je pouvais me permettre de manipuler directement les lignes et cellules mais avec un code de lib du coup beaucoup plus complexe. Autrement dit je préfère dans certains cas un code de lib plus simple et déplacer ce qui est complexe au niveau de l'application. Parfois c'est l'inverse (tri par ex).

    Avec le générique en Go il y aura moyen de se rapprocher de ce que l'on peut faire avec du typage dynamique. Avec par exemple un tableau qui contient des lignes de type T défini au niveau de l'application. C'est sûrement ce que j'aurai fait s'il y avait eu du générique à l'époque au lieu d'essayer la méthode avec fermeture que je préfère finalement pour ce cas de figure.

    Je sais pas si je suis clair, c'est vraiment difficile à décrire...