読者です 読者をやめる 読者になる 読者になる

レガシーコード生産ガイド

私に教えられることなら

Parenscriptメモ

&key

&keyを使ったコードは、引数が次のように変換される

        var _js48 = arguments.length;
        for (var n47 = 1; n47 < _js48; n47 += 2) {
            switch (arguments[n47]) {
            case 'parent':
                parent = arguments[n47 + 1];
                break;
            case 'child':
                child = arguments[n47 + 1];
                break;
            case 'children':
                children = arguments[n47 + 1];
                break;
            case 'text':
                text = arguments[n47 + 1];
            };
        };

(key value key value key value)の配列とみなして、セットで処理していくみたいだ。

そんなに大量な引数になることは無いと思うけど、もしボトルネックになったらマクロで先に展開した方が良さそう。

関数版

    (defun create-element (type &key parent child children text)
      (let ((element (chain document (create-element type))))
        (when text   (inner-value element text))
        (when parent (append-to element parent))
        (when child  (append-to child element))
        (when children 
          (mapcar (lambda (child) (append-to child element)) children))
        element))

    (defvar e1 (create-element "div" :text "hoge"))

展開結果

    function createElement(type) {
        var _js132 = arguments.length;
        for (var n131 = 1; n131 < _js132; n131 += 2) {
            switch (arguments[n131]) {
            case 'parent':
                parent = arguments[n131 + 1];
                break;
            case 'child':
                child = arguments[n131 + 1];
                break;
            case 'children':
                children = arguments[n131 + 1];
                break;
            case 'text':
                text = arguments[n131 + 1];
            };
        };
        var parent;
        var child;
        var children;
        var text;
        var element = document.createElement(type);
        if (text) {
            element['innerHTML'] = text;
        };
        if (parent) {
            appendTo(element, parent);
        };
        if (child) {
            appendTo(child, element);
        };
        if (children) {
            mapcar(function (child) {
                return appendTo(child, element);
            }, children);
        };
        return element;
    };
    var e1 = createElement('div', 'text', 'hoge'); 

マクロ版

    (defmacro create-element-mac (type &key parent child children text)
      `(let ((element (chain document (create-element ,type))))
         ,(when text   `(inner-value element ,text))
         ,(when parent `(append-to element ,parent))
         ,(when child  `(append-to ,child element))
         ,(when children 
                (reduce 
                 (lambda (child ops) (cons `(append-to ,child element) ops)) children 
                        :from-end t :initial-value ()))
         element))

    (defvar e2 (create-element-mac "div" :text "fuga"))
    (defvar e3 (create-element-mac "div" :text "honi"))

展開結果

    var element;
    var element158;
    var e2 = (element = document.createElement('div'), (element['innerHTML'] = 'fuga', element));
    var e3 = (element158 = document.createElement('div'), (element158['innerHTML'] = 'honi', element158));

オブジェクトのプロパティの取得・設定方法

シンボルで操作する場合

    (defun awesome-function (x) x)
    (defvar ee (create))
    (setf (chain ee awesome-method) #'awesome-function) ; chainを使う
    function awesomeFunction(x) {
        return x;
    };
    var ee = {  };
    ee.awesomeMethod = awesomeFunction;

文字列で操作する場合

    (defun awesome-function (x) x)
    (defvar ee (create))
    (setf (getprop ee "awesome-method") #'awesome-function) ; getpropを使う
    function awesomeFunction(x) {
        return x;
    };
    var ee = {  };
    ee['awesome-method'] = awesomeFunction;

car, cdrは無い

javascriptの薄いラッパーなので、当然javascriptに無い関数は使えない。リストは配列になる。 (ps:ps-lisp-libraryにmapcarやreduceなどがあるけど)

なので'(("color" "#f00") ("background-color" "#00"))みたいなリストを渡して、 carやcadrで処理しようとしてもcarやcadrが無い。

マクロで展開してしまうか、javascriptのデータ操作方法に従うかする。

広告を非表示にする