Journal FuncSug, encore un nouveau langage de programmation concurrent

Posté par  . Licence CC By‑SA.
Étiquettes :
13
20
mar.
2023

Ce langage est incomplet dans le sens où vous verrez souvent {js ...} qui permet d'inclure du code JavaScript.
Alors quel avantage a-t-il ? Mon but était de permettre une structure de code plus naturelle et plus lisible (Je sais, c'est subjectif).
Pour le voir, je propose de commenter très brièvement ici le code (simplifié) de l'aquarium.

La partie principale du code

{par
    *supplLifeOf
    (lifeOfFish 'Mérou' 0)
    (lifeOfFish 'Mérou' 1)
    (lifeOfFish 'Thon' 0)
    (lifeOfFish 'Thon' 1)
    (lifeOfFish 'Poisson-clown' 0)
    (lifeOfFish 'Poisson-clown' 1)
    (lifeOfFish 'Sole' 0)
    (lifeOfFish 'Sole' 1)
    (lifeOfFish 'Bar' 0)
    (lifeOfFish 'Bar' 1)
    (lifeOfFish 'Carpe' 0)
    (lifeOfFish 'Carpe' 1)
}

par est une instruction FuncSug permettant de lancer des blocs de code en parallèle.
*supplLifeOf permettra de rajouter dynamiquement des branches parallèles supplémentaires.

lifeOfFish est le nom d'une fonction (qui est définie avant dans le code, j'en parle juste après).

(lifeOfFish 'Thon' 0) appelle la fonction lifeOfFish avec les arguments 'Thon' et 0.

Ainsi, tous les appels de fonction lifeOfFish sont lancés et s'exécutent en parallèle.

Nous allons voir que lifeOfFish est une fonction qui fait naître le poisson et continue de s'exécuter jusqu'à sa mort.

La fonction lifeOfFish

Voilà le code de la fonction :

{deffunc lifeOfFish (p_race p_sexe)

    # naissance
    #==========

    # dessin du poisson, etc.
    .var thisFish <-- (drawNewFish 100 30 0)
    ...

    # après la naissance
    #===================

    {par @life

        # gestion des collisions
        #-----------------------
        {whileTrueAwaitFrame `

            // ---> Début de code JavaScript <---

            // collisions
            //-----------
            for (const otherFish of ...) {
                // Quand des poissons se rencontrent, ça génère une nouvelle naissance
                if (  colliObj(thisFish, otherFish)  ) {
                    sugBip('newBirth')
                }
            }

            // fin de vie si ...
            //------------------
            if (...) sugBreak('life')

            // ---> Fin de code JavaScript <---
        `}

        # gestion des naissances
        #--------------------------------
        {whileTrue
            # on attend un signal 'newBirth'
            :await newBirth beep
            # on ajoute une nouvelle branche parallèle branch dans le bloc 'par' qui a '*supplLifeOf'
            {spawn supplLifeOf
                (lifeOfFish $p_race 0)
            }
        }

        # mouvements du poisson
        #----------------------
        {whileTrueAwaitFrame `
            // ---> Début de code JavaScript <---
            thisFish.setAttribute('x', thisFish.x + thisFish.dx)
            thisFish.setAttribute('y', thisFish.y + thisFish.dy)
            // ---> Fin de code JavaScript <---
        `}
    }

    # mort
    #=====
        # suppression du poisson de l'aquarium
}

{deffunc lifeOfFish (p_race p_sexe) ...} permet de définir une fonction à deux arguments p_race et p_sexe.

.var maVariable <-- maValeur permet de déclarer une variable et de l'initialiser.

Après la naissance, le poisson gère plusieurs choses à la fois (c.-à-d. en parallèle) :

  • Les collisions avec les autres poissons
  • La naissance de ses enfants
  • Ses propres mouvements

Il y a donc une instruction par avec les trois blocs correspondants. @life est juste une étiquette pour pouvoir référencer le bloc par (notamment pour l'instruction ```sugBreak('life') qui interrompt le bloc).

L'instruction whileTrueAwaitFrame permet d'exécuter du code JavaScript à chaque rafraichissement d'écran. Dans ce code JavaScript, on peut utiliser sugBip pour lancer un signal FuncSug ou sugBreak pour interrompre un bloc FuncSug.

L'instruction {spawn monEtiquetteEtoile monNouveauBloc} permet d'ajouter dynamiquement monNouveauBloc dans le bloc par dont le premier élément est *monEtiquetteEtoile.

  • # L’aquarium

    Posté par  (site web personnel, Mastodon) . Évalué à 9.

    Si on m’avait dit à l’époque que l’exercice que j’avais créé pour montrer à un stagiaire qu’il y a des problèmes qui se modélisent « naturellement » avec des objets en Java mais que dans la réalité c’est pas si simple, serait encore utilisé presque 13 ans plus tard… ben je ne l’aurais pas cru :D

    Le plus drôle, c’est que je n’ai presque jamais vu d’implémentation du point 3.3 (là où ça ne devient plus « naturel » dans beaucoup de langages) et, à ma connaissance, aucun des points 4+.

    La connaissance libre : https://zestedesavoir.com

    • [^] # Re: L’aquarium

      Posté par  . Évalué à 4.

      Merci SpaceFox. :-)

      J'avais fait cet exercice parce qu'il me semble que l'implémentation dans FuncSug est nettement plus simple que dans les langages habituels.
      Je pense que cela est dû à ce que ce langage permet d'exprimer facilement le parallélisme logique.

      Je vais donc essayer de faire les points 3.3 et 4. ;-)

      • [^] # Re: L’aquarium

        Posté par  (site web personnel) . Évalué à 4. Dernière modification le 20 mars 2023 à 19:00.

        Je pense que cela est dû à ce que ce langage permet d'exprimer facilement le parallélisme logique.

        J'avoue.

        J'ai écrit

        {par
            {while [ 1 = 1 ] .print 1}
            {while [ 1 = 1 ] .print 2}
        }
        

        Et j'ai bien eu mon alternance de 1 et 2 dans la console sans avoir à me prendre la tête avec des histoire de threads ou de await.

        La détection et la terminaison des boucles infinis, c'est une feature ou une limite de l'interpreteur ?

        • [^] # Re: L’aquarium

          Posté par  . Évalué à 2.

          La détection et la terminaison des boucles infinis, c'est une feature ou une limite de l'interpreteur ?

          J'ai oublié de retirer le mode debug dans l'interpréteur. J'avais mis une limite arbitraire pour faciliter mon développement.

    • [^] # Re: L’aquarium

      Posté par  . Évalué à 0.

      J'ai continué l'exercice avec le point 3.3.

    • [^] # Re: L’aquarium

      Posté par  . Évalué à 0.

      Tel que je l'ai fait, les poissons hermaphrodites opportunistes ne changent de sexe que lorsque les deux poissons ont l'âge de procréer.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.