Swift for javascript cover?fm=jpg&fl=progressive&q=75&w=300

JavaScript開発者のためのSwift

今週の火曜日、サンフランシスコの Pubnub で行われた Swift Language User Group(#SLUG) で、JP Simard が、「 Swift for JavaScript Developers 」と題して発表を行いました。 JP は、まず Swift と Javascript における類似点と相違点についての説明から始め、2つの言語におけるクラス、コールバック、型安全、インターフェイスを含む8つの主要な概念に焦点を当てた発表がされています。スポンサーをしてくださった PubNubDeNA 本当にありがとう!

以下が、発表をスライドです。(Youtube動画とスライドは同期されてます) ぜひご覧ください!


Swiftについて (2:32)

この間の WWDC では、多くのデベロッパーが新しい言語 Swift の発表に驚かされたことかと思います。また、そのシンタックスが Javascript に似ていたことも驚いたことでしょう。しかし、それらの違いが徐々に様々な場面で姿を現してきたかと思います。たとえば、以下のコードは、Swift と Javascript の両方で動きます。しかし、その返り値は全く違ったものになります。

var strings = ["a", "b"] // => [a, b]
strings.reverse() // => [b, a]
strings[0] // => Swift: a, JS: b

似ているところ… (5:41)

シンタックスという点では、2つの言語は非常によく似ています。上記の通りに、全く同じコードが両方でコンパイル & 実行できます。Swift は、ツールとして REPL(Read-Eval-Print-Loop) という新しい機能を持っています。これにより開発者は、書いたコードの結果をリアルタイムで確かめることができるようになりました。REPL は、Swift をスクリプト言語のように思わせてくれます。

違うところ… (6:33)

Swift は、コンパイル言語です。また、もちろん API やライブラリ、フレームワークは、各プラットフォーム毎によって違います。 型安全とジェネリクスは、間違った型を使うことを未然に防ぎ、Swift をより安全なものにしています。また、Swift は元から関数型言語の性質を持っています。大きな違いとして、Swift は、バックエンドやブラウザ内で動作しません。それに、Swift をバックエンドで動かそうとすると多くの立ちはだかる壁がいくつかあります。

iOS/OSX 以外で Swift が使われるようになるためには… (9:48)

iOS/OSX 外で Swift が、使われるようになるためには3つの大きな壁があります。Swift のコンパイラ、ランタイム、標準ライブラリがオープンソースとして公開される必要があると思います。複数のプラットフォームをまたいで Swift が、使われるようになるには、Apple は、Swift ランタイムのコードを公開しなければならないのです。Objective-C の場合、これらのうちの2つ(コンパイラとランタイム)は、オープンソースとして公開されています。しかし、標準ライブラリは30年間、未だに公開されないままでいます。開発者が、複数のプラットフォームで Swift を使えるようにするには、Apple が Swift の標準ライブラリを公開するのを待つ必要があると思います。

REPL (12:17)

Node.js の REPL は、アルゴリズムのデバッグや何かアイデアを試す時、とても便利な機能です。Swift の REPL と Xcode6 の Playground は、手間がかかるコンパイルを走らせることなく、iOS/Mac 開発者にリアルタイムで実行結果を確認することを可能にしてくれました。

Demo (14:15)

Xcode6 の Playground でのデモを行います。”class” キーワードでクラスを作成し、いくつかのプロパティを追加していきます。Swift がかなりすっきりとしたシンタックスであることを皆さんにお見せできたことかと思います。

Swift と JavaScript における8つの概念 (21:35)

1. クラス (22:06)

記事の更新情報を受け取る

JavaScript には本当の意味でのクラスは存在しません。その代わりにプロパティを持つ関数をクラスとして使用します。

function Car(model){
  this.model = model;
}

Car.prototype.drive = function() {
  return 'Driving my ' + this.model;
}

var car = new car('Batmobile');
car.drive(); // => Driving my Batmobile

Swift のクラスでは、以下のようにプロパティとメソッドを追加できます。

class Car {
    var model = ""
    func drive() -> String {
        return "Driving my " + model
    }
}

let car = Car()
car.model = "Batmobile"
car.drive()

2. コールバック (23:21)

Swift と JavaScript においてシンタックスはとてもよく似ています。以下のコードは、log というログを出力する関数を定義してます。

var log = function(txt, done) {
  setTimeout(function() {
    console.log('callbacks are ' + txt);
    done();
  }, 1000)
}

log('awesome', function() {
  console.log('and done');
});

このような機能を定義するときは、Swift のコードの方が冗長になるようです。Swift と Javascript の違いの一つが、それぞれの API の違いにあることが分かるかと思います。

func log(txt: String, completion: () -> ()) {
    var delta = 1 * Int64(NSEC_PER_SEC)
    var time = dispatch_time(DISPATCH_TIME_NOW, delta)

    dispatch_after(time, dispatch_get_main_queue()) {
        println("closures are " + txt)
    }
}

log("not the same as JS closures") {
    println("and done")
}

3. プロミス (25:10)

Promise でラップすることは、再利用性を高める方法です。

var log = function(txt) {
  return new Promise((resolve) => {
    setTimeout(function() {
      console.log('promises are ' + txt);
      resolve();
    }, 1000)
  })
}

log('the future').then(() => {
  console.log('and done');
});

ここでも、Swift の方が冗長ですが、JavaScript のコールバックや Objective-C の blocks に似ていると感じるかと思います。

func log(txt: String, #resolve: () -> (), #reject: () -> ()) {
    var delta = 1 * Int64(NSEC_PER_SEC)
    var time = dispatch_time(DISPATCH_TIME_NOW, delta)

    dispatch_after(time, dispatch_get_main_queue()) {
        println("closures are " + txt)
        resolve()
    }
}

log("not the same as JS closures",
    resolve: {
        println("and done")
    },
    reject: {
        // handle errors
})

4. 型安全 と インターフェイス (26:38)

型安全とインターフェイスは、Swift でプログラムを書くときにバグが入り込むことを未然に防いでくれます。変数に値を割り当てるときなど Swift コンパイラが型の間違いを正してくれます。

let anInt = 3
let aFloat = 0.1416
var pi = anInt + aFloat // Compile warning

pi = 3 + 0.1416
// Compiles: number literals are untyped

5. タプル (30:42)

JavaScript でもお馴染みであるタプルは、複数の値を一つの変数にまとめておくことで、変数により多くの意味を持たせることができます。Swiftでは、タプルも同じように厳密に型指定されたものになります。

let http404Error = (404, "Not Found")
http404Error.0 // => 404
http404Error.1 // => Not Found

6. ミュータビリティ (31:39)

Swift は、この機能を JavaScript から持ってきました。Apple はこの辺りについて変更を加え続けています。Swift はまだ開発中の言語であり、ミュータビリティについてはまだ完全に決まっていません。Swift では、”var” キーワードはミュータブル, “let” キーワードはイミュータブルとなります。

var letter = "a"
letter = b // works

let a = "a"
a = "b" // compilation error

JavaScript において、 ”var” と “let” は共にミュータビリティであり、”let” は、制限されたスコープを与えてくれます。”const” キーワードがイミュータブルな宣言ができます( FireFox と Chrome だけでのみ)。それと他に JavaScript で変数をイミュータブルにする方法は、freeze() メソッドを使うことです。

var obj = {
  foo: "bar"
};

obj.foo = "baz"; // works
Object.freeze(obj); // freezes obj
obj.foo = "bar"; // silently does nothing

7. 関数型プログラミング (37:03)

JavaScript では、サードパーティのライブラリを使うことで関数型プログラミングのように書けるようになります。しかし、それは言語の機能ではありません。一方で、Swift は map や filter メソッドのような関数型性質をビルトインで持ってます。

let numbers = [1, 5, 3, 12, 2]
numbers.map {
    (number: Int) -> Int in
    return 3 * number
} // => [3, 15, 9, 36, 6]
numbers.filter {$0 % 2 == 0} // => 12, 2]

8. ジェネリクス (37:36)

Swift では、Generics が使えます。Optional 型は、変数が nil になることを許容するという意味になります。これは、JavaScript で言う undefined に似ています。以下で定義している OptionalValue は Swift の enum で Generics が使えることを示しています。

// Reimplement the Swift standard
// library's optional type
enum OptionalValue<T> {
    case None
    case Some(T)
}
var maybeInt: OptionalValue<Int> = .None
maybeInt = .Some(100)

// Specialized Array
var letters: [String]
letters = ["a"]

さらに (40:52)

Optional 型、enum、構造体、パターンマッチング、ランタイムなどまだまだここで説明できていない強力な機能が Swift にはあります。今見てきたように、Swift と JavaScript の大きな違いは、コンパイル言語、型安全に加えて、API の違いがありました。Swift は、シンタックス、ツールなど様々な概念を JavaScript から持ってきていることがお分かりいただけたことかと思います。

関連する情報 (42:44)

Q&A (44:40)

Q: 無名関数を引数として渡すことはできますか?
JP: 無名関数は、基本的にクロージャです。例えば、sort 関数は、ソート対象のオブジェクトとソートに用いるクロージャを引数としてとります。

Q: Swift と Objective-C は今後どうなると思いますか?
JP: Objective-C がすぐに無くなるとは思いません。だけど、Apple は、今後 Swift を優先的に考えていくと思います。

Q: 何かパフォーマスンの観点で違いはありますか? もしあるとするなら開発者にどのような影響を及ぼしますか?
JP: 実際、Swift はまだ完成していません。だから今、Swift と Objective-C のパフォーマンスの違いについて話すのは難しいことです。でも、Swift はかなり速くなるポテンシャルを持っていると思います。今のところそれらはまだ機能していません。

Q: Swift は Objective-C のサブセットですか? Swift に移行することで何か失うことはありますか?
JP: はい、いくつか失う点はあります。Objective-Cで採用されていた、ランタイムまでどのメソッドが実行されるか分からない動的なメソッドのディスパッチなどです。このことについては、Swift に移行するときに考える必要がある部分だと思います。ほとんどの API は、今も変わっていません。しかし、Swift で動的なことを扱うには少し難しい部分があります。

Q: Swift と Objective-C を一緒に使うのはどれくらい難しいですか?
JP: もちろん可能です。Objective-C の関数やメソッド、クラスなどを Swift で使いたい場合、また逆の場合も、Xcode が自動的に2つの言語を使うための Bridge-Header ファイルを作ってくれます。 Apple のフレームワークは、今も Objective-C で実装されていますが、Swift からそれら呼び出すことができます。

Q: じゃあ、Swift はイミュータブルやスレッドセーフなどの特性を持ってるってことですか?
JP: はい、その通りです。可能な限りミュータブルである必要がないところでは、イミュータブルであるべきという考えがあります。 そのような特性は、Objective-C では、ほとんどありませんでした。

Q: Swift でのメモリ管理はどうなっていますか?
JP: Swift でも ARC が使われています。ARC(Auto Reference Counting) は、Swift と Objective-C 両方にある機能です。参照カウンタによるメモリ管理システムです。オブジェクトを使い始める時に retain を呼んで、それを保持し(カウントを上げ)、使わなくなったら release を呼んで、解放します(カウントを下げる)。オブジェクトの参照カウントが 0 になったら、そのオブジェクトは破棄されます。Swift でも、ARC が retain/release を自動的にコンパイル時に行ってくれます。


About the content

This content has been published here with the express permission of the author.

JP Simard

JP works at Realm on the Objective-C & Swift bindings, creator of jazzy (the documentation tool Apple forgot to release) and enjoys hacking on Swift tooling.

4 design patterns for a RESTless mobile integration »

close