ぴよログ

↓に移転したのでこっちは更新されません、多分。

一発当てるより健康が欲しい

最近エンジニアとかWeb的な文脈であれやこれやと色々見かける中で「一発当てたい」というのを見つけたが、それについて僕が思ったことは

である。

不健康(病気、怪我、メンタル)なときは仕事のこととかはどうでもよくなって何もやりたくなくなる。HPは黄色になるしMPもほぼゼロになる。健康あっての仕事だと思うので一発当てるよりも健康を獲得して安定した生活をおくるほうが僕にとっては重要度が高い。すでに健康極まりないって人は好きなことをやればいいので、一発狙うなりなんなりすればいいと思います。

いわゆる不健康自慢

あとはただの不健康自慢ということで不健康ツイートを最新からさかのぼっていってみる。

多分娘から映った。目が痒いです。

エアコンが効いた部屋にいるとときどき鼻水とくしゃみが止まらなくなることがある。最近知ったんだけどどうやらこれはアレルギーの一種らしい。風邪に直結するわけではなさそうだった。

口内炎は口の中を噛んだわけでもないのに頻繁にできる上、一度できると1週間以上苦しむことになる。食事は人生において最も楽しいことの一つだと思っているので、その食事を著しく制限する口内炎は本当に最悪。

体重は順調に減っていて、最近は記憶にある中で最低クラスの57kg台に突入しようとしている。原因は運動しないことによる筋力の低下だと思われる。会う人会う人痩せた?と聞いてくるのですごく心配になる。

このへんは確か浜松Ruby会議直前に高熱を出し、その結果収まっていた喘息をぶり返して1ヶ月近く苦しんでいたときのツイートだと思う。大人になってから喘息を発症したけど本当に辛い。これから秋、冬になっていくとまた症状があらわれる可能性があるから注意せねば。

また口内炎について書いてる。口内炎パッチ、もう少し安くならないかな…。

ツイートしてない中でもいっぱいあって、例えばまさに今日は腰が痛すぎて整体に行ったし、約一ヶ月前には夜中に吐いてしまい、妻を起こして夜間救急に連れて行ってもらったこともあった。

腰が痛いとか筋肉が減るとかはプログラマの職業病みたいなところがあるわけで、じゃあ体動かせばいいじゃんて話になるわけだけど、急に運動すると具合悪くなるのが常なのよね。

なんか悲しくなってきたので終わりにする。

ヘルシープログラマ ―プログラミングを楽しく続けるための健康Hack

ヘルシープログラマ ―プログラミングを楽しく続けるための健康Hack

MPが足りない

今日はMPが足りなくて仕事ができないなーなどと思っていたらちょうど最近MPに関する記事がライフハッカーに載ってバズってたみたいでタイムリーだなーと思った話。

僕もはてブしました。

[L] 時間が足りないのではなく、MPが不足して何もできないとき | Lifehacking.jp

まさに今MPが足りない。こういう時は消化すべきタスクリストとかがあると何も考えずに進められるんだけど、そうでもないときは本当に困る。

2015/08/25 12:28

MPが足りないとは

MPが足りないっていう表現はよく同僚とか妻にもしていた。僕はやる気が出ないとか、新しいことを始める意欲がないとか、気がすすまないとかそんなような意味あいで使っていた。

MPが足りないときには企画を考えるとかアイデアを出すとか、システムのアーキテクチャを考えるといったようなこと、言い換えると創造力が必要なことができない感じがする。逆にバグを直すとか、画面のレイアウトを少し修正するといった小さいタスクをこなすのは容易にできる。

頭を働かせることはできないが、ちょっと手を動かせば片付くような仕事はサクっと片付くという印象がある。ちょっとしたタスクをこなしている分には能率の低下は感じない。ザコ敵はMPが足りなくてもHPさえあればどんどん倒していけるわけ。

原因

どんなときにMPが足りなくなるのか。言い換えるとどんなときにやる気や意欲、想像力がなくなるのか。

  • 体調を崩す(HPも足りない)
  • 嫌なことを言われる
  • Appleにリジェクトされる
  • 睡眠不足
  • 子どもがめちゃくちゃ機嫌悪い

など。もっと色々ある気がするけどあまり覚えていない。

AppleのリジェクトはものすごくMPを消費する、というか奪われる。まっとうなリジェクトでもテンションが下がるのに、半分ぐらいはレビュー担当者がちゃんと見ていないとか最初のリジェクトで一度に指摘してくれれば済んだのにとかって事態だとものすごいダメージになる。

同じアプリで何回もリジェクトされると「もういいわ〜」みたいな気持ちになる。いや良くないんだけど、そうなってしまう。

対策

今日の昼にMPを回復しようとして考えた。

大抵の場合は寝るのが良い気がする。睡眠不足のときってクリエイティブなことができないイメージがある。

運動も良さそう。あまり好きではないし膝が悪いからやらないんだけど、ランニング(ジョギング?)なんかは頭がすっきりしそうな気がしている。書籍「のうだま」でも読んだけど、運動をするとやる気を呼び起こす「淡蒼球」という部位が刺激されるらしいし、きっとそうなんだろう。それに運動すると気持ちがいいし。

Emacsとかブラウザの拡張とかを探し回るのはとても楽しいがあまり生産的な活動ではないので普段はやらないようにしている。かといって新しいものを何も導入したいのではつまらないので、MPが足りなくていまいち生産的ではないタイミングであえて新しい拡張機能を探したりするようにしている。今日はEmacsにスクロール関係の拡張を入れた。ツールが新しくなると使いたくなって仕事に戻れることもある。

あと、最初のライフハッカーの記事のブコメで瞑想がどうのって言ってる人がいたから少し調べてみた。

change-life.hatenablog.com

瞑想の状態ってのはよくわからないけど、ランニングしてると頭がクリアになることがあったからそれに近いのかなという気がしている。あの状態を運動せずに作れるなら楽かもね。

サボり?

MPが足りないとか言ってサボりじゃないかみたいな議論は起こりがちだと思うけど、やはり人間気が向いたときにやったほうが能率がいいしできるものも良くなると思う。少しぐらいダラダラしたっていずれMPが回復してフロー状態(ゾーン)のように仕事をできるといがきて挽回できるわけだし。

終わりです。

のうだま―やる気の秘密

のうだま―やる気の秘密

Yosemiteで日本語入力が遅い問題が解決

昨年末にMacbook Pro 15inchに買い替えてからOS X Yosemiteで日本語入力が遅い問題にずっと困っていたのを、さっきおこなった対策で直せた気がするのでメモしておく。

まず、以前試していて少し改善したのがこれ。

Excel2011で日本語入力のスピードが極端に遅い | Apple サポートコミュニティExcel2011で日本語入力のスピードが極端に遅い | Apple サポートコミュニティ
フォントの重複が起こるのをFont Bookから解消するという話。

これでよくなった!と思っていたらそんなことはなくてしばらくすると再発するというのを繰り返していた。

特定のソフトというのは、ブラウザや一部のエディタ(Atomなど)、Evernoteなど。ATOK PadEmacsのように遅くならないエディタもあった。

今日もいつものように「Yosemite 日本語 遅い」などとググっていくうちにこの方のブログに辿り着き、

アクセシビリティの設定で、次のようにアクセシビリティの設定で「コントラストを上げる」「透明度を下げる」の設定をONにすると解決しました。

このような対策をして解決したことがわかった。

www.downtown.jp

ちなみにこの方、数記事に渡って色々な対策をしていくのを書いてくれているので、同じような問題に直面している身としては解決策を知るだけではなく途中経過も追えて良かったと思う。

コントラストを上げる」「透明度を下げる」の対策後は問題のあったソフト上での日本語入力も問題なくできるようになった。ようやく解消してよかったという気持ちでいっぱいだが、もうすぐ新しいバージョンのOS Xが出るんだよなと思うと、また別の問題が起こりそうで面倒だ。いつもはすぐにインストールしていたが、今回はアップデート数回分待つぐらいのことはしてもいいかもしれない。

ところで、「コントラストを上げる」を選ぶと画面の雰囲気がそこそこ大きく変わる。

有効にする前(通常の見た目)はこれだが、

コントラストを上げるとこうなる。

でもすぐに慣れるので問題ないと思う。

SwiftでMicrosoft Azure StorageのAPIクライアントを書きました(書いてます)

最近はSwift版のMicrosoft Azure StorageのAPIクライアントを書いている。

github.com

Microsoft Azure Storageを管理するようなMacまたはiOSのアプリを書きたくてSwiftObjective-Cで書かれたAPIクライアントライブラリを探したのだけれど、現時点ではそのようなものはないということがわかったのでSwiftを勉強しつつ自分で書くことにした(ここにそう書かれている→Microsoft Azure Storage Client Library for C++ v1.0.0 (General Availability) - Microsoft Azure Storage Team Blog - Site Home - MSDN Blogs

このクライアントを使って書いたMacアプリは現在申請中でレビュー待ち。というか一回リジェクトされてしまった。

そもそもなぜMacアプリを書く必要があるのか、そしてそもそもなぜAWSではなくAzureなのか、ということに答える必要があるかもしれないけど、今回はその点はスルーすることにする。

MS Azure Storage

(ここ、間違っていたらごめんなさい)

MS Azure StorageにはBlob、Queue、Table、Fileという4つのサービスの総称で、AWSと対応させると大体こんな感じになっている。

Azure Storage AWS 用途
Blob S3 ファイル
Queue SQS メッセージング
Table DynamoDB NoSQL
File (ない?) ファイル共有

今回書いているAPIクライアントはこれら4つのサービスのうちBlobとQueueに対応しようと考えていて、実際主要なAPIはある程度実装できたと思っている。

ちなみにAzure StorageのAPIリファレンスはこちら。

ストレージ サービス REST API リファレンス | Windows Azure のテクニカル ドキュメント ライブラリ

設計

Swift力不足のためAPIクライアントをSwiftでいい感じに書くにはどうしたらいいのか全く検討がつかなかった。そこで「Swift API クライアント」などと適当にググって調べらとてもいい記事を発見し、記事やサンプルアプリケーションを見て良い感じだなと思ったのでほぼそのままの設計で実装することにした。この記事に感謝します。

堅牢で使いやすいAPIクライアントをSwiftで実装したい

設計方針はこの3つだそう。

目標としたのは以下の3つの条件を満たすことです。

  • レスポンスはモデルオブジェクトとして受け取る (便利)
  • 個々のリクエスト/レスポンスの定義は1箇所で済ます (変更しやすくしたい)
  • リクエストオブジェクトはAPIクライアントから分離させたい

この記事を読んでいただければ僕のライブラリでやっていることも全部わかると思うが、一応簡単に設計について触れておく。

クライアントの主要コード

クライアントの主要メソッドcall擬似コードを載せてみる。

public class Client {
    public func call<T: Request>(request: T, handler: (Response<T.Response>) -> Void) {
        // ① 成功時の処理
        let success = { (task: NSURLSessionDataTask!, responseObject: AnyObject!) -> Void in
            let statusCode = (task.response as? NSHTTPURLResponse)?.statusCode
            switch (statusCode, request.convertResponseObject(responseObject)) {
            case (.Some(200..<300), .Some(let response)):
                handler(Response(response))
            default:
                let userInfo = [NSLocalizedDescriptionKey: "unresolved error occurred."]
                let error = NSError(domain: "WebAPIErrorDomain", code: 0, userInfo: userInfo)
                handler(Response(error))
            }
        }

        // ② 失敗時の処理
        let failure = { (task: NSURLSessionDataTask!, error: NSError!) -> Void in
            handler(Response(error))
        }

        // ③ リクエスト
        let manager = AFHTTPSessionManager()
        let url = scheme + "://" + host() + request.path()
        manager.responseSerializer = AFHTTPResponseSerializer()
        manager.responseSerializer.acceptableContentTypes = request.responseTypes()
        manager.GET(url, parameters: nil, success: success, failure: failure)
    }
}

③の部分は単にAFNetworkingの呼び出しなのでここでは特に触れない。通信のライブラリとしてはAFNetworkingを選択した。同じ作者が書いたSwift版のライブラリ、AlamofireのほうがSwiftらしく書けるのかもしれないけれど、一度も使ったことがなかったので今回はパスした。いずれ書き換えてみてもいいかもしれないと思っている。

次は短い②の部分だけど、これは単にエラーオブジェクトをcallに渡ってきたハンドラに返している。

最後の①はレスポンスが正常に返ってきたときの処理で、ステータスコードとレスポンスから正しくモデルオブジェクトに変換できたかどうかで処理を分岐している。

全体を見ると、個々のリクエストに必要な情報(メソッド、パラメータ、HTTPレスポンスから得たいモデルオブジェクトなど)はリクエストオブジェクトから取り出して使うようになっている。そのためクライアントのコードは全てのリクエストに共通の処理だけ書いておけば良い。

レスポンス

クライアントのcallメソッドに渡すハンドラにはResponse<T>が渡ってくるようになっている。このResponseは値付きenum(というのかなんというのか…?)になっていて、成功時はリクエストオブジェクトが持つレスポンスの型に対応したモデルオブジェクトが、失敗時にはNSErrorを持っていることになる。

public class Wrapper<T> {
    public let value: T
    
    init(_ value: T) {
        self.value = value
    }
}

public enum Response<T> {
    case Success(Wrapper<T>)
    case Failure(Wrapper<NSError>)
    
    init(_ value: T) {
        self = .Success(Wrapper(value))
    }
    
    init(_ error: NSError) {
        self = .Failure(Wrapper(error))
    }
}

クライアントの呼び出し側はこのようになる。response: Response<T>でSwitchして成功時、失敗時の処理をしてあげる感じになる。

client.call(AzureQueue.ListQueuesRequest(), handler: { response in
    switch response {
    case .Success(let wrapper):
        println(wrapper.value) // AzureQueue.ListQueuesRequest.Response
    case .Failure(let wrapper):
        println(wrapper.value) // NSError
    }
})

リクエストオブジェクト

さっき書いたようにリクエストオブジェクトには個々のHTTPリクエストで必要な情報を個別に定義して、クライアントから使えるようにしてある。

参考にした記事では

  • パス
  • メソッド(GET,POSTなど)
  • モデルオブジェクトへの変換
  • モデルオブジェクトへの型

などが書かれていたが、Azure Storageのクライアントではさらに、

  • リクエストBody
  • 追加のHTTPヘッダー(BodyのContent-Lengthなど)
  • HTTPレスポンスのContent−Type

あたりを追加している。

public class ListQueuesRequest:  Request {
    public let method = "GET"

    public typealias Response = Collection<Queue>

    public init() {}

    public func path() -> String {
        return "/?comp=list"
    }

    public func body() -> NSData? {
        return nil
    }

    public func additionalHeaders() -> [String : String] {
        return [:]
    }

    public func convertResponseObject(object: AnyObject?) -> Response? {
        return ResponseUtility.responseItems(object, keyPath: "Queues.Queue")
    }

    public func responseTypes() -> Set<String>? {
        return ["application/xml"]
    }
}

Promise版の呼び出し

ここまで書いたことでAPIクライアントとしての機能は大体果たせるようになった。

ところでJavascriptなんかではよくあるように、非同期処理を待ってから次の非同期処理を書こうとするととても書きにくいという問題が、Objective-CSwiftAPIクライアントを書くときにも現れる。これはまあ放っておいてもいいのだけど使うときに便利なほうがいいと思ったので試しに対応してみることにした。

SwiftでもJavascriptのPromise的なアプローチを使えることができると知っていたので調べてみたところ次のようなライブラリが候補に挙がった。

決め手はなんだったかよく覚えていないが、上に挙げた3つのライブラリを全て試してみて最終的にBrightFuturesを採用してみた。

実装の際に参考にしたリンクはこちら。

BrightFutures版のクライアント

public class Client {
    public func future<T: Request>(request: T) -> Future<T.Response, NSError> {
        let promise = Promise<T.Response, NSError>()

        // ① 成功時の処理
        let success = { (task: NSURLSessionDataTask!, responseObject: AnyObject!) -> Void in
            let statusCode = (task.response as? NSHTTPURLResponse)?.statusCode
            switch (statusCode, request.convertResponseObject(responseObject)) {
            case (.Some(200..<300), .Some(let response)):
                promise.success(response)
            default:
                let userInfo = [NSLocalizedDescriptionKey: "unresolved error occurred."]
                let error = NSError(domain: "WebAPIErrorDomain", code: 0, userInfo: userInfo)
                promise.failure(error)
            }
        }

        // ② 失敗時の処理
        let failure = { (task: NSURLSessionDataTask!, error: NSError!) -> Void in
            promise.failure(error)
        }

        // ③ リクエスト
        let manager = AFHTTPSessionManager()
        let url = scheme + "://" + host() + request.path()
        manager.responseSerializer = AFHTTPResponseSerializer()
        manager.responseSerializer.acceptableContentTypes = request.responseTypes()
        manager.GET(url, parameters: nil, success: success, failure: failure)

        // ④ Futureオブジェクトを返す
        return promise.future
    }
}

通常版と変わったのはcallメソッドにハンドラを渡さなくなり、代わりにFutureというオブジェクトを返すようになったことで、レスポンスが返ってきたときにはハンドラにモデルオブジェクトやエラーを渡す代わりにPromiseオブジェクトのsuccessfailureメソッドを呼ぶようになっている。

BrightFutures版を使う側のコード

例えば、

  1. Queueの一覧を取得した後で、
  2. Queueを新しく生成し、
  3. 次にそのQueueを削除する

というAPI呼び出し(意味はないが)をしたいとき、通常版ではこのようになる(ひどすぎる…)。

func onError(error: NSError) {
    println(error)
}

func normal() {
    let req1 = AzureQueue.ListQueuesRequest()
    queueClient.call(req1, handler: { response in
        switch response {
        case .Success(let wrapper):
            let req2 = AzureQueue.CreateQueueRequest(queue: "brandnewqueue")
            self.queueClient.call(req2, handler: { response in
                switch response {
                case .Success(let wrapper):
                    let req3 = AzureQueue.DeleteQueueRequest(queue: "brandnewqueue")
                    self.queueClient.call(req3, handler: { response in
                        switch response {
                        case .Success(let wrapper):
                            println("Success!!")
                        case .Failure(let wrapper):
                            self.onError(wrapper.value)
                        }
                    })
                case .Failure(let wrapper):
                    self.onError(wrapper.value)
                }
            })
        case .Failure(let wrapper):
            self.onError(wrapper.value)
        }
    })
}

BrightFutures版では煩雑さは残るものの幾分かマシに書けるようになる。

func promise() {
    let req1 = AzureQueue.ListQueuesRequest()
    queueClient.future(req1).flatMap { response -> Future<AzureQueue.CreateQueueRequest.Response, NSError> in
        let req = AzureQueue.CreateQueueRequest(queue: "brandnewqueue")
        return self.queueClient.future(req)
    }.flatMap { response -> Future<AzureQueue.DeleteQueueRequest.Response, NSError> in
        let req = AzureQueue.DeleteQueueRequest(queue: "brandnewqueue")
        return self.queueClient.future(req)
    }.onSuccess { response in
        println(response)
    }.onFailure { error in
        println(error)
    }
}

煩雑さの原因になっているflatMap { response -> Future<AzureQueue.CreateQueueRequest.Response, NSError> inのようなクロージャの型の部分だが、これを省略してしまうと現状のXcode6.4ではambiguousとか言われてコンパイルできなかった。PromiseKitなどでも同じように見えるエラーに出会ったのでこのあたりはSwiftXcodeの進化が必要なのかな。

とにかく、これでAPI呼び出しを順番にしたいという要求にも一応答えられるようになった。

あとPromise系のライブラリはそれぞれ進化が速いらしい。すぐに色々変わってしまうかもしれない。

テスト

プロジェクトをCocoaPodsのpod lib createで生成したらデフォルトでQuickというテストライブラリが入ってきたのでそのままこれを使った。Quickでのテストは書いたことがなかったが参考になるコード(後述)が見つかったのであまり苦労することはなかった。

テストはできるだけ書いておきたいと思ったものの、APIクライアントはAPIサーバーあっての話なのでテストはどうしようか迷って色々試した結果、今のように実際のAzure環境を使ったテストに落ち着いた。

Nocillaでスタブ?

最初はNocillaというライブラリを使ってスタブしてテストを書こうと思ったが、マッチポンプ的あまり意味がない気がしたのでこれは却下することにした。

なお、Nocillaを使おうとして色々調べているときに見つけたサンプルコードがQuickでテストを書くときにも訳にたったので紹介しておく。

Azure Storage Emulator

次に試そうとしたのはWindowで動かすことができるAzure Storage Emulatorを使うことだ。ざっくり言うとAPIサーバーのエミュレータをローカルに立てられるというものらしい。ということはこれをMacに入れたVMWareとかで動かしておけばテストに使えるんじゃねーか(少なくともローカルでは)と考え色々準備してみた。

ところがクライアントの接続先にVMWareのIPを指定してもどうにもうまくいかない。3時間近く奮闘したものの何も得られなかったのでこの作戦も却下することに。

実環境でテストする

ここでようやく他の言語のクライアントではどうしてるんだろうということに気がついたので、Railsで使ったことがあるRuby版のクライアントを見てみることにした。

Azure/azure-sdk-for-ruby

これのテストコードを見ると環境変数にストレージのアカウントやアクセスキーが設定されているときだけテストを動かせるようになっていた。つまり本物のAzure環境でテストを動かすよ、ということのようだった。

そういうわけでSwift版でも同じようにAzure環境でテストを動かすコードを書くことになった。テストコードを書くにあたってBrightFutures版が非常に役に立った。これをしてそれをして、最後にあれをしたらこうなっている、というコードを通常版で書こうとしていたらだいぶ辛いことになっていたと思う。

コード

もう1回貼っておきます。

github.com

宣伝

途中に出てきた表は自作のMacアプリで作りました。日本語入力で若干不具合があるけどMarkdownで表を書くときにはWebにある表生成ツールMarkdown Tables generator)よりも便利なのでぜひどうぞ。

Table2Text (Markdown, CSV)
カテゴリ: 開発ツール, ユーティリティ

詳解 Swift

詳解 Swift

XcodeでiOSシミュレータがサイズごとに2つずつダブって表示されたのを直した

タイトル通りなのだが、気がついたらこんな感じでiOSシミュレータがたくさん並んでいて気持ち悪かったので直した。

Devicesを開く

まずXcodeのメニューからDevicesを開く。WindowDevices、またはCmd+Shift+2

左ペインのデバイス一覧からダブっているものを削除

ダブっているもののうちどちらを消しても実質違いはないと思うんで、適当に選びながらDeleteキーで削除していく。

おわり

わーい直った。

SwiftでN文字ずつに分割した文字列を得る方法

例えば"hogefugapiyo"という文字列があるとして、これを4文字ずつに分割するなら["hoge", "fuga", "piyo"]、5文字ずつに分割するなら["hogef", "ugapi", "yo"]を得たい。

Rubyであればscanメソッドを使って次のように実行できるということがわかった。

str = "hogefugapiyo"
# => "hogefugapiyo"

str.scan(/.{1,5}/)
# => ["hogef", "ugapi", "yo"]

参考

Ruby 文字列を任意の文字数に分割する - Qiita

これと同じことをSwiftでやりたくなったが、どうやら全く同じようなことをする関数はなさそうに見えた。なのでSwift力が足りないながらも自前で書いてみたのでそれを晒してみる。

Rubyの用にArrayを返す関数を追加するのでもよかったが、SequenceTypeを使うほうがよさそうな気がしたので↓のように実装した。Stringsubstr(Int)という関数を生やして、それを呼ぶとforループやmapとかが使えるという感じになった。

extension String {
    var length: Int { return count(self) }
    
    internal class SubstringGenerator: GeneratorType {
        typealias Element = String
        let count: Int
        let string: String
        var i = 0

        init(count: Int, string: String) {
            if count <= 0 {
                fatalError("'count' must be bigger than 0.")
            }
            self.count = count
            self.string = string
        }
        
        func next() -> Element? {
            if i < string.length {
                var endIndex : String.Index
                if i + count > string.length {
                    endIndex = string.endIndex
                } else {
                    endIndex = advance(string.startIndex, i + count)
                }
                
                var range = advance(string.startIndex, i)..<endIndex
                i += count
                return string.substringWithRange(range)
            } else {
                return nil
            }
        }
    }
    
    internal class SubstringSequence : SequenceType {
        let count: Int
        let string : String
        typealias Generator = SubstringGenerator
        
        init(count: Int, string: String) {
            self.count = count
            self.string = string
        }
        
        func generate() -> Generator {
            return Generator(count: count, string: string)
        }
    }
    
    func substr(count: Int) -> SubstringSequence {
        return SubstringSequence(count: count, string: self)
    }
}

このsubstrを実際に使ってみるとこうなる。

for substr in "hogefugapiyo".substr(5) {
    println(substr)
}
// hogef
// ugapi
// yo

var array = map("hogefugapiyo".substr(5)) {$0}
println(array)
// [hogef, ugapi, yo]

どうですかね、これ。

詳解 Swift

詳解 Swift