kotlin小ネタ:expression の値が null の場合のみ expression の値を変えずに処理を行う例

// オリジナル
val currentValue = nextValue()
if (currentValue == null) finish()

// 等価コード1
val currentValue = nextValue().apply { if (this == null) finish() }

// 等価コード2
val currentValue = nextValue() ?: { finish(); null }()

elvis operator を使う場合に expression が null を返すのが面倒なら
こういうのを作っちゃっう方法もありかも。

/**
 * Calls the specified function [block] with `this` value as its receiver only if `this` is null and returns `this` value.
 */
inline fun <T> T.applyIfNull(block: T.() -> Unit): T {
    if (this == null) block(); return this
}
// 等価コード3
val currentValue = nextValue().applyIfNull { finish() }

kotlin小ネタ:ある値が null の場合は null を、そうでない場合にはその値を用いて初期化された値を取得するサンプル

class Sample {
    private var mStringBuilder: StringBuilder? = null
    
    // letters が null の場合は null を、そうでない場合は letters.length で初期化された StringBuilder を生成する
    fun init(letters: String?) { 
        mStringBuilder = letters?.let { StringBuilder(it.length) }
   }
}

jsvc経由でTomcatを起動する際のタイムアウト設定

tomcat を jsvc 経由で起動する際に、コンテナ起動時にエラーが発生していなくても exit status が 1 になる現象に遭遇したのでメモ。

原因

tomcat の起動(全warの起動含む)が、jsvc 内部で SERVICE_START_WAIT_TIME 変数として指定された時間内に完了していなかったため、結果としてコンテナは正常に起動しても exit status 1 を返していた。

対策1

  • daemon.sh を /etc/init.d/tomcat にコピーしてそれを直接叩く場合は、下記のようにタイムアウト時間(秒)を指定することにより、タイムアウト前に起動が完了すれば exit status として 0 を返すようになる。
/etc/init.d/tomcat --service-start-wait-time 25 start 

対策2

  • service を利用する場合は、bin/setenv.sh に以下のようにタイムアウト時間を設定すればOK。
SERVICE_START_WAIT_TIME=180

三項演算子のような if-then-else 処理

三項演算子のような if-then-else 処理

[ testの評価式 ] && 真の場合の処理 || 偽の場合の処理

真の場合の例

$ [ "a" = "a" ] && echo "OK" || echo "NG"
OK

偽の場合の例

$ [ 1 -eq 2 ] && echo "OK" || echo "NG"
NG

サブシェル内部の変数を参照しようとして失敗する例とその対策

6つのランダム値を作成し、その中の最大値を得るというスクリプトの例

失敗例
#!/bin/bash

# このシェルでランダムな値を6つ作成して、パイプラインで while 文に渡し、
# while 文内部で最大数を取得する。
printf "%s\n" ${RANDOM}{,,,,,} |
  while read num
  do
    [ $num -gt ${biggest:=0} ] && biggest=$num
  done

# 最大数を表示しようとするが、パイプラインの先はサブシェル内で実行されるため、
# サブシェル内で格納された結果をこのシェルで参照することはできない。
printf "The largest number is: %d\n" "$biggest"

結果

The largest number is: 0
リダイレクトを利用した例
#!/bin/bash

# サブシェルでランダムな値を6つ作成して、このシェルの while 文にデータをリダイレクトする。
while read num
 do
 [ $num -gt ${biggest:=0} ] && biggest=$num
 done < <(printf "%s\n" ${RANDOM}{,,,,,})

# while 文はこのシェルで実行されるので、結果をこのシェルで参照することができる。
printf "The largest number is: %d\n" "$biggest"

結果例

The largest number is: 26815
リダイレクトを利用しない例
#!/bin/bash

for num in ${RANDOM}{,,,,,}
 do
 [ $num -gt ${biggest:=0} ] && biggest=$num
 done

printf "The largest number is: %d\n" "$biggest"

結果例

The largest number is: 32654

Muninメモ

参考情報

学習方法

注意点