29
Kotlin as an AltJS @mike_neck

Kotlin as an AltJS

Embed Size (px)

Citation preview

Kotlin as an AltJS@mike_neck

おことわり

• たぶん15分も話せません

• いろいろ言い訳ありますが…

• 要するに雑に話します

Kotlin as an AltJS

誰?

• 持田真哉(@mike_neck)

• たんなるJava、Groovy好きのおっさん

• Kotlin歴3時間弱

Kotlin as an AltJS

概要

• モティベーション

• Java使いにとってのAltJSの候補

• Interoperating with existing JS libs

• Kotlin as an AltJS

Kotlin as an AltJS

モティベーション

生JS書きたくない

普通のプログラミングしたい

モティベーション• 普通のプログラミングとは?(あくまで私見です)

• 型があって、不正な操作はコンパイル時にエラーにしてくれる

• IDE(IntelliJ IDEA)で補完してくれる

• 欲を言えばGradleでビルドできる

• 老害脳なので、新しいツール覚えるの辛い

Java使いにとってのAltJS

• TypeScript

• Scala.js

• Kotlin

• ClojureScript…ごめんLisp覚えるの辛い

キワモノから…

Java使いにとってのAltJS

Kotlin• デフォルトでJavaScriptへのコンパイルをサポートしているbetter Java

• Java、C#やっていれば学習コストは大して高くない

• 生成されるJavaScriptはそこそこ複雑

• JetBrains製なのでIntelliJ IDEAでもサクサク書ける

• 対応している既存JSライブラリーがjQueryしかない

• kotlin2jsプラグインでGradleでもビルドできる

Java使いにとってのAltJS

Scala.js• ScalaコンパイラーのプラグインでJavaScriptを生成する

• それなりに学習コストが高い(私見です)

• 生成されるJavaScriptが巨大

• IntelliJのScalaプラグインによってそこそこ補完が効く

• jQuery、Angular、Reactに対応するライブラリーがある

• sbtという人間には早すぎたビルドツールが必要(0.6.0からはMaven/Gradleでも利用可能にするためにMaven artifact化しているらしいけど、現在プラグインがない)

Java使いにとってのAltJS

TypeScript• JavaScriptを拡張したAltJS

• Java、C#やってれば学習コストは大して高くない

• 生成されるJavaScriptはシンプル

• IntelliJ IDEAで補完が効くのでサクサク書ける

• エコシステム(DefinitelyTypedのd.ts)が豊富

• Gradleプラグインがあった!

• sothmann/typescript-gradle-plugin

• grezi/gradle-typescript-plugin

Java使いにとってのAltJS

悪いこと言わないからTypeScriptを使え

Java使いにとってのAltJS

おわり

・・・

Kotlinの勉強会でしたね…

Interoperating with existing JS libraries

• インターフェースを作る必要がある

• native(“foo”)のような形で既存JSライブラリーのインターフェースを準備する

• 中身は実装する必要ないのでnoImplを指定する

• 型安全なハンドラーを指定したい場合はジェネリクスを用いる

• 型安全にしたいからKotlinを使うのであって、Any使ってたらあまり意味無いですよね

jQueryのajax関数(kotlin-js-libraryでは未定義)を使うimport jquery.jqpublic fun main(args: Array<String>) { jq { jq(“.button”).click(e -> { val options = ajaxOptions( “greeting”, “GET”, Person(“foo”,”bar”)) ajax<Message,Any>(options) .done { msg, raw, jqXHR -> jq(“name”).text(msg.text) jq(“message”).text(msg.message) } }) }}

Interoperating with existing JS libs

自分で既存JSライブラリーのインターフェースを定義する

native(“$.ajax”)public fun ajax<R,E>( options: jqAjaxOption): jqPromise<R,E> = noImpl

native(“jqXHR”)open class jqPromise<R,E>() { fun done(handler: (R,String,jqDeferred<R,E>)->Unit): jqDeferred<R,E> = noImpl fun fail(handler: (jqDeferred<R,E>,String,E)->Unit): jqDeferred<R,E> = noImpl}

Interoperating with existing JS libs

自分で既存JSライブラリーのインターフェースを定義する

native(“$.ajax”)public fun ajax<R,E>( options: jqAjaxOption): jqPromise<R,E> = noImpl

native(“jqXHR”)open class jqPromise<R,E>() { fun done(handler: (R,String,jqDeferred<R,E>)->Unit): jqDeferred<R,E> = noImpl fun fail(handler: (jqDeferred<R,E>,String,E)->Unit): jqDeferred<R,E> = noImpl}

Interoperating with existing JS libs

nativeアノテーションでJavaScriptにコンパイルした時の出力される名前を指定

自分で既存JSライブラリーのインターフェースを定義する

native(“$.ajax”)public fun ajax<R,E>( options: jqAjaxOption): jqPromise<R,E> = noImpl

native(“jqXHR”)open class jqPromise<R,E>() { fun done(handler: (R,String,jqDeferred<R,E>)->Unit): jqDeferred<R,E> = noImpl fun fail(handler: (jqDeferred<R,E>,String,E)->Unit): jqDeferred<R,E> = noImpl}

Interoperating with existing JS libs

実装はいらないのでnoImplを指定する

自分で既存JSライブラリーのインターフェースを定義する

native(“$.ajax”)public fun ajax<R,E>( options: jqAjaxOption): jqPromise<R,E> = noImpl

native(“jqXHR”)open class jqPromise<R,E>() { fun done(handler: (R,String,jqDeferred<R,E>)->Unit): jqDeferred<R,E> = noImpl fun fail(handler: (jqDeferred<R,E>,String,E)->Unit): jqDeferred<R,E> = noImpl}

Interoperating with existing JS libs

ハンドラーの引数は型安全にしたいのでジェネリクスを付

ける

Interoperating with existing JS libraries

• JavaScriptのシンプルなオブジェクトが欲しい場合

• 普通のclassを用いれば後はよしなにやってくれるclass Person( val firstName: String, val lastName: String)// Person(“foo”, “bar”)// -> {firstName:”foo”, lastName: “bar”}

Interoperating with existing JS libraries

• 落とし穴

• deep copyをするなどのJavaScriptの実装によっては実行時エラーが発生する

class jqAjaxOption<T>( val url: String, val method: String, val data: T)// jQueryがdataパラメーターを処理しているときに// cannot set property ‘firstName’ of undefined// のようなエラーが発生する

Interoperating with existing JS libraries

• 解決策

• json(Pair<String,Any>…): Json を使う

interface JsonSerializable { fun asJson(): Json}class Person( val firstName: String, val lastName: String): JsonSerializable { override fun asJson(): Json { return json(Pair(“firstName”,firstName), Pair(“lastName”, lastName)) }}

Kotlin as an AltJS• まだAltJSとして使うにはつらいところが多々ある

• Kotlinから生成されるJavaScriptの品質についてはJetBrainsに頑張ってもらう一方で、ユーザーである我々もフィードバックしていくことが望まれる

• Kotlinが使ってもらえるAltJSとなるには、エコシステムの構築にカギがある

Kotlin as an AltJS

• TypeScript

• DefinitelyTypedプロジェクトによるエコシステム

• tsdやdtsmのような簡易に型情報を収集するツール

Kotlin as an AltJS• Scala.js

• scala-js.orgでライブラリーへのリンクが貼ってある

• 基本的なスタンスは「sbtで取ってきてね」という感じ

• 最初はギャグと言われていたけど、Scalaのユーザー数が増えているのでScala.jsのエコシステムも充実しつつあるという印象

Kotlin as an AltJS• AltJSとしてKotlinを使ってもらうためには…

• エコシステムの構築

• レポジトリーの構築

• 必要なライブラリーを管理するツールの構築

• そもそものユーザー数を増やしていく

• ちなみにKotlin自体は3時間さわった感じでは、よい言語に分類できると思ってます

おわり

Kotlin as an AltJS