Swift の勉強する環境を docker を使って構築する

docker で勉強する環境を作ってみた。

github.com

準備

リポジトリと README を見てもらえば分かるけど、下記のような bin/runスクリプトを用意する。

#!/bin/sh

if [ -n "$*" ]
  then docker run -v $(pwd):/app -w /app swiftdocker/swift $*
else
  docker run --privileged -it swiftdocker/swift swift
fi

使い方

REPL で試したい場合は bin/run を実行する。

$ bin/run
Welcome to Swift version 3.0-dev (LLVM 8fcf602916, Clang cf0a734990, Swift 000d413a62). Type :help for assistance.
  1>

終了するときは :exit を入力する。
*.swift を実行したいときは bin/run swift sample/hello.swift のように実行する。

$ bin/run swift sample/hello.swift
Hello, World!

Mac で docker-machine の IP を localdocker にしておくと捗る

Mac で docker を使うと、docker-machine の IP にアクセスするときが少し面倒です。
これを /etc/hosts を使って localdocker でアクセスできるようにしておくと便利って備忘録。

準備

まず、 /etc/hosts にこんな感じで書いておく。

127.0.0.1 localdocker

次に、下記のようなスクリプトを用意しておく。

  • up_localdocker
#!/bin/sh

eval $(docker-machine env default)
sudo sed -i '' "s/.*localdocker$/$(docker-machine ip default) localdocker/" /etc/hosts

使い方

docker-machine の再起動の後などにスクリプトを実行すれば環境変数/etc/hosts が更新される。

$ . up_localdocker

. up_localdocker と実行すれば IP が更新されます。

babel + remap-istanbul を使って、ES2015 のコードのカバレッジを計測する

表参道.rb #12【一周年】 で話したネタ。

全然アップデートできていない clairvoyance をちゃんと更新しようと、やる気を高める為に ES2015 で書けるように直した。

資料

やったこと

gulp + babel の環境構築

これは Web 上に資料がいくらでも転がっているので、楽。

clairvoyance
├ lib/
└ test/
  • gulp + babel の構築後
clairvoyance
  ├ lib/   # gulp build で src/lib から生成
  ├ test/  # gulp build で src/test から生成
  └ src/   # ES2015 のソースコード
    ├ lib/
    └ test/

こんな感じになるように環境作った。

ESLint (airbnb) の導入

ES2015 初心者なので、 ESLint を導入して、 airbnb の style に準拠して書くように設定した。
これも苦労せず、 web 上に資料がいくらでも転がっているので、普通に環境作れた。

あとは、 ESLint に指摘された箇所を 頑張って直す だけです。

カバレッジ計測

今まで使っていた istanbul だとカバレッジが計測できなくなったので、 remap-istanbul を使って直した。
これが一番苦労した。

# gulpfile.babel.js
gulp.task('build', ['clean'], () =>
  gulp.src('src/lib/**/*.js')
    .pipe(sourcemaps.init())
    .pipe(babel())
    .pipe(sourcemaps.write('../maps', {
        includeContent: false, sourceRoot: '../src/lib'
      }))
    .pipe(gulp.dest('lib'))
);

gulp.task('remap-istanbul', ['test'], () =>
  gulp.src('coverage/coverage-final.json')
    .pipe(remapIstanbul({
      basePath: 'maps/',
      reports: {
        json: 'coverage/coverage.json',
        html: 'coverage/lcov-report',
        lcovonly: 'coverage/lcov.info',
      },
    }))
);

こんな感じで設定したら動いた。 Current Directory がよく分からんけど、色んなパターンで設定を試したところ、これで動いた。

備考

ブログ書いていたときに見つけたけど、 babel 向けのカバレッジツールもあるみたい。

github.com

codecov とか使えるか検証してないけど、もしかしたら remap-istanbul を使うより楽かも。

最後に

あまり参考になりそうにないブログだけど、 babel + remap-istanbul を使う人の参考に何かなれば幸いです。
詳しく設定内容などを知りたい人は GitHubリポジトリを見てください。

github.com

Ruby でメソッドがどこで定義されているか調べる方法

byebug で辿っても良いけど、これはこれで便利なのでメモ。

method(:byebug).source_location
#=> ["/Users/sinsoku/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/byebug-8.2.5/lib/byebug/attacher.rb", 29]

参考

class Method (Ruby 2.3.0)
http://docs.ruby-lang.org/ja/2.3.0/class/Method.html

Gemfile を指定して RSpec を実行する方法

毎回、忘れて困るのでメモ。

bundle install

$ bundle install --gemfile=gemfiles/rails_5.gemspec

BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle install でも動くっぽい。

bundle exec

$ BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle exec rspec

参考

Bundler: The best way to manage a Ruby application's gems http://bundler.io/v1.3/bundle_config.html

try! Swift に参加しました

遅くなったけど、 3/2(水)〜4(金) で try! Swift という Swift のカンファレンスに参加していたので、感想とか書いてみました。

セッション

Swift 初心者から上級者まで参考になる話がいくつも発表されていました。*1

Swift 界隈のツールの話、 Swift コミュニティの話、iOS アプリ開発で使えそうなコード例などが紹介されていました。 また、「Sketchでアイコンを作る方法」や「デザイナーを巻き込む方法」など実践的な Tips の発表もありました。

同時通訳

英語のプレゼンには同時通訳があり、発表内容を日本語で聞くことができました。
また、登壇者に質問できるQ&Aルームでも同時通訳をして頂け、日本語の質問を英語に、英語の回答を日本語で聞くことができました。

無料コーヒー、軽食、ランチ

スタバのコーヒー、ジュースが継続的デプロイされていました。 あと、サラダラップなどの軽食、お弁当などもあり、飲食関連がかなり充実していました。

プロトコル指向

個人的に新しいパラダイムだと思って期待していたけど、try! Swift で話を聞いても結局よく分かりませんでした・・・ 誰かの発表で「具象型ではなく、プロトコルに依存させて・・・」みたいな例があったけど、すごいデジャヴを感じた。

あと、「プロトコル拡張で実装をプロトコルに持たせて Mixin する」とか Ruby で何年も前からあるし、いまいち良さが分からん。
ただ、さすがにそれだけで プロトコル指向 !!! とか名乗らないと思うので、他にもメリットあって自分が気付いてないだけだとは思うけど・・・

Swift らしさ

プロトコル指向はよく分からないけど、 try! Swift の話を聞いていると、下記要素を使うと Swift らしさが出そう。

  • struct を使う
  • 具象型じゃなくて protocol に依存させる
  • ジェネリクスを使う
  • enum を使う
  • パターンマッチを使う
  • Optional を使う

一通り基本的な使い方は覚えているけど、まだ慣れていないので、もっとコードを書いて自然に扱えるようになりたい。

英語

RubyKaigi のときも感じたけど、カンファレンスで英語できないエンジニアのコミュ力はゼロになりますね。
ただでさえコミュ力が少ないので、これ以上下がらないように英語は覚えておきたいと思いました。


今回は Swift 初心者だったので、次回の try! Swift 2017 までにレベル上げてから参加したいですね。
あと、英語力もあげたい。

*1:私は Swift 初心者なので、上級者の気持ちは推測です

プロトコル拡張で条件をつけたり、特定のプロトコル拡張のメソッドを呼ぶ方法

Swiftプロトコル拡張の動きが気になったので調べた結果を備忘録として残しておく。

プロトコル拡張で条件を定義

特定プロトコルの場合だけ挙動を変える。

protocol A {}
protocol B {}

extension A {
    func say() {
        print("A")
    }
}
extension A where Self : B {
    func say() {
        print("B")
    }
}

class User: A, B {}
class Author: A {}

User().say() // B
Author().say() // A

プロトコル、クラスのどちらが優先されるか?

クラスが優先された。

protocol A {}
protocol B {}

extension A {
    func say() {
        print("A")
    }
}
extension A where Self : B {
    func say() {
        print("B")
    }
}

extension A where Self : User {
    func say() {
        print("User")
    }
}

class User: A, B {}
class Author: A {}

User().say() // User
Author().say() // A

プロトコル拡張のメソッドを呼ぶ

プロトコルにキャストすれば呼べる。

protocol A {}
protocol B {}

extension A {
    func say() {
        print("A")
    }
}
extension A where Self : B {
    func say() {
        print("B")
    }
}

extension A where Self : User {
    func say() {
        print("User")
    }
}

class User: A, B {
    func say() {
        (self as A).say()
    }
}
class Author: A {}

User().say() // A
Author().say() // A