メモを揉め

お勉強の覚書。

RubyのcombinationをSwiftでも使いたい

2016年9月15日追記

Swift 3.0 に対応させました。

memowomome.hatenablog.com

めちゃくちゃ久しぶりに Swift 触ったわ。。。

追記ここまで。

---

最近codeIQの問題にSwiftでもちょくちょく挑戦してます。
それまでRubyで解くことが多かったので、配列操作のあれが無いこれが無いといった感じで不便さを満喫しております。

combinationrepeated_combinationはその中でも特に良く使うのでSwift版を作りました。

all-user/swift_combination

stack overflowから拾ってきたコード

ググってたらすでに良い感じのコードがあった。
Rubyのrepeated_combinationと同じように動く。

stack overflow : Apple Swift - Generate combinations with repetition

func combos(var array: Array, k: Int) -> Array<Array> {
    if k == 0 {
        return [[]]
    }

    if array.isEmpty {
        return []
    }

    let head = [array[0]]
    let subcombos = combos(array, k - 1)
    var ret = subcombos.map {head + $0}
    array.removeAtIndex(0)
    ret += combos(array, k)

    return ret
}

シンプルで分かりやすいのですが、遅い。

再帰呼び出しを使って配列をちぎっては投げを繰り返しているので、大量に配列を扱うことになりコストが高くなっているのだと思います。

forループで書きなおす

forループで書き直したら約8倍速くなりました。

できるだけRubyと同じように使えるようにしました。
だったらRuby使えばいいじゃんていうね、ありがとうございます。

基本的な使い方

let a = [1, 2, 3, 4]

println(combination(a, 1)) // => [[1], [2], [3], [4]]
println(combination(a, 2)) // => [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
println(combination(a, 3)) // => [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
println(combination(a, 4)) // => [[1, 2, 3, 4]]
println(combination(a, 0)) // => [[]]
println(combination(a, 5)) // => []

配列のインスタンスメソッド

// Array method

println(a.combination(3))
// => [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]

引数にブロック(クロージャ)を渡す

// with closuer

a.combination(2){ println($0) }
// =>
// [1, 2]
// [1, 3]
// [1, 4]
// [2, 3]
// [2, 4]
// [3, 4]


let chrs = ["h", "e", "l", "o", "!"]
chrs.repeatedCombination(6){ combo in
    if join("", combo) == "hello!" { println(combo) }
}
// => [h, e, l, l, o, !]

Light Tableについて

Light Table使ってます。

Light Tableってどのくらい使われてるんだろう?
twitterのタイムラインを見てるとSublime TextとかAtom関連のつぶやきは良く見かけるけど、Light Tableの事はほぼ見ない印象。

なのでLight Tableのいいところを紹介します。

Evaluation(即時実行)

これがLight Table最大の特徴だと思うんですけど、エディタの中でcmd + enterを押すと即座にそのコードを実行出来ます。
実際に自分で試してみた範囲だと、

  • Java Script
  • Coffee Script
  • Ruby
  • HTML & CSS(タブの中でブラウザが起動できる、ライブリロード)

などを実行出来ます。他にも、

などたくさんのプラグインがありました。(これらは実際に試してないので、シンタックスハイライトだけの物もあるかも)

使い方はcmd + enterが基本です。
JavaScriptの場合はカーソルのある文やブロック、関数などの単位で実行されます。
eval_07_01
行単位で、もしくはより細かく選択した範囲のみを実行することも出来ます。

  • 行単位でeval!
    eval_07_02
  • 選択範囲でeval!
    eval_07_03
実行される範囲(JSの場合)
  1. カーソルのある行の先頭から、一つの式として値を評価できるところまでを実行する。
    行の途中でセミコロンがあるとそれ以降は実行しない。
    eval_01_01
    eval_01_02
  2. forブロック行にカーソルがある場合は、そのforブロックが実行される。
    eval_02
  3. 関数宣言行にカーソルがある場合は、関数宣言が実行される。
    eval_03
  4. 関数式の代入でも同じ。
    eval_04
  5. でも即時関数はなぜかブロック単位で実行されないので、選択してあげる必要がある。
    スコープを作るために即時関数で包む用途が多いから、敢えてそうしているのかもしれない。
    eval_05
関数の動作テスト

たとえばRubyCoffeeScriptなんかだと、

5行くらいの関数を書く→その場で実行してテストする

みたいな使い方を良くします。
とりあえずその場で動作を確認できるので相当便利です。

eval_08

どこでもプレイグラウンド

cmd + enterで実行出来るということは、いわば編集中のあらゆる場所でプレイグラウンドできちゃうということです。
ビルトインライブラリや言語の仕様など、しばらく触っていないとうろおぼえなことも多いですよね?そんな時すぐにその場で確認できるので超便利です。

0の真偽値ってどっちだっけ?って思ったら…

って確かめられるぅ。

  • JSのオーバーフロー
    eval_11
計算用紙

どこでもプレイグラウンドのように使えるということはすなわち、計算用紙の様に書捨ての計算をどんどん実行できるということです。
電卓のような感覚で気軽に計算できちゃう。

ブラウザの開発ツールみたいに使える

各種ブラウザの開発ツールのように使うことが出来ます。
Light Table内でブラウザを起動することで、そのページ上でJS、Coffeeのコードを実行することが出来ます。
これは次に紹介するWatch機能とも関連する部分です。

Watch(監視)

これはJS、coffeeでしか試してませんが強力な機能です。
おそらくRuby, Clojure, ClojureScriptでも利用出来ます。

基本的にはEvaluationと一緒ですが、あらかじめ選択しておいた範囲を監視して、
その部分が実行されると値を右に表示してくれます。

監視したい範囲を選択後、alt + wでWatch出来ます。

これをブラウザタブと連携して使うことで、強力なデバッガとして使うことが出来ます。 watch_01

たとえば、jQueryを使ってるサイトだと… watch_02 みたいな事もできる。

ltWatch関数(名前はなんでも良い)を作っておくデバッグ方法

あらかじめグローバルにltWatchという関数を定義する、
名前はLight TableのWatchで使うからltWatch

下のようなコードを別ファイルにして読み込ませておくと便利、他のコードより先に読み込ませる。
jQuery等他のライブラリを拡張する場合はそれより後)

ltwatch.js

 

function ltWatch() {

}

jq-ltwatch.js

 

//jQuery用
jQuery.fn.extend({
  ltWatch: function () {
    return this;
  }
});

空の関数を宣言しておいて、Watchしたいタイミングで中身を実装、Evaluationすることで上書きします。

監視したい対象のオブジェクトなり、変数なりをltWatch関数に渡しておけばこれを監視できます。
thisの値を監視するのも便利です。
jQueryメソッドチェーンの中身も覗くことができます。 watch_03
これ実はLight Tableに限らず、chromeとかのデバッガでもメソッドチェーンの途中にブレークポイントを設定できるようになるので便利です。

アニメーションの更新やイベントのコールバック関数を監視 watch_04

Coffee Script

そしてこれらの機能はすべてCoffee Scriptでも使えます(要プラグイン)。
Light TableでEvaluationするコード以外はちゃんとコンパイルしないと当然反映されないので、
gulpのwatchタスクでソースファイルを監視、コンパイルしながら使うと快適です。

watch_05

プラグインマネージャが便利

AtomやSublimeTextと同じようにプラグインマネージャがあって、簡単にインストール、アンインストール、アップデートができます。

見た目

良い。すごく良い。

好きではない所

ぐらいです。

最近の状況

最近は新しいプラグインが増えてない印象。
SwiftプラグインAtomでは速攻で出ましたよね。Light Tableでも出て欲しいナー(自分では作れない)。

追記: 2015/5/27

公式ページのリンクです。

Light Table

Ruby, RSpec, CoffeeScript, Node.js, gulp, browserify

もろもろはじめました。
何を書いていいのか分からなくなるので、メモはこまめに取らないとダメですね。

ザクッとした感想(雑感)

あれこれ悩んでいるより、とにかく触ってみるのが一番だなと思いました。
新しかったり、自分の知らない技術の紹介とかを見て、興味を持ったらとりあえずREADME.mdを読んで動かしてみると。
スティングフレームワークもタスクランナーも、ひとつ触ってみると俄然意味が分かるようになります。
というか今まで意味全然分かってなかったです、ありがとうございます。

  • Ruby
    • とにかく書いてて気持ち良い(JSと比べて)
    • リファレンスのメソッドとか見てるとこんな便利なものまで!(JSしか知らないので)
    • クラス、proc、スコープの範囲とかはなんとなくしか分からないのでこれから勉強します
  • RSpec
    • codeIQのある問題で使われていたのがきっかけ
    • テストってそれまでのイメージよりはずっと簡単に導入出来るんだなと思った
    • もっと早く使えばよかったです
  • CoffeeScript
    • Rubyをはじめたことで俄然興味がわいた
    • Rubyと同時にはじめたので文法がごっちゃになる(if文、Rangeオブジェクト、三項演算子など)
    • 個人的にはファットアロー(=>)でthisをバインド出来るのがめっちゃ嬉しい
  • Node.js
    • coffeeを使うためにようやくインストール
    • いままで散々見てきたpackage.jsonの意味がようやく分かった
  • gulp
    • coffeeを毎回コンパイルするの大変だなと思ったらやる気出てきた
    • 結局gruntはそのうち、そのうちでを使うことなかった
  • browserify
    • nodeのmoduleの概念が分かったことで何が有難いのかようやく理解

参考にした有難きリンクたち

ほんとに有難いです。

Dashが鬼神のごとく便利

紹介記事にすすめられるがままにインストールしていたDash。
いままで自分が設定したショートカットすら忘れるほどの頻度でしか使ってなかったのですが、新しい言語やフレームワークを使いはじめると必然的にリファレンスを読む機会が多くなります。そして、オフラインでいつでリファレンスが読めるのはやはりすばらしいです。
現在使ってなくても興味あるフレームワークはドキュメントをダウンロードしてあります。

試したいもの

JSテストフレームワーク

やらねば、と思いつつまだ触ってないものシリーズのうちのひとつです。
casper、mocha、jasmineのいずれかをまずは試してみます。

Jenkins、Travis CI

まず何をするものなのかがとても漠然としている状態、おじさんのイラスト。

Sass || Less || Stylus && Haml || Emmet || Jade

このへんもまだ手を付けていないんです、というかどれを使えばいいんだろ。
まずはなんでもいいから一個やってみるか。

LiveScript

CoffeeScriptを調べてた流れで当然出てくるわけです、でもまだこれは自分には早いようなきがしなくもない。

Swift

文法とかの解説記事をちょいちょい見ている、早く触ってみたいけどディベロッパープログラムに入ってないからまだ無理。
Yosemite出たらやってみよう。