Journal Retour d'expérience avec le langage J

36
23
août
2013

Sommaire

Bonjour Nal,

je vais te parler d'un langage que je me suis mis à apprendre ce mois d'août. Son nom c'est J tout court. Il s'agit d'un langage spécialisé dans la manipulation de tableaux multidimensionnels à l'aide d'une notation très compacte, descendant d'APL. Il n'y a qu'une seule implémentation, dont la version 701 a été libérée sous GPLv3 en 2011, mais des licences commerciales sont aussi possibles. Il s'agit d'un langage interprété, pensé pour une utilisation intéractive exploratrice même s'il permet aussi une certaine modularité pour faire des programmes plus gros.

Soyons honnêtes, au début on a parfois l'impression qu'il s'agit juste de code offusqué, ou d'un simple jeu. Pour dire, j'ai failli renoncer malgré mon habitude des notations en tant qu'étudiant mathématicien. Cependant, une fois habitué à la philosophie du langage j'ai fini par changer d'avis, d'où ce journal :)

Un petit tour avec J

Maintenant je vais essayer de donner un petit avant-goût de cet étrange langage.

Un peu d'arithmétique

C'est parti :

    2 + 3
5
    2 4 + 1 3
3 7

+ se généralise donc tout seul aux listes, mais aussi à un tableau de n'importe quelle dimension. Et la plupart des fonctions se généralisent de façon analogue:

    2 ^ 0 1 2 3 4
1 4 8 16

Alors bon, c'est bien tout ça, mais d'autres langages comme Scilab ou Octave permettent des choses similaires. Là où J se démarque vraiment c'est dans sa grammaire exotique.

Tout d'abord, l'évaluation est extrêmement simple : pas de priorité parmi les opérateurs, + et * sont logés à la même enseigne :

    2 * 2 + 3
10

Il faut donc lire 2 * ( 2 + ( 3 ) ). On peut bien sûr mettre des parenthèses pour changer le destin :

    (2 * 2) + 3
7

Du vocabulaire

Et là c'est la surprise : au lieu de parler de variables ou fonctions, on parle de noms et de verbes. En fait, on rencontre des adverbes, des conjonctions, et même des gérondifs! Pourquoi ces noms fantaisistes? Parce qu'un programme J est composé de phrases et que ce vocabulaire donne une image assez fidèle de la réalité.

Adverbes, conjonctions

Regardons l'adverbe / pour se faire la main:

    +/ 1 2 3     NB. 1 + 2 + 3 (après NB. c'est un commentaire)
6

On l'appelle « insère », et il s'agit bien de ça, il insère le verbe qui le précède entre les éléments. Ici 1 + 2 + 3. On peut l'appliquer à n'importe quel verbe. Prenons par exemple <. qui renvoie le plus petit parmi deux nombres.

    3 <. 2
2
    <./ 5 7 3 4
3

En gros, un adverbe est une fonction qui prend un verbe en argument et renvoie un nouveau verbe avec un nouveau comportement. Les conjonctions sont similaires mais prennent deux verbes ou noms en argument. Par exemple @: sert à composer deux verbes. Donc avec >: verbe qui incrémente de un les éléments d'un tableau, */ @: >: est le verbe qui incrémente tout de un puis fait le produit des éléments.

Verbe monadique/dyadique

Jusqu'à présent, on a rencontré des cas de verbes dyadiques, c'est-à-dire qui prennent deux arguments. La plupart des verbes ont aussi un cas monadique, pour <. par exemple:

    <. 2.3  NB. partie entière : l'entier inférieur le plus proche
2

Comment définir ses propres verbes, noms,…

Le symbole =: qui permet d'assigner un nom, verbe, adverbe ou conjonction. Par exemple min =: <./ pour définir le verbe minimum, qu'on utilise simplement min 5 7 3 4 comme n'importe quel verbe.

Séquences de verbes (« verb trains » en anglais)

En J, une succession de deux ou trois verbes ou plus à la suite a un sens particulier. Un exemple classique avec trois verbes : calcul de la moyenne d'une liste de nombres. Le verbe # renvoie la longueur d'un tableau, et % est la division (/ est déjà pris!) :

    moy =: +/ % #
    moy 2 9 7   NB. (2 + 9 + 7) % 3
6

Où est la magie? Il s'agit d'une fourchette (fork) : si f, g et h sont trois verbes et y un nom, (f g h) y signifie (f y) g (h y). Ici on doit donc lire « la somme(f) divisée(g) par la longueur(h) ». Ces séquences permettent un style de programmation dit tacite, où on définit des fonctions sans faire référence explicitement aux arguments.

Le rang

Une notion importante : celle du rang (ou dimension). Dans les cas les plus simples il s'agit de décider si une somme se fait suivant les lignes ou les colonnes, par exemple:

    a =: i. 3 3  NB. matrice 3x3 avec les 9 premiers entiers
    a
0 1 2
3 4 5
6 7 8
    NB. + est « inséré » entre les lignes.
    +/ a
9 12 15
    NB. somme suivant chaque ligne (dimension 1)
    NB. On utilise la conjonction " appelée « rang »
    +/"1 a
3 12 21

Aller plus loin

Voilà, il reste une multitude de choses : calculs d'inverses, itérations à l'aide de la conjonction ^:, structures de contrôles (if-then-else,… et même while !),… mais l'esprit est là, il ne reste plus qu'à se plonger dans un des guides du wiki :)

Quelques remarques en vrac

Tout a l'air assez simple (j'espère), mais il y a un hic quand on apprend J : il y a plus d'une centaine de primitives (verbes, adverbes, conjonctions), qui s'écrivent à l'aide d'une seule lettre ou symbole, suivie parfois d'un ou deux . ou :, et même si souvent c'est mnémotechnique, pas toujours, et il m'a fallu un paquet d'heures pour les digérer avant de pouvoir comprendre le code des autres. Le pire c'est les fonctions pour intéragir avec le monde extérieur, qui s'obtiennent toutes grâce à la conjonction !:, par exemple 1!:1 est un verbe pour lire un fichier, aucun moyen de s'en souvenir, même si heureusement pas mal d'alias plus verbeux sont prédéfinis pour les tâches courantes.

Malgré les difficultés, c'est un langage sympathique, et la possibilité d'exprimer des algorithmes assez complexes, demandant dans un langage plus traditionnel plusieurs boucles, en une seule ligne, c'est quand même pratique. Bien sûr, il faut être capable de se relire après, et je n'y croyait qu'à moitié au début, mais c'est tout à fait possible en fait avec de l'entraînement. Un autre avantage est que toutes les opérations sur les tableaux sont très optimisées, donc on se retrouve avec du code très rapide à la fin, du moment qu'on applique les fonctions sur un maximum de données à la fois (pas de problèmes pour effectuer des opérations sur des tableaux avec des millions de valeurs).

La documentation du langage est assez particulière, puisqu'il s'agit d'un «dictionnaire», et le wiki officiel collectionne assez d'articles intéressants, et guides variés.

Une remarque concernant la licence : la version 701 de J est GPLv3, mais les binaires distribués sur le site officiel par contre viennent avec quelques autres trucs non libres (un IDE, des docs et des broutilles), donc il faut compiler soi-même. Sous Gentoo il y a un ebuild, mais j'ai pas l'impression qu'il y ait de package Debian, sans doute parce que le makefile n'est pas terrible, d'ailleurs l'ebuild Gentoo doit placer ça dans /opt/. Il y a aussi un petit problème mineur : le binaire s'appelle par défaut jconsole donc petit conflit de noms avec java.

La compilation est assez facile, il y a juste readline qui n'est pas activé par défaut : le plus simple c'est d'utiliser rlwrap.

Enfin, une petite mise en garde : apprendre J peut avoir des conséquences surprenantes, comme en témoigne ce petit extrait du fichier vt.c du code source C de l'interpréteur définissant le cas monadique du verbe {. qui renvoie le premier élément d'un tableau :

F1(jthead){I wcr,wf,wr;
 RZ(w);
 wr=AR(w); wcr=jt->rank?jt->rank[1]:wr; wf=wr-wcr;
 R !wcr||*(wf+AS(w))? from(num[ 0],w) : 
     SPARSE&AT(w)?irs2(num[0],take(num[ 1],w),0L,0L,wcr,jtfrom):rsh0(w);
}

C'est du C ça!? De quoi faire frémir Linus Torvalds ;)

  • # euh?!

    Posté par . Évalué à 2.

    Si jamais je vois un codeur qui utilise "*/ @: >:" comme code, je le pends par les c…

    / c'est map
    f @: g c'est x -> f (g(x))

    C'est quand même plus lisible !

    "La première sécurité est la liberté"

    • [^] # Re: euh?!

      Posté par (page perso) . Évalué à 3.

      Imagine f @: g @: h @: k, et compare avec f(g(h(k(x)))). Ça devient moins clair que c'est plus lisible. D'ailleurs en maths pour la composition on utilise un rond, et certains langages comme Haskell proposent un opérateur pour la composition (Ocaml aussi dans les batteries).

      Je te préviens, en J tu peux faire bien pire que ça ;)

      • [^] # Re: euh?!

        Posté par . Évalué à 10.

        Pourtant perl était un bon exemple à ne pas reproduire.

        Un code est bien plus souvent lu qu'écrit, gagner du temps à l'écriture, fait perdre un temps de malade ensuite.

        "La première sécurité est la liberté"

        • [^] # Re: euh?!

          Posté par . Évalué à 4. Dernière modification le 23/08/13 à 15:04.

          C'est une question d'habitude. Pour qu'un code fonctionnel soit lisible, il faut qu'il le soit pour quelqu'un qui est habitué à un code fonctionnel, pas impératif.

          J'aime bien le codé visuel de la composition de fonction, quand on écrit f (g (h x)) on le lit « f appliqué à g appliqué à h(x)", en écrivant f . g . h x on fait apparaitre le fait que f g et h sont combiné pour faire une nouvelle fonction, ça permet de on retrouver un peu le coté procédural, tout en étant plus compacte :

          x' = h x
          x'' = g x'
          return f x''
          

          petit ajout : ça dépend aussi de la syntaxe du langage, en pseudo lisp, il est évident que (f (g (h x))) est moins lisible que ((compose f g h) x)

          Please do not feed the trolls

        • [^] # Re: euh?!

          Posté par (page perso) . Évalué à 3.

          Les symboles vs les mots c'est une question de fréquence d'utilisation (personne ne se plaint du + ou du * par exemple), et avec J tu passes ton temps à utiliser les primitives donc la plupart rentre dans la catégorie « usage fréquent ». Certaines non, et c'est dommage, mais rien n'empêche d'un autre côté de se créer des alias : les fonctions trigonométriques utilisent la primitive o., je n'arrive pas à me souvenir de son utilisation donc je me suis fait des alias pour cos, sin, etc…

          Au moins avec J tu n'as quasiment pas de syntaxe : =: et =. pour l'assignement, et les parenthèses et c'est à peu près tout, le reste sont des fonctions qui suivent les règles du langage.

          • [^] # Re: euh?!

            Posté par . Évalué à 2.

            • et * sont surtout des symboles mathématique connu de tous. Mais remplacer '/' par '%', c'est fort quand même.

            "La première sécurité est la liberté"

            • [^] # Re: euh?!

              Posté par (page perso) . Évalué à 5.

              Je ne dis pas que quelqu'un qui connaît C (ou autre) va trouver ces symboles intuitifs, mais que quelqu'un qui programme en J finit par les connaître, et c'est l'important.

              Le / vient d'APL ou la division utilisait ÷, mais le problème avec les symboles non-ascii d'APL c'était qu'ils n'étaient pas pratiques à taper sur un clavier, mêmes s'ils étaient plus intuitifs et traditionnels (mathématiquement parlant). % était le symbole qui se rapprochait le plus et donc mnémotechnique pour les APListes.

              Ça prend un peu de temps, mais comprendre à fond la portée des primitives, leur sens, ce qu'elles font suivant leur rang qui détermine la manière dont elles agissent sur un tableau, les diverses façons de les composer, etc… prend beaucoup plus de temps que de se faire à la notation, et ce n'est finalement pas si important que ça: la plupart du temps où je restais bloqué pour comprendre un expression ce n'était pas parce que je ne me souvenais pas du nom informel du symbole (comme 'insert' pour /), mais plutôt de la façon exacte dont il se comportait par rapport à ses arguments, et que / s'appelle fold ou reduce ne change rien.

              Et puis il faut garder à l'esprit l'objectif principal du langage : une notation pour l'exploration intéractive d'algorithmes, donc c'est important de pouvoir faire loger suffisamment d'information sur une seule ligne. Il ne s'agit pas vraiment de faire de gros programmes, ni des systèmes critiques. Je ne sais pas si c'est possible, je n'ai encore fait aucun programme de plus d'une trentaine de lignes en J.

              Alors c'est vrai, c'est un langage un peu surprenant, et je réagissais pareil au début, mais je suis content de ne pas être passé à côté finalement.

        • [^] # Re: euh?!

          Posté par . Évalué à 9.

          Pourtant perl était un bon exemple à ne pas reproduire.

          Bon je suppose que c'est juste un bel appeau à troll (on est trolldi après tout). Mais bon, j'en ai un peu marre des gens qui disent que Perl c'est pas lisible.

          1. Perl n'est pas lisible uniquement si on n'écrit pas lisiblement. Comme C, comme C++, comme OCaml.
          2. Perl a une syntaxe et un vocabulaire. Un langage ou une langue, ça s'apprend. Sinon, perso je trouve que le Roumain, c'est pas lisible. En même temps, j'ai jamais cherché à apprendre la langue. Mais bon, ça s'écrit avec des caractères latins, c'est donc que ça doit être sensiblement pareil que le Français, non ?

          Oui, il y a quelques symboles particuliers à connaître en Perl, en particulier $_ (variable utilisée par défaut dans lors de l'itération sur une collection ou lors de la lecture d'un fichier), @_ (tableau des paramètres passés à une fonction), $! (errno), $(résultat d'une évaluation avec les backticks), $@ (erreur au retour de l'appel àeval) et pour certains cas très particuliers lors de traitements d'entrées/sorties$/` (séparateur de ligne, "\n" par défaut), et $| (E/S bufferisées ou pas). Il y en a plein d'autres. Mais perso je ne les utilise pas, et je les vois rarement employés.

          Pire: en tant qu'utilisateur de bibliothèques/modules Perl, les modules eux-même font souvent usage de plein de symboles, mais le code utilisateur lui se conte de bêtes my $instance = MON::MODULE->new(...); $instance->ma_methode(...);

          Bref, laissez mon Perl tranquille !

          • [^] # Re: euh?!

            Posté par . Évalué à 10.

            Pour Perl, comme pour J à vue de nez, je ne dirais pas que le code est lisible ou pas lisible. Je pense que comme tu dis, ça dépend beaucoup de qui code.
            Mais par contre, je dirais que là où par exemple Python oblige quasiment à coder très lisiblement, Perl offre la possibilité de réaliser parmi les pires délires d'obfuscation jamais imaginées, et plus généralement ne met que peu de contraintes au développeur sur la lisibilité du code.

            C'est un peu comme dire que Java c'est lent et lourd. C'est surtout que Java c'est "facile à apprendre" et très populaire. Un débutant peut rapidement faire un programme lent et lourd en Java, et décider qu'il n'est plus débutant vu que "ça marche".

          • [^] # Re: euh?!

            Posté par (page perso) . Évalué à 1.

            Si tu mets un programmeur qui ne connait pas Python devant un programme Python, il arrive en général à le comprendre (quoique les "list-comprehensions" ont un peu relevé le niveau). Tu n'a jamais cet effet là devant un programme Perl.

            Dans tout langage, tu peux écrire très lisiblement et de façon obtuse. Après, il y a la moyenne et le style encouragé par le langage. Perl clairement encourage un style cryptique pour qui ne parle pas le Perl. La même chose peut être dit du LISP, mais certainement pas du PHP, Java ou C#.

            • [^] # Re: euh?!

              Posté par . Évalué à 8.

              Je m'avance peut-être un peu, mais il me semble que le point commun entre Python, Java, PHP et C#, c'est une "relative" (j'insiste sur le relative..) similarité de la syntaxe, surtout quand on les oppose à Perl/LISP. Du coup, c'est un peu normal qu'ils apparaissent plus lisible pour un novice.

              Quand tu dis "un programmeur qui ne connait pas Python", quelles suppositions fais-tu sur les langages qu'il connaît?

            • [^] # Re: euh?!

              Posté par . Évalué à 4.

              Après, il y a la moyenne et le style encouragé par le langage. Perl clairement encourage un style cryptique pour qui ne parle pas le Perl.

              Il ne me semble pas que Perl encourage quoi que ce soit de cryptique. Aurais-tu des sources ?

              J’en ai une où Larry Wall dit au contraire qu’on utilise Perl comme on le veut : You Can Cuss in Perl.

              How you use the language is really based on things that are external to the language itself. So many computer languages try to force you into one way of thinking and Perl is very much the opposite of that approach.

            • [^] # Re: euh?!

              Posté par (page perso) . Évalué à 6.

              Dans tout langage, tu peux écrire très lisiblement et de façon obtuse. Après, il y a la moyenne et le style encouragé par le langage. Perl clairement encourage un style cryptique pour qui ne parle pas le Perl. La même chose peut être dit du LISP, mais certainement pas du PHP, Java ou C#.

              T'as des sources sur ce que t'avances ?

              J'ai en tout cas deux remarques à faire.
              La premières est que les dialectes Lisp (en tout cas pour Clojure et Emacs Lisp, c'est les seuls que j'étudie et pratique) ont une syntaxe extrêmement simple et encouragent clairement à coder de façon explicite. Je vois pas du tout pourquoi tu fais le rapprochement avec le perl, y a pas vraiment de rapport.

              Pour la deuxième : T'es sérieux ? Tu considères réellement que PHP encourage un style propre ? Parce qu'à chaque fois que je dois en faire et que je lis la documentation officielle, je me fais la réflexion inverse.

              Étant donné les langages que tu mets dans la seconde catégorie (qui ont tous une syntaxe de base assez proche, découlant du C) je pense surtout qu'il s'agit surtout d'une question d'expérience. Si effectivement tu n'as utilisé que des langages découlant du C le reste doit te sembler ésotérique. Joue un peu avec, tu verras que ça fait pas aussi peur qu'il n'y paraît.

              Et sinon, parce que je trouve sympa comme la chose est analysée, j'aime bien pointer vers cet article quand les gens débattent de la lisibilité du Perl :)

    • [^] # Re: euh?!

      Posté par . Évalué à 5. Dernière modification le 23/08/13 à 17:57.

      / c'est map

      Dans les autres langages ça ressemble plus à un fold.

      f @: g c'est x -> f (g(x))
      C'est quand même plus lisible !

      Pas du tout. C’est perdre tout l’avantage du point free, l’un des principaux apports de la programmation fonctionnelle, qui permet de réfléchir sur les fonctions plutôt que sur les données (voir la liste des avantages sur Wikipédia ou le HaskellWiki). D’autant qu’il s’agit d’un des points forts de J, inspiré des travaux de Backus.

      • [^] # Re: euh?!

        Posté par . Évalué à 0.

        "It helps the writer (and reader) think about composing functions (high level), rather than shuffling data (low level). "

        Le codeur moyen en est parfaitement incapable.

        f x = x + 1

        ==
        f = (+ 1)

        Franchement, cela rajoute quoi comme sémantique ? C'est exactement la même chose.

        "La première sécurité est la liberté"

        • [^] # Re: euh?!

          Posté par . Évalué à 5.

          Il ne s'agit pas vraiment de composition de fonction mais d'adopter un style pointless, c'est un peu plus fort.

          Franchement, cela rajoute quoi comme sémantique ? C'est exactement la même chose.

          Là oui, mais pour cet exemple :

          f x = let g = map (+1) x
                   in g
          
          f' = let g = map (+1)
                in g

          Certes, la sémantique est la même concernant les données, mais pas l'implémentation. La première implémentation f est bien plus lente que la seconde f'. Dans f le compilateur voit que la valeur de g dépend de x, et donc va créer la fermeture à l’exécution (à chaque appel). Dans f', on donne la "vrai" définition de f', c'est "la fonction qui prend une liste d'entiers et retourne la liste où chaque entier est incrémenté". Un compilateur malin va pouvoir "inliner" le (+1) dans le map et compiler du code optimal (dans ce cas simple).

          Please do not feed the trolls

          • [^] # Re: euh?!

            Posté par (page perso) . Évalué à 2.

            Dans le même ordre d'idée, en J certaines phrases idiomatiques dans un style tacite peuvent être optimisées par du code spécial.

            Par exemple avec l'adverbe \ (« préfixe ») qui applique un verbe aux préfixes d'un tableau :

                i.5 NB. 5 premiers entiers
            0 1 2 3 4
                <\i.5 NB. liste des préfixes chacun dans sa boîte
            ┌─┬───┬─────┬───────┬─────────┐
            │0│0 1│0 1 2│0 1 2 3│0 1 2 3 4│
            └─┴───┴─────┴───────┴─────────┘
                +/\i.5 NB. sommes cumulées
            0 1 3 6 10
            

            On pourrait penser que +/\ est en temps quadratique, mais le compilateur reconnaît cette composition classique du verbe + et des deux adverbes / et \ et produit du code efficace:

                NB. x: c'est pour les entiers de précision arbitraire
                x: +/+/\i.10^7 NB. somme des sommes cumulées jusqu'à 10 millions
            166666666666664984576
            

            et ça en 0.14s sur ma machine à 1.5Ghz.

            • [^] # Re: euh?!

              Posté par (page perso) . Évalué à 2.

              166666666666664984576

              Heu, le x: de mon calcul était stupide : passer en précision arbitraire après donne un résultat faux pour les derniers chiffres logiquement ;), donc c'est juste un flottant avec des chiffres faux vers la fin.

            • [^] # Re: euh?!

              Posté par . Évalué à 1.

              Encore une fois, ces bidouilles de langage sont là pour palier des défaut du compilateur. Reconnaitre l'usage de certaine forme d'opération et les optimiser, c'est la base d'un compilateur optimisant. Gcc va jusqu'à réécrire les nids de boucles pour les rendre plus régulière pour les vectoriser.

              "La première sécurité est la liberté"

              • [^] # Re: euh?!

                Posté par (page perso) . Évalué à 4.

                Ce que je voulais dire c'est qu'a priori il est plus simple pour un compilateur de faire des manipulations d'optimisation sur un code « algébrique », et reconnaître une combinaison de symboles plutôt que des structures complexes.

                Et je ne vois pas trop ce que tu veux dire avec ta première phrase : la combinaison d'adverbes /\ peut s'appliquer à n'importe quel verbe, et l'idée c'est de permettre son utilisation dans les cas complexes tout en ne perdant pas en vitesse dans les cas simples facilement optimisables, c'est donc une bidouille utile et facile à implémenter.

          • [^] # Re: euh?!

            Posté par . Évalué à 1.

            Vu que sémantiquement, c'est la même chose, le problème vient du compilateur. Rendre le code peut lisible, n'est jamais une bonne solution.

            "La première sécurité est la liberté"

            • [^] # Re: euh?!

              Posté par (page perso) . Évalué à 4. Dernière modification le 25/08/13 à 12:09.

              Je crois qu'on s'égare un peu. Ce que disait Zylabon était que certains codes étaient plus faciles à optimiser (ou du moins c'est ce que j'ai compris).

              Quant à la lisibilité du code, il faut juste je crois accepter que tout le monde n'en a pas la même notion, tout le monde ne travaille pas de la même façon et n'a pas les mêmes besoins, ce qui compte c'est d'être à l'aise avec son code et celui des gens avec qui on travaille, mais si d'autres travaillent ailleurs différemment, tant mieux pour la diversité. Personne n'est obligé de comprendre le code de tout le monde heureusement.

          • [^] # Re: euh?!

            Posté par . Évalué à 3.

            Je me répond à moi même pour me dire que mon exemple était particulièrement stupide, celui ci est bien mieux :

            {- f est ici redéfini à chaque appel de fib car le compilo (ghc 7.6.3 en O0)
               ne détecte pas que f ne dépend pas de n (le parametre de fib),
               en revanche en O2 il le détecte
            -}
            
            fib n = let f 0 = 1 
                        f 1 = 1 
                        f n = fib (n - 1) + fib (n - 2)
                    in f n
            
            {- pour fib' on explicite le fait que la définition (complete) de f est connue
               à la compilation, le compilo peut donc optimiser ça en 
               fib' 0 = 1
               fib' 1 = 1
               fib' n = fib' (n-1) + fib' (n-2)
            -}
            fib' = let f 0 = 1
                       f 1 = 1
                       f n = fib' (n-1) + fib' (n-2)
                   in f
            
            -- sur mon petit test à l'arrache, fib' 40 s'execute en 28 seconde, fib 40 en 55 secondes

            Please do not feed the trolls

  • # AAAHPL

    Posté par (page perso) . Évalué à 10.

    Je suis tombé sur "L'informatique, Larousse, 1976 (Encyclopoche Larousse)" chez un bouquiniste (50 cts) avec quelques exemples de code à la rubrique APL.

    J'ai fait des cauchemars pendant 2+2 3 nuits < jours ;)

  • # Licences libres donc commerciales

    Posté par . Évalué à 3.

    […] la version 701 a été libérée sous GPLv3 en 2011, mais des licences commerciales sont aussi possibles.

    La GPL autorisant l'utilisation du logiciel pour tous les usages sans restrictions et sa diffusion (sans s'intéresser à qui diffuse ni qui reçoit), elle permet le commerce. Donc la caractéristique des autres licences possibles n'est pas d'être commerciales, mais d'être payantes ou d'accorder des droits différents aux utilisateurs.

  • # PKGBUILD

    Posté par . Évalué à 1.

    Sous Gentoo il y a un ebuild, mais j'ai pas l'impression qu'il y ait de package Debian, sans doute parce que le makefile n'est pas terrible, d'ailleurs l'ebuild Gentoo doit placer ça dans /opt/. Il y a aussi un petit problème mineur : le binaire s'appelle par défaut jconsole donc petit conflit de noms avec java.

    Pour ma part, j’ai fait un PKGBUILD pour Arch Linux. Pour éviter le conflit, je renomme jconsole en j tout court. (Du coup, c’est pratique à entrer dans un terminal quand on veut s’amuser un peu. :p)

    • [^] # Re: PKGBUILD

      Posté par (page perso) . Évalué à 2.

      J'ai jc à la place de jconsole sous Gentoo. Ton message me fait penser que j'ai oublié de dire qu'il y a un dépôt git openj avec quelques modifications par rapport à la version de mars 2011, c'est peut-être celle que tu utilises. L'ennui c'est que ça a l'air un peu arrêté, et il y a une petite régression du 3/02/2012 sur les modulos pour les nombres complexes (ou « feature », mais quelques résultats me semblaient louches quand même). En tout cas c'est pas vraiment documenté, et trois tests unitaires ne passent plus chez moi.

Suivre le flux des commentaires

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