(copie de ma dépêche sur linuxfr)

RapydScript est un langage qui se compile en JavaScript, avec une syntaxe et des fonctionnalités qui se veulent proches de Python. Pour ceux qui connaissent coffeeScript, RapydScript est pareil mais inspiré par la lisibilité de Python. Il ne s'agit pas d'une nouvelle tentative de faire tourner Python dans le navigateur, comme par exemple Pyjamas. RapydScript reste du JavaScript, il n'introduit aucune limitation ni surcoût. Il paraît juste plus propre et donne l'impression d'écrire du Python.

Ses quelques fonctionnalités :

  • comme CoffeeScript, RapydScript répare les incohérences et inconsistances de JavaScript ;
  • un système de classes similaire à Python ;
  • support des listes en compréhensions ;
  • des exceptions comme en Python ;
  • des modules, plus flexibles que les modules Python
  • des arguments optionnels pour les fonctions, comme en Python
  • des décorateurs (sans arguments)
  • un système d'héritage plus puissant que celui de Python et plus clair que celui de JavaScript
  • le support d'objets (dictionnaires) avec fonctions anonymes, comme en JavaScript
  • la possibilité d’appeler n'importe quelle fonction, méthode, code JavaScript ou appel au DOM de n'importe quel framework, sans syntaxe spéciale
  • le choix entre les méthodes et fonctions à la Python ou leurs équivalents JavaScript
  • RapydScript s'auto-compile, c'est à dire que le compilateur est lui-même écrit en RapydScript et compile en JavaScript.

Les liens:

Voici un court exemple qui utilise JQuery :

class Popup:
    def __init__(self, containterId):
        # pop-up class will give us absolute position, high z-index and center the container
        self.$popup = $('#' + containerId).addClass('pop-up').mouseout(def():
            self.hide() # unlike 'this', 'self' will reference the object itself
        )
        self._$darkbg = $('#dark-bg') # overlays background with a dim layer to draw focus to the pop-up
    def show(self):
        self._$darkbg.show()
        self.$popup.show()
    def hide(self):
        self._$darkbg.hide()
        self.$popup.hide()

msg = Popup('my-popup')
msg.show()

Notons toutefois quelques limitations :

  • le source mapping n'est pas implémenté, mais l'auteur compte le faire ;
  • pas shell (repl) non plus, mais l'auteur le souhaite également ;
  • RapydScript a quelques bugs connus.

1 Installation

Comme d'habitude avec les applications Node.js, on utilise npm :

npm install rapydscript -g

2 Bibliothèque standard

Il est assez facile de faire tourner un code Python existant dans le navigateur car RapydScript a ré-implenté quelques bibliothèques standard de Python. Par exemple si vous utilisez range, print, ou list.append, il vous suffit d'importer la stdlib.js de rapydscript. Soit par un import explicite dans votre HTML, soit par la ligne import stlib dans votre code .pyj.

Il existe aussi le module math, re, unittest, random.

Mais si vous écrivez du nouveau code, il est conseillé de se baser sur les bibliothèques JavaScript existantes, plus fournies.

3 Exemples

3.1 Appel à javascript

Si jamais vous devez appeler directement du JavaScript à cause d'une limitation de RapydScript, vous pouvez le faire avec la fonction JS:

JS('module').exports # meilleur équivalent à JS('module.exports')

3.2 Définir des fonctions

Une fonction tout à fait classique en RapydScript :

#regular
def fibonacci(n):
    if n == 0: return 0
    elif n == 1: return 1
    else: return fibinacci(n-1) + fibinacci(n-2)
a = fibinacci(8)

l'équivalent en javascript:

function fibonacci(n) {
    if (n === 0) {
        return 0;
    } else if (n === 1) {
        return 1;
    } else {
        return fibinacci(n - 1) + fibinacci(n - 2);
    }
}
a = fibonacci(8);

Utiliser des fonctions anonymes :

# anonymous
math = {
    add:    def(a, b): return a+b;,
    sub:    def(a, b): return a-b;,
    mul:    def(a, b): return a*b;,
    div:    def(a, b): return a/b;,
    roots:  def(a, b, c):
        r = Math.sqrt(b*b - 4*a*c)
        d = 2*a
        return (-b + r)/d, (-b - r)/d
}

Des arguments optionnels comme en Python :

# with optional arguments
def get(item, quantity=1):
return [item for i in range(quantity)]
a = get('hammer')
b = get('nail', 3)

Ce qui produit le JavaScript suivant :

function get(item, quantity) {
    if (typeof quantity === "undefined") quantity = 1;
    return (function() {
        var _$rapyd$_Iter = range(quantity), _$rapyd$_Result = [], i;
        for (var _$rapyd$_Index = 0; _$rapyd$_Index < _$rapyd$_Iter.length; _$rapyd$_Index++) {
            i = _$rapyd$_Iter[_$rapyd$_Index];
            _$rapyd$_Result.push(item);
        }
        return _$rapyd$_Result;
    })();
}
a = get("hammer");
b = get("nail", 3);

// les deux fonctions utilitaires créées:
function range(start, stop, step) {
    if (arguments.length <= 1) {
        stop = start || 0;
        start = 0;
    }
    step = arguments[2] || 1;
    var length = Math.max (Math.ceil ((stop - start) / step) , 0);
    var idx = 0;
    var range = new Array(length);
    while (idx < length) {
        range[idx++] = start;
        start += step;
    }
    return range;
}
function _$rapyd$_print() {
    var args, output;
    args = [].slice.call(arguments, 0);
    output = JSON.stringify(args);
    if ("console" in window) console.log(output.substr(1, output.length-2));
}

L'usage de décorateurs (sans arguments) :

# and finally, decorated
def makebold(fn):
    return def():
        return "<b>" + fn() + "</b>"

def makeitalic(fn):
    return def():
        return "<i>" + fn() + "</i>"

@makebold
@makeitalic
def hello():
    return "hello world"

4 Écrire une chaîne de callbacks

On fait souvent appel à une suite de callbacks en JavaScript. C'est tout à fait facile en RapydScript :

params = {
    width:  50,
    height: 30,
    onclick:    def(event):
        alert("you clicked me"),
    onmouseover:    def(event):
        $(this).css('background', 'red')
    ,
    onmouseout: def(event):
        # reset the background
        $(this).css('background', '')
}

Pour plus de détails, voyez "chaining blocks" dans la documentation.

5 Autres outils

RapydScript est assez jeune et n'a pas autant d'outils que, par exemple, CoffeeScript, mais on commence à voir des extensions pour Django ou d'autres outils Node, comme Gulp ou Grunt, ce qui permet de l'intégrer facilement à son projet AngularJS ou autre.

5.1 un dé-compileur JavaScript->RapydScript

5.2 RapydFiddle pour partager du code en ligne

http://rapydscript.pyjeon.com/ (cliquer sur "démo")

5.3 gulp

https://github.com/vindarel/gulp-rapyd (utilisable mais pas fini)

5.5 extension pour Django

5.8 vim

https://github.com/atsepkov/vim-rapydscript (la configuration de l'auteur)

6 Conclusion

Nous n'avons pas expliqué tout le fonctionnement de RapydScript, pour cela il y a la bonne documentation. Nous espérons vous avoir fait miroiter de nouveau ce vieux rêve: écrire une application web dans un seul langage, en Python.