Kotlinにチャレンジしてみる（HelloWorld)

#Kotlinって何？
IntelliJなどで有名なJetBrains社が作り上げた、JVM上で動作する新しい言語らしい。
どんな言語なの？今後どんな感じになるの？流行るの？と疑問は色々出てきますが、無料で使えるんだから自分の手を動かして試してみるのが手っ取り早いし、そうするべきなのでチャレンジしてみました。

#環境構築

## SDKMANを利用してインストール
最近のプログラミング言語には、それ自体をお手軽にインストール、管理できるツールが付きものです。
現在、JVM上で動くプログラミング言語やツールをインスール、管理するツールとして[SDKMAN](http://sdkman.io/)が有ります。
コレを使えばKotlinだけでなく、GroovyやScalaと言った別のプログラミング言語からそれらのフレームワークやツールまでインストールすることが出来ます。
SDKMANのインストール方法や詳細な情報は[[Groovy]gvmが生まれ変わった。SDKMANでGrvoovyやGrailsをインストール](http://qiita.com/saba1024/items/967ee3d8a79440a97336)を参照してください。
SDKMANのインストールが完了したら`sdk install kotlin`を実行するだけでKotlinの最新バージョンがインストールできます。


## 手動でインストール 
KotlinはJetBrains製（オープンソースだけど）なので、当然IntelliJでサポートされます。
でも、こういった新しい言語の勉強を始めるときはなんといってもコマンドライン！
ということでコンパイラを公式から落としてきます。

[http://kotlinlang.org/#get-kotlin](http://kotlinlang.org/#get-kotlin)にアクセスして、Download Compilerを選択クリック。
すると別のダウンロードサイト（Github）に飛ばされるので、そのページの最下部にあるkotlin-compiler-0.8.11.zipをダウンロード。

解凍するとkotlincというディレクトリができるので、好きなディレクトリに置いて、kotlinc/binディレクトリにパスを通しておきます。。
ちなみにkotlinはまだまだ発展途上らしいので、おそらく頻繁にアップデートされると思う。
なので自分はkotlincというディレクトリはシンボリックリンク用にした。
新しいバージョンのKotlinがリリースされたら、同じディレクトリに設置してシンボリックリンクだけ切り替えればOK。
このあたりは個人の好みや環境に合わせればOKだと思います。

```console:シンボリックリンク化
kkuwana% mv kotlinc kotlinc-0.8.11
kkuwana% ln -s kotlinc-0.8.11 kotlinc        
kkuwana% ls -al | grep kotlin
lrwxrwxrwx  1 k-kuwana k-kuwana   14  9月  8 14:55 kotlinc -> kotlinc-0.8.11
drwxr-xr-x  5 k-kuwana k-kuwana 4096  7月  2 10:53 kotlinc-0.8.11
kkuwana% 
```
自分の環境ではzshを使っているので$HOME/.zshenvに以下を記述

```zsh:$HOME/.zshenv
export KOTLIN_HOME=/home/k-kuwana/lib/kotlinc
path=(
    $KOTLIN_HOME/bin
    $path
)
```
`source $HOME/.zshenv`するとかすればOK。

#HelloWorld
何はともあれHelloWorld！
[公式チュートリアル](http://kotlinlang.org/docs/tutorials/command-line.html)を参考に。
拡張子は**.kt**で、ファイル名の先頭はJavaと違って大文字じゃなくてもいいのかな？

##ソース
```kotlin:helloworld.kt
fun main(args:Array<String>) {
    println("こんにちわ世界！")
}

```
##コンパイル

コンパルには、`kotlinc-jvm`というコマンドを使います。
間違いなく長すぎるコマンド名ですね。。。groovyですら長いと思っていたのに。。。
しかも`kotlin-j`までは同名のファイルが存在するので、結構イライラします。
メジャーバージョンが出るときにここのあたり弄るんですかね？
まぁ慣れの問題だと思うのでスルー！

コンパイルしてclassファイルが生成される、わけではなくてjarにして出力してるみたい。
オプション扱いだから多分普通のclassファイルも出力できると思うけど。。。
とりあえず進む。

基本的なコマンドのフォーマットは`kotlinc-jvm <プログラム名> -jar <出力jarファイル名>`という感じです。

```
kkuwana% kotlinc-jvm helloworld.kt -jar app.jar
kkuwana% ls
app.jar  helloworld.kt
```

**追記（2017/05/22）**
修正リクエストにてご指摘頂きました。最近のバージョンでは、`-jar`に替わって、`--include-runtime`というオプションを付与しなければならないようです。

```bash
kkuwana% kotlinc-jvm helloworld.kt -include-runtime -d app.jar
kkuwana% ls
app.jar  helloworld.kt
```



##実行

Javaコマンドで実行します。
ちょっとここに驚きました。GroovyやScalaの場合、JVMで動くからjavaコマンドで実行できますよというのはよく見聞きしますが、基本はそれぞれ専用のscalaコマンドやgroovyコマンドで実行しますが、kotlinの場合はチュートリアルでいきなりjavaコマンドで実行するという清さ。
Kotlinの目標がScalaやGroovyとは少し違うのかな？というのがここから感じられました。（本当のところはどうか知りませんが。。。）
ちなみにJavaのバージョンは1.8.0_11です。

実行時には当然、今回生成したapp.jarと、kotlin-runtime.jarにクラスパスを通して、`＿DefaultPackage`というクラスを実行します。

```bash
kkuwana% java -classpath app.jar:$KOTLIN_HOME/lib/kotlin-runtime.jar _DefaultPackage
こんにちわ世界！
kkuwana% 
```

無事文字化けすることもなく実行できました！

##jarじゃなくclassを生成する
-jar オプション以降を省略するだけでOK.
今回のhelloworld.ktの場合、2つのclassファイルが生成されて、`_DefaultPackage.class`のほうが実際のmainクラスになるらしい。
あ、そうか！と思ってさっき生成されたapp.jarの中身を見ると、当然2つのclassファイルが生成されていて、`_DefaultPackage.class`もちゃんと入っていました。


```console
# コンパイル
kkuwana% kotlinc-jvm helloworld.kt

#2つのクラスファイルが生成されている。
kkuwana% ls
_DefaultPackage-helloworld-3798a62d.class  _DefaultPackage.class  app.jar  helloworld.kt
kkuwana% 
```

なので、当然以下の様に実行することができます。

```console
java -classpath .:$KOTLIN_HOME/lib/kotlin-runtime.jar _DefaultPackage
```
細かく調べていませんが、`_DefaultPackage.class`は、このkotlinアプリケーションのスタートポイントだよ、というモノっぽいです。
今回のhelloworld.kt本体はもう片方のclassファイルの気がします。

##ちょっと試してみる
試しに`_DefaultPackage.class`を削除して、残った方のclassファイルを実行してみます。

```console
#コンパイル
kkuwana% kotlinc-jvm helloworld.kt 
kkuwana% ls
_DefaultPackage-helloworld-3798a62d.class  _DefaultPackage.class  helloworld.kt

#_DefaultPackage.classを削除
kkuwana% rm _DefaultPackage.class 

#残った別のclassファイルを実行
kkuwana% java -classpath .:$KOTLIN_HOME/lib/kotlin-runtime.jar _DefaultPackage-helloworld-3798a62d 
こんにちわ世界！
kkuwana%
```
動いた！

じゃあ逆に`_DefaultPackage.class`**じゃない方**を消してみたら？

```console
#コンパイル
kkuwana% kotlinc-jvm helloworld.kt 
kkuwana% ls
_DefaultPackage-helloworld-3798a62d.class  _DefaultPackage.class  helloworld.kt

#_DefaultPackage.classじゃない方を削除
kkuwana% rm _DefaultPackage-helloworld-3798a62d.class 
kkuwana%  

#_DefaultPackageを実行してみる
kkuwana% java -classpath .:$KOTLIN_HOME/lib/kotlin-runtime.jar _DefaultPackage                    
Exception in thread "main" java.lang.NoClassDefFoundError: _DefaultPackage-helloworld-3798a62d
	at _DefaultPackage.main(helloworld.kt:1)
Caused by: java.lang.ClassNotFoundException: _DefaultPackage-helloworld-3798a62d
	at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 1 more
kkuwana% 
```
動かない。
やっぱり`_DefaultPackage.class`はスタートアップだけど本体ではないっぽいですね。


#REPL
あるの！？ないの！？どっちなの！REPLって検索してもヒットしないじゃん！と思ったらRunning the shellって言うところに書いてました。コレがどうやらREPLのようです。
ただ`kotlinc-jvm`とだけ入力すればOKらしい。

```console
kkuwana% kotlinc-jvm
Kotlin interactive shell
Type :help for help, :quit for quit
>>> 
```
起動が早い！groovyshから比べたら雲泥の差レベルで早い！

helpコマンドがあるみたいです。`:help`と入力します。

```console
>>> :help
This is Kotlin REPL help
Available commands are:
:help                   show this help
:quit                   exit the interpreter
:dump bytecode          dump classes to terminal
:load <file>            load script from specified file
>>> 

```

##REPLでHelloWorld

```console
>>> println "Hello World"
ERROR: /line5.kts: (1, 9) Unexpected tokens (use ';' to separate expressions on the same line)
>>> println ("Hello World")
Hello World
>>> 
```
カッコは省略できないみたいですね。

## REPLで変数を使ってみる

```console
>>> val a:String = "HelloWorld"
>>> a
HelloWorld
>>> 
```
普通に使えます。

#感想
とりあえずKotlinが動く状態になりました。
本当にHelloWorldだけなのでまだまだ何もわかりませんが、これからKotlinに挑戦していこうと思います。
`kotlinc-js`というコマンドがあります。もうファイル名からその役割が臭ってきますが、勉強するのがかなり楽しみです。

#参考
http://kotlinlang.org/