CoffeeScriptで配列宣言いじり倒し


CoffeeScriptって面白い宣言するなーと思ったので今回は配列に絞っていろいろやってみました。もしかするともっと面白い宣言があるかもしれないので、こんなのもあるよ!というものがあればぜひ教えてほしいです。

CoffeeScriptコード

array.coffee
# 基本形
arr0 = ["a", "b", "c"]

# カンマのみならず, 改行でも要素を区切れる
arr1 = [
  "a", "b", "c"
  "d", "e", "f"
  "g", "h", "i"
]

# カンマ+改行(任意回)でも一つの区切りとして認識
# 最末尾にカンマを入れてもOK
# カンマを複数回重ねるとNG
arr2 = [
  "a", "b", "c",
  "d", "e", "f",

  "g", "h", "i",
  # "j", "k", "l",,, <- NG
]

# 最初の要素は空白を開ける必要あり
# 2個目以降は空けなくてもOK
arr3 = [
 "a"
"b"
"c"
]

# 1から10までの配列
arr4 = [1..10] # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 逆向きも負の数もOK
arr5 = [10..-1]

# 小数点もいけるけど1.0ずつ増えていくため末尾の数値が表示されないことがある
arr6 = [0.1..3.0] # [0.1, 1.1, 2.1]

# 文字列は無理
arr7 = ["a".."z"] # [ "a" ]

# booleanでもいけなくはない
arr8 = [true..false] # [true, 0]
arr9 = [false..true] # [false, 1]
arr10 = [true..3] # [true, 2, 3]
arr11 = [true..-3] # [true, 0, -1, -2, -3]

コンパイル後

コンパイルを通すとjsファイルになります。これを見るとなぜ上の結果になるか丸わかり。

array.js
// Generated by CoffeeScript 1.9.1
(function() {
  var arr0, arr1, arr10, arr11, arr2, arr3, arr4, arr5, arr6, arr7, arr8, arr9, i, j, k, l, m, results, results1, results2, results3, results4;

  arr0 = ["a", "b", "c"];

  arr1 = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];

  arr2 = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];

  arr3 = ["a", "b", "c"];

  arr4 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

  arr5 = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1];

  arr6 = [0.1, 1.1, 2.1];

  arr7 = (function() {
    results = [];
    for (var i = "a"; "a" <= "z" ? i <= "z" : i >= "z"; "a" <= "z" ? i++ : i--){ results.push(i); }
    return results;
  }).apply(this);

  arr8 = (function() {
    results1 = [];
    for (var j = true; true <= false ? j <= false : j >= false; true <= false ? j++ : j--){ results1.push(j); }
    return results1;
  }).apply(this);

  arr9 = (function() {
    results2 = [];
    for (var k = false; false <= true ? k <= true : k >= true; false <= true ? k++ : k--){ results2.push(k); }
    return results2;
  }).apply(this);

  arr10 = (function() {
    results3 = [];
    for (var l = true; true <= 3 ? l <= 3 : l >= 3; true <= 3 ? l++ : l--){ results3.push(l); }
    return results3;
  }).apply(this);

  arr11 = (function() {
    results4 = [];
    for (var m = true; true <= -3 ? m <= -3 : m >= -3; true <= -3 ? m++ : m--){ results4.push(m); }
    return results4;
  }).apply(this);

}).call(this);

このfor文が肝ですね。

for (var i = "a"; "a" <= "z" ? i <= "z" : i >= "z"; "a" <= "z" ? i++ : i--){ results.push(i); }
// i++, i-- はNaNになるため、2回目の判定でfalseとなりfor文を抜ける

trueやfalseはインクリメント(デクリメント)しようとすると数値の1や0とみなされるからあのような結果になるのですね。