おはようエンジニア

まともなエンジニアになりたい

『Kotlinイン・アクション』第3章を読む (その1)

Kotlinイン・アクション第3章は「関数の定義と呼び出し」です。

前章と同じく知らなかったことやそのうち忘れそうなことを中心に書いていきます。

コレクション生成

  • ~Of メソッドでコレクションを生成できる
    • 内部ではJavaの標準コレクションを使用している
    • 例: hashSetOf, arrayListOf, hashMapOf
val set = hashSetOf(1, 7, 53) // 生成
println(set.javaClass) // -> class java.util.HashSet

関数の呼び出し

名前付き引数

  • 引数名を指定して呼び出し
    • ただしKotlinで定義した関数のみ
    • 混乱を避けるためすべての引数に対して名前を指定すべき
joinToString(collection, separator = " ", prefix = " ", postfix = ".")

デフォルト引数

  • 関数の宣言でデフォルト値を持たせることができる
    • 呼び出し時に引数を省略するとデフォルト値が入る
    • 名前付きではない関数呼び出しをする場合は、後ろ側の引数のみ省略可
  • 関数に @JvmOverloads をつけると、コンパイル時にデフォルト引数を持った関数からオーバーロードメソッドを生成する
@JvmOverloads
fun test(msg1: String = "hoge", msg2: String = "piyo"): String
// 同一のクラスへコンパイルされるJavaコード
String test(String msg1, String msg2)
String test(String msg1)
String test()

トップレベル関数

  • 関数はトップレベルに宣言できる
// join.kt
package strings
fun joinToString(...): String { ... }
// 同一のクラスへコンパイルされるJavaコード
package strings

public class JoinKt {  // ファイル名から決定される
    public static String joinToString(...) { ... }
}
  • Kotlinファイルに@file:JvmName("StringFunctions") をつけると生成するクラス名を変更できる

トップレベルプロパティ

  • プロパティもトップレベルに宣言できる
    • 普通に宣言するとプロパティになるのでgetterやsetterが自動で生成される
  • const をつけて宣言すると public static final な定数として宣言できる
const val TAX = 1.08
/* java */
public static final String TAX = 1.08;

tmuxのすすめ

今回は tmux についての記事です。

私自身まだ十分に tmux を活用できていませんが、導入してからターミナル生活がとても快適になったので、普段どんな風に使っているかを書いていきます。

tmuxについて

tmuxは端末多重化ソフトウェアです。 詳細な説明は検索するとたくさん出てくるので割愛します。 ↓のリンクは私が導入するときに参考にした記事です。

qiita.com

私は1つのセッションの中で2~3つのウィンドウを作り、それを2~6つのペインに分割して使っています。

prefixキーについて

tmuxの機能は [prefixキー] を一度押した後 [特定のキー] を押すことで実行できます。

prefixキーのデフォルトはCtrl-bです。私はCtrl-gに変更しています。

tmux.confの設定

~/.tmux.conf に設定を書くことができます。

# prefixキーをC-gに変更する
set -g prefix C-g

# C-bのキーバインドを解除する
unbind C-b

おすすめ機能

導入した後にまずこれだけ使ってほしいという機能を紹介します。

その1: ウィンドウの分割

操作 デフォルト 私の設定
ウインドウを上下に分割 prefixキー → " prefixキー → -
ウインドウを左右に分割 prefixキー → % prefixキー → /

上下分割の-は横線で分けるイメージ、左右分割の\は縦線で分けるイメージです。

tmux.confの設定

bind - split-window -v
bind / split-window -h

その2: ペイン移動

操作 デフォルト 私の設定
左のペインに移動 prefixキー → Left prefixキー → Ctrl-h
上のペインに移動 prefixキー → Up prefixキー → Ctrl-j
下のペインに移動 prefixキー → Down prefixキー → Ctrl-k
右のペインに移動 prefixキー → Right prefixキー → Ctrl-l

prefixキーのあとの設定をCtrl+h,j,k,l にすることによって以下の例のように少し移動が楽に(?)なります。

  1. Ctrlgを同時押し
  2. gだけ離す
  3. hを押す → 上のペインに移動完了

tmux.confの設定

bind C-h select-pane -L
bind C-j select-pane -D
bind C-k select-pane -U
bind C-l select-pane -R

その3: ペイン最大化

操作 デフォルト 私の設定
ペイン最大化/元に戻す prefixキー → z 変更なし

選択中のペインをウィンドウいっぱいに拡張します。

該当のペインに移動して最大化、編集したら戻ったらまた次のペインへ...というような使い方をよくしています。

最後に私のtmux.confを貼って終わります。

tmux.conf

# prefixキーをC-gに変更する
set -g prefix C-g

# C-bのキーバインドを解除する
unbind C-b

# ウィンドウのインデックスを1から始める
set -g base-index 1

# ペインのインデックスを1から始める
setw -g pane-base-index 1

# 設定ファイルをリロードする
bind r source-file ~/.tmux.conf \; display "Reloaded!"

# 画面分割
bind - split-window -v
bind / split-window -h

# vimキーバインドでペインを移動する
bind C-h select-pane -L
bind C-j select-pane -D
bind C-k select-pane -U
bind C-l select-pane -R

# vimキーバインドでペインサイズを変更する
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5

# マウス操作を有効にする
setw -g mouse on

# アクティブなウィンドウの色
set-window-option -g window-status-current-fg colour16
set-window-option -g window-status-current-bg colour178

# ペインのボーダーの色
set-option -g pane-border-fg black #base02
set-option -g pane-active-border-fg brightgreen #base01

# ステータスバーの位置を上にする
set-option -g status-position top

# status line の背景色を指定する
set-option -g status-bg "colour235"

# status line の文字色を指定する
set-option -g status-fg "colour255"

# status-left の最大の長さを指定する
set-option -g status-left-length 20

# status-left のフォーマットを指定する
set-option -g status-left "#[fg=colour255,bg=colour241]Session: #S #[default]"

# status-right の最大の長さを指定する
set-option -g status-right-length 60

# status-right のフォーマットを指定する
set-option -g status-right "#[fg=colour255,bg=colour241] #h | %m/%d %H:%M:%S#[default]"

# window-status のフォーマットを指定する
set-window-option -g window-status-format " #I: #W "

# カレントウィンドウの window-status のフォーマットを指定する
set-window-option -g window-status-current-format "#[fg=colour255,bg=colour27,bold] #I: #W #[default]"

# コピーモードでviのキーバインドを使用する
setw -g mode-keys vi
bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T vi-copy V send-keys -X select-line
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "pbcopy"
bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "pbcopy"

『Kotlinイン・アクション』第2章を読む (その2)

前回に引き続き、Kotlinイン・アクションの第2章「Kotlinの基本」です。

『Kotlinイン・アクション』第2章を読む (その1) - おはようエンジニア

 enum

  • 列挙型は enum class で宣言する
    • enum の部分はソフトキーワードという扱い(classと組み合わせて意味を持つ)
enum class Color {
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}
  • プロパティを持つ列挙型も宣言できる
    • enum定数の宣言ではプロパティの値を指定する
    • 定数定義の終わりにセミコロンが必要 (メソッドの定義と分離するため)
enum class Color (val r: Int, val g: Int, val b: Int){
    RED(255, 0, 0), ORANGE(255, 165, 0), ..., VIOLET(238, 130, 238);

    fun rgb() = (r * 256 + g) * 256 + b
}

when

  • whenは値を返すので「文」ではなく「式」
    • それぞれの分岐でのbreak文は不要
    • 複数の値によって分岐できる
fun getWarmth(color: Color) = when(color) {
    Color.RED, Color.ORANGE, Color.YELLOW -> "warm"
    Color.GREEN -> "neutral"
    Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold"
}
  • 定数の値をインポートするとより簡潔
    • ここの1行目の役割がわからない
import ch02.colors.Color
import ch02.colors.Color.*

fun getWarmth(color: Color) = when(color) {
    RED, ORANGE, YELLOW -> "warm"
    GREEN -> "neutral"
    BLUE, INDIGO, VIOLET -> "cold"
}
  • when式の引数にオブジェクトも使用できる
    • この例は比較の度にインスタンスを生成するのでパフォーマンスはあまりよくない
    • 読みにくくなるが引数なしwhen文を使うとパフォーマンスは改善する
// オブジェクトが引数の場合
when (setOf(c1, c2)) {
  setOf(RED, YELLOW) -> ORANGE
  ...
}

// 引数なしの場合
when {
  (c1 == RED && c2) || (c1 == YELLOW && c2 == RED) -> ORANGE
  ...
}

スマートキャスト

is によって変数の型をチェックすると明示的なキャストが不要になる

fun eval(e: Expr): Int {
    if (e is Num) {
        val n = e as Num   // 不要
        println("num: ${n.value}")
        return n.value
    } else if (e is Sum) {
        val n = e as Sum   // 不要
        ...
}

whenですっきり表記

fun eval(e: Expr): Int {
    when (e) {
        is Num -> {
            println("num: ${e.value}")
            e.value
        }
        is Sum -> {
        ...
}

while

  • whiledo-while がある

for と range

  • Kotlin の forJavafor-each 形式のみ
// 1から100まで (閉区間)
for (i in 1..100) {
    print(i) // 1,2,3,...,100
}

// 1から100の直前まで (半開区間)
for (i in 1 until 100) {
    print(i) // 1,2,3,...,99
}

// 後進
for (i in 100 downTo 1) {
    print(i) // 100,99,98,...,1
}

// 2ずつ増加
for (i in 1..100 step 2) {
    print(i) // 1,3,5,...,99
}
  • 文字やコレクションでもレンジを作れる
// Character
for (c in 'A' .. 'F') {
    ...
}

// TreeMap
for ((key, value) in myMap) {
    ...
}

// ArrayList
for ((index, element) in list.withIndex()) {
    ...
}
  • !in でレンジ外であることをチェックできる
fun isNotDigit(c: Char) = c !in '0'..'9'

例外処理

  • throw は式扱い
  • 関数定義の後ろに throws はいらない
  • 検査例外と非検査例外は区別しない
    • 例外を処理するかどうかは実装者に委ねる
    • 理由はJavaの検査例外の処理がボイラープレートになっているため
  • tryも式
    • 例外をキャッチしたときに結果を変える実装をシンプルに書ける
val number = try {
    Integer.parseInt(reader.readLine())
} catch (e: NumberFormatException) {
    null
}

式と文のまとめ

構文 Java Kotlin
when
if
throw
try
代入 (例: a = 1)

おわりに

2章で基本的な構文について学ぶことができました。

KotlinではJavaで文だったものの一部が式になり、式本体を持つ関数と相性が良さそうな印象です。

特に、when式はかなり柔軟で使い勝手がよさそうです。また、break文を何度も書く必要がないのも嬉しいです。

『Kotlinイン・アクション』第2章を読む (その1)

はじめに

Kotlinイン・アクション第2章「Kotlinの基本」を読んでいきます。 

今回は以下2点を中心に書いていこうと思います。

  • 知らなかったこと
  • そのうち忘れそうなこと  

関数

  • mainはトップレベルに宣言できる
    • main用にクラス作らなくてもいい
  • 「ブロック本体」と「式本体」がある
    • 式本体は「波括弧」「return文」「戻り値の型」を省略できる  
// ブロック本体を持つ
fun max(a: Int, b: Int): Int {
    return if (a > b) a else b
}
// 式本体を持つ
fun max(a: Int, b: Int) = if (a > b) a else b

変数

  • 変数宣言のキーワードは2つ
    • val (value) はイミュータブルな変数 = Javaのfinal変数
    • var(variable) はミュータブルな変数
  • 文字列テンプレートの機能で文字列に変数を埋め込むことができる
    • 単純な場合 -> "Hello, $name!"
    • 複雑な場合 -> "Hello, ${args[0]!}" (どんなケースが複雑な場合に該当する?)

クラス

  • コンストラクタの中でフィールドを宣言できる
    • class Person(val name: String) でOK
    • ↑のように実装コードがないクラスは値オブジェクトと呼ばれる
  • Kotlin のデフォルトの可視性は public
    • Javapackage private

プロパティ

  • 「プロパティ」=「フィールド」+「アクセサメソッド(getter/setter)」
    • Kotlin ではプロパティは第一級の言語機能(変数や関数と同列)
  • プロパティの宣言はvalまたはvarを使う
    • valでプロパティを宣言するとgetterも宣言される
    • varでプロパティを宣言するとgetter/setterも宣言される
  • 宣言されたgetter/setterはJavaでは命名規則に従って名前決まる
    • プロパティ名name --> getter: getName(), setter: setName()
    • プロパティ名isMarried --> getter: isMarried(), setter: setMarried()
  • カスタムアクセサ
    • ↓のように実装できる。isSquareとget()の間に別の変数を宣言したりするとエラーになる
class Rectangle(val height: Int, val width: Int) {
    val isSquare: Boolean
        get() {
            return height == width
        }
}

パッケージ

  • 全ファイルの冒頭にpackage文を持つことができる
    • 例: package geometry.shapes
  • 別のパッケージに宣言されているものを使う場合はimport
    • 例: import geometry.shapes.createRandomRectangle
    • インポート時はクラスと関数を区別しない
  • packageの階層構造とディレクトリ構造は同じでなくてよい

おわりに

構文を見ているやはり簡潔でわかりやすいと感じました。

getter/setterの命名規則はちょっとクセがありそうなのでプロパティの命名には注意したいと思います。

個人的にはvalとvarが似ているのがちょっと気になりました。実際にはvalを使うケースが多いように思うので、使ってみるとそんなに気にならないかもしれません。

後半は次の記事で書きたいと思います。

『Kotlinイン・アクション』第1章を読む

はじめに

社内のKotlin勉強会に参加することになりました。

以前からAndroidアプリ開発に興味があり、Kotlinの勉強もしたいと思いつつほとんど進めていなかったので、ちょうど良い機会でした。

課題図書読む→演習問題をやる→参加者がレビューする→... というスタイルで進めていくようです。

 

課題図書は『Kotlinイン・アクション』です。

主に開発経験者 (特にJavaで書いたことがある人) 向けに書かれているようです。 

著者がKotlinの設計に携わっているということもあり、言語仕様だけでなく設計思想も知ることができるようなので、とても楽しみです。

本についてはこちらの記事で紹介されていました。

 

kirimin.hatenablog.com

 

「第1章 Kotlinとは何か?なぜ使うのか?」のメモ

Kotlinとは

Kotlinは、Java仮想マシンで動くJVM言語の一つです。

開発元は長年IDEの開発に取り組み続けているJetBrains社です。

相互運用性を重視し、実用主義で、簡潔で、安全な言語」という表現がKotlinの特長をよく表しているようです。

相互運用性

KotlinはJavaと混在して使うことが可能で、既存のJavaライブラリをそのまま使うこともできます。

また、ツールによってJava <--> Kotlin間のコード変換も簡単に行うことができます。

実用主義

Kotlinは実業務でJavaを使ったときに起こる問題を解決するための言語です。

そのため、革新的なアイデアの導入は避け、他の言語で経験上良いとされている構文などを積極的に取り入れています。

また、言語そのものだけでなくツールを重視しており、InteliJ IDEAやAndroid StudioといったIDEで開発することを想定しています。 

簡潔

Kotlinはボイラープレート(お決まりのコード)をできるだけ暗黙的にすることで、明示的に書くコードのすべてが意味を持つような設計を目指しています。

その一方で、ソースコードの文字数を単に減らそうとはせず、可読性や理解のしやすさを重視しています。

安全

Kotlinはコンパイル時にコードをチェックすることで安全性を高めています。

特に、ランタイムエラーの代表格であるNullPointerExceptionをなくすように努めています。

Kotlinではnull許容型を明示的にサポートすることでこの問題を解決しようとしています。

 

おわりに

1章を読んで、Kotlinは地に足の着いた堅実な言語という印象を受けました。

既存のJavaプロジェクトに簡単にKotlinを取り入れることができるようにすることで、少しずつKotlinの良さに気づいてもらい、最終的に置き換えてほしい、という開発者の意図が感じられました。

私自身も、ここまでしっかりサポートされていれば、業務でも使っていけそうだと感じました。

Kotlinは今年の5月にAndroidアプリ開発の推奨言語になったので、今後もますます盛り上がっていけば良いなと勝手に思っています。

 

自己紹介

はじめまして、yoと申します。

Web系のエンジニアのような仕事をしています。

 

思っていることを素直に文章にする力を身につけたいと思い、ブログを始めてみました。

記事の内容が役に立つかどうかは一旦考えず、自分が勉強したことなどをメモ程度に書いていこうと思います。

 

よろしくお願いします。