なんか「kotlin にしてみねー?」って話になったのでちょーてきとーに触ってみた
(scala は現環境では動かないっぽいので)
ぶっちゃけ kotlin 言語自体にそんなに熱があるわけでもないので、かなり雑
メモもメモの体裁のまま整えてないし、ドメイン層で触れそうな箇所だけに絞って 3h くらい
ruby / python を書いたときはたしか 20h くらいだったはずなので、それに比べると相当...
そういう意味でも、とても qiita に出す気は起きないけど、一応アウトプット(放出)だけしとく
fun f(x: Int, y: Int): Int {
return x + y
}
- scala と同じじゃんと思って書いたら
= {
ではないのか、怒られた return
省略しても怒られた+
演算子でジャンプ操作をしたらplus
って関数に飛んだので、上書きできそう- クラス定義が出てきたらやってみよう
- 返却がない場合は
Unit
なので、やっぱだいたい scala
infix ってのをつけると中置記法で使えるらしい
data class N(val v: Int) {
infix fun plus(n: N): N = N(v + n.v)
}
println(
n1 plus n2
)
ちなみにn1 + n2
はなんか怒られたのでInt
の+
を見てみたら、operator
とかいうのがついてた
data class N(val v: Int) {
operator fun plus(n: N): N = N(v + n.v)
}
こうするとn1 + n2
ができる
関数の本体が単一の式の場合は{
じゃあなくて=
で定義できる
ってかすぐ上のplus
の例で気づかないでやってた
関数は関数の中でも作れる
これは地味に大変良い
fun halfAndTriple(n: Int): Int {
fun half(n: Int) = n / 2
fun triple(n: Int) = n * 3
return triple(half(n))
}
こうなってくると関数合成とかもしてみたい(素ではできないっぽいので後述)
val
とvar
があるけど、基本val
で良いよね- どっちかの指定は必要っぽい
print(
"result: ${3 + 5}"
)
- 普通に式かける感
- groovy と同じ感じ
複数行
val text = """
|line 1
|line 2
""".trimMargin()
- scala と同じ感じ
val text = """
line 1
line 2
""".trimIndent()
こんなのもあるんだ、おもしろいな
fun isEven(x: Int): Boolean {
if (x % 2 == 0)
return true
else
return false
}
fun isEven(x: Int): Boolean {
return if (x % 2 == 0)
true
else
false
}
if
は式だね!- なので三項演算子も
? / :
じゃあなくてそのまんまだろう
fun isEven(x: Int): Boolean {
return if (x % 2 == 0) true else false
}
- この辺も scala と一緒
- ruby の if 修飾子みたいなのあんのかな?
- あんまり使いたいと思ったことないけど
val x = null
↑ はできるけど ↓ はできないってことらしい
fun f():Int {
return null
}
やりたいなら戻りの型をInt?
にするらしい(しないけど)
fun main() {
val x = f()
}
fun f():Int? {
return null
}
これx
が null っちゃうのは防げないのか...残念...
って思ったけどx: Int = null
って型明記したら怒られた、けどせっかくの型推論なのに明記するの面倒だな
まぁInt?
なんて絶対に使わないので、良いか
しないのでパス
これも式なのかな?
(ちょっと調べたけどわからず...値を返す scala のyield
みたいなのはわかんなかった)
いらん、パス
if 修飾子みたいなやつかと思ったけど、match
みたいなやつっぽい
val x:Any = 5
when (x) {
5 -> print("5")
"5" -> print("five")
}
unapply
みたいなのがあるのかな?
val n = 3
val s = when (n) {
1 -> "one"
2 -> "two"
}
- 漏らす可能性があるから
else
書けって怒られた、嬉しい
listOf(1, 2, 3, 4)
.filter { it % 2 == 0 }
.map { it * 2 }
it
とかは groovy とほとんど同じ感じ- メソッド参照は
::
らしいforEach(::println)
data class User(val id: UserId, val name: UserName)
data class UserId(val v: Int)
data class UserName(val v: String)
- 1 ファイルに複数クラス作れる
data
ってつけると scala のcase
とだいたい同じ感じ- 正直ここだけでも java から置き換える価値がある
- ↓ の java とだいたい同じ
@lombok.ToString
@lombok.EqualsAndHashCode
@lombok.AllArgsConstructor
public class User {
@lombok.Getter
private final UserId id;
@lombok.Getter
private final UserName name;
}
@lombok.ToString
@lombok.EqualsAndHashCode
@lombok.AllArgsConstructor
public class UserId {
@lombok.Getter
private final int v;
}
@lombok.ToString
@lombok.EqualsAndHashCode
@lombok.AllArgsConstructor
public class UserName {
@lombok.Getter
private final String v;
}
インスタンス生成は...
val user = User(UserId(1), UserName("John"))
println(user) // User(id=UserId(v=1), name=UserName(v=John))
普通にできた
static は修飾子ってよりオブジェクトでシングルトンでやる感じっぽい
だいたい scala
println(
UserId.validate(2)
)
data class UserId(val v: Int) {
companion object {
fun validate(v: Int): UserId = UserId(v)
}
}
class
の中に書けるのは良いな
定義列挙、scala と似てる
sealed class UserStatus {
object Confirming
data class Using(val startAt: LocalDateTime)
}
listOf(
UserStatus.Confirming,
Using(LocalDateTime.now()) // import も可能
).forEach { println(it) }
継承は今はいいや、使わないし
あとPair
とTriple
があるよって一言書いてあった、Tuple かな
public data class Pair<out A, out B>(
public val first: A,
public val second: B
) : Serializable {
あ、クラスなのか、ならこうかな
val p = Pair(2, "three")
println(p)
println(p.first)
拡張は...いいや、別にInt
魔改造する気はないし
と思ったけど、関数合成が素でできなかったのでちょっと練習してみる
fun Int.add(n: Int):Int {
return this + n
}
先に型を書いてthis
を使うと良いっぽい、これで3.add(5)
ができる
(infix
をつけておくと3 add 5
も可能なのはさっきやってみた通り)
infix fun Function1<Int, Boolean>.and(f: (Boolean) -> String): Function1<Int, String> = { n: Int -> f(this(n)) }
ラムダ式には必ず{
が必要、最初=
書かないで書いてたからちょっとハマった...
val isEven = { n: Int -> n % 2 == 0 }
val labeling = { b: Boolean -> if (b) "even" else "odd" }
println(
isEven.and(labeling)(4)
)
println(
(isEven and labeling)(4)
)
慣れてきたのであと一歩でおしまい
ジェネリクス(java とほぼ同じ感じで使える)導入してなんとなくplus
でやってみる
operator fun <T1, T2, R> Function1<T1, T2>.plus(f: (T2) -> R): Function1<T1, R> = { t1: T1 -> f(this(t1)) }
val isEven = { n: Int -> n % 2 == 0 }
val labeling = { b: Boolean -> if (b) "even" else "odd" }
listOf(1, 2, 3, 4, 5)
.map(isEven + labeling)
.forEach(::println)
スッキリ
public
がデフォルトprivate
internal
はモジュール- IDEA モジュールや Gradle プロジェクト、同じタスクでコンパイルされたファイルセット?
- package private の様なものではないっぽいな、pp ないって噂で聞いたし...
protected
さっきsealed
でやったやつなのかと思ったけど、普通にあるっぽい
値も持てるよ!
enum class Vector {
U, R, D, L
}
enum class Size(val price: Int) {
S(120), M(180), L(220)
}
.values()
なんかもそのまま使えるっぽい
ちょいちょい使いたくなるので良い
val ns = listOf(1, 2, 3)
println(
ns.plus(4) // 1, 2, 3, 4
)
println(
ns // 1, 2, 3
)
破壊されない!
ん?
kotlin ってOptional
とかSome
ってないの?
String?
だけ?
それはいくらなんでも...
javaslang でも使うか...
でもそれだとList
も javaslang にしておいた方が組みやすいしな...えぇ...
大事
なんかsdkman
で入れるっぽい(ここまでは IntelliJ で書いてた、流石にそっちはなんの設定もなしで書ける)
$ kotlinc
>>> listOf(1, 2, 3).forEach(::println)
1
2
3
なんやかんやで入れたけど、<TAB>
補完が効かないなぁ
設定必要?
- 公式マニュアルが微妙に読みづらい
- 章立てとか、サンプルコードが必要最低限より大きい感じがするとか
- ちょいちょいリンクが切れてる
- python / ruby の時に触れた以下は今回は略
- 配列(文字列)のスライス, file, os command, コマンドラインパーサ
- あっちはライトツール用だったけど、今回はその辺はあんまりやらない見込みだし
- groovy と scala 知ってりゃ最低限の読み書きは数時間で大丈夫
- ただ案外やれることがあって、その辺は今回は飛ばしちゃった
Option
ないのはキツい- というか
Either
とかもないな - これは結構うっおとしいな...
- というか
- 試してないけど、
List
が java のList
じゃあなかったけど、spock ( groovy ) とかで[]
記法でテスト書いたらどうなるんだろう? - っつーか制約なく選ぶなら scala 使うな
- java よりはまぁマシだけど、これ一本に倒したい言語ではないなぁ...んん...