sibilant

ちょっと癖のあるnode.js上のlisp->jsトランスレータ
http://sibilantjs.info/#welcome

combinationsとか作ってみた。

(puts '(1 2 3 4))
(puts (append-map '(1 2 3 4) (lambda (x) (list x (* x x)))))
(puts (combinations (list 1 2 3 4) 2))

result

sibilant -x combinations.sbl
[ 1, 2, 3, 4 ]
[ 1, 1, 2, 4, 3, 9, 4, 16 ]
[ [ 1, 2 ]
, [ 1, 3 ]
, [ 1, 4 ]
, [ 2, 1 ]
, [ 2, 3 ]
, [ 2, 4 ]
, [ 3, 1 ]
, [ 3, 2 ]
, [ 3, 4 ]
, [ 4, 1 ]
, [ 4, 2 ]
, [ 4, 3 ]
]

original

以下のコードを渡してjsのコードを生成している。

(defmacro import (module)
  (concat "var " module " = " "require" "(\"" module "\");"))

(import sys)

;;;
(defun erase (xs e)
  (select xs (lambda (x) (!= x e))))

(defun append-map (xs fn)
  (defvar r [])
  (each (x) (map xs fn)
        (setf r (r.concat x)))
  r)

(defun combinations (xs n)
  (if (= n 1)
      (map xs (lambda (x) (list x)))
      (append-map xs (lambda (x) 
                (map (combinations (erase xs x) (- n 1))
                     (lambda (y) (cons x y)))))))

(defun puts (obj)
  (sys.puts (sys.inspect obj)))

;;;
(puts '(1 2 3 4))
(puts (append-map '(1 2 3 4) (lambda (x) (list x (* x x)))))
(puts (combinations (list 1 2 3 4) 2))

js

var sys = require("sys");
//
var erase = (function(xs, e) {
  // xs:required e:required
  return select(xs, (function(x) {
    // x:required
    return (x !== e);
  }));
});

var appendMap = (function(xs, fn) {
  // xs:required fn:required
  var r = [  ];;
  map(xs, fn).forEach((function(x) {
    // x:required
    return r = r.concat(x);;
  }));
  return r;
});

var combinations = (function(xs, n) {
  // xs:required n:required
  return (function() {
    if ((n === 1)) {
      return map(xs, (function(x) {
        // x:required
        return [ x ];
      }));
    } else {
      return appendMap(xs, (function(x) {
        // x:required
        return map(combinations(erase(xs, x), (n - 1)), (function(y) {
          // y:required
          return [ x ].concat(y);
        }));
      }));
    };
  })();
});

var puts = (function(obj) {
  // obj:required
  return sys.puts(sys.inspect(obj));
});

//
puts([ 1, 2, 3, 4 ]);

puts(appendMap([ 1, 2, 3, 4 ], (function(x) {
  // x:required
  return [ x, (x * x) ];
})));

puts(combinations([ 1, 2, 3, 4 ], 2));