Skip to content

Instantly share code, notes, and snippets.

@suzuki-hoge
Last active September 29, 2019 12:55
Show Gist options
  • Save suzuki-hoge/0949c98ca2c76798ea40664b91235b1f to your computer and use it in GitHub Desktop.
Save suzuki-hoge/0949c98ca2c76798ea40664b91235b1f to your computer and use it in GitHub Desktop.
雑 kotlin 超超雑記

これは

なんか「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))
}

こうなってくると関数合成とかもしてみたい(素ではできないっぽいので後述)

変数定義

  • valvarがあるけど、基本valで良いよね
  • どっちかの指定は必要っぽい

文字列

print(
    "result: ${3 + 5}"
)
  • 普通に式かける感
  • groovy と同じ感じ

複数行

val text = """
    |line 1
    |line 2
""".trimMargin()
  • scala と同じ感じ
val text = """
    line 1
    line 2
""".trimIndent()

こんなのもあるんだ、おもしろいな

if

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 修飾子みたいなのあんのかな?
    • あんまり使いたいと思ったことないけど

nullable

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?なんて絶対に使わないので、良いか

キャスト

しないのでパス

for

これも式なのかな?

(ちょっと調べたけどわからず...値を返す scala のyieldみたいなのはわかんなかった)

while, brake, continue

いらん、パス

when

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)

class

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) }

継承は今はいいや、使わないし

あとPairTripleがあるよって一言書いてあった、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

enum

さっき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
)

破壊されない!

optional / nullable

ん?
kotlin ってOptionalとかSomeってないの?
String?だけ?

それはいくらなんでも...

javaslang でも使うか...
でもそれだとListも javaslang にしておいた方が組みやすいしな...えぇ...

repl

大事

なんか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 よりはまぁマシだけど、これ一本に倒したい言語ではないなぁ...んん...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment