【JDBC】SimpleJdbcInsertでDEFAULTを設定したEnumのInsert時にcannot be nullと言われる状況への対処

wrongwrong163377.hatenablog.com
前回の記事がトラブっていた原因が判明したので書き直します。

原因

NOT NULLEnumカラムに対して値を指定しない場合、com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column '[カラム名]' cannot be nullになります。

詳細

テーブルの内指定していないカラムに関する値は全てNULLで埋められてしまうため、「NULLをInsertしようとする→NULLは設定できないのでエラー」となります。

前回の記事で書いた↑の内容は正しいです。
ただし、Enum以外(自分が見つけられなかったので他有るかは不明です)の場合勝手にデフォルトを使ってリトライするようで、問題は起きません。

対処

DEFAULTを使いたいカラム名usingGeneratedKeyColumnsに設定すればOKです。

SimpleJdbcInsert jdbcInsert =
    new SimpleJdbcInsert(jdbcTemplate)
            .withTableName("[テーブル名]")
            .usingGeneratedKeyColumns("[DEFAULTを使うカラム名]");

前回のやり方をしてしまうとBeanPropertySqlParameterSourceを使えないので、こちらのやり方が演繹的です。

【Arrow】トランポリンを使う【Kotlin】

wrongwrong163377.hatenablog.com
qiita.com

続きです。

Arrowとは

Kotlinで関数型プログラミングをするためのライブラリです。
以下の記事で知りました。
techblog.picappinc.jp

トランポリンの実装と使い方

GitHubに実装と使い方(相互再帰で奇偶判定)が上がっています。
github.com
github.com

導入方法

トランポリンのみを使う場合は、ideaのライブラリ追加→from mavenから「io.arrow-kt:arrow-free:0.8.1*1」を追加すれば導入完了です。
f:id:wrongwrongwrongwrong163377:20181224172512p:plain
f:id:wrongwrongwrongwrong163377:20181224172437p:plain

実装してみた

簡単な階乗を実装してみました。

import arrow.free.Trampoline
import arrow.free.TrampolineF
import arrow.free.map
import arrow.free.runT
import java.math.BigInteger

fun fact(n: Int): TrampolineF<BigInteger> = when(n < 2){
    true -> Trampoline.done(BigInteger.ONE)
    else -> Trampoline.defer { fact(n-1) }.map { x -> x * n.toBigInteger() }
}

fun main(){
    val x = fact(10000).runT()
    println(x)
}
実装の続き

トランポリン含め幾つかの末尾再帰アルゴリズムを実装したものをGitHubに上げています。
github.com

*1:執筆時点の最新版

【JDBC】SimpleJdbcInsertでDEFAULTを設定したカラムへのInsert時にcannot be nullと言われる状況への対処

この記事に書いたやり方でも動きますが、より演繹的な方法が有ったのでこちらもどうぞ。

wrongwrong163377.hatenablog.com

問題

SimpleJdbcInsertでInsert時に、DDLでNOT NULLとDEFAULTを設定したカラムについてMapSqlParameterSourceに値を指定しなかった場合、com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column '[カラム名]' cannot be nullと言われます。

原因

テーブルの内指定していないカラムに関する値は全てNULLで埋められてしまうため、「NULLをInsertしようとする→NULLは設定できないのでエラー」となります。

対策

以下のように、usingColumnsを使って使うカラム名を初期化時に指定することで、問題が発生しなくなります。

SimpleJdbcInsert jdbcInsert =
    new SimpleJdbcInsert(jdbcTemplate)
            .withTableName("[テーブル名]")
            .usingColumns("[使うカラム名1], [使うカラム名2], [使うカラム名3], ...);

【プログラミング】sealed classでトランポリンを実装する【Kotlin】

2018/12/22追記

ArrowというKotlinでの関数型プログラミングを支援するライブラリにトランポリンの実装が有りましたので、Arrowを使った方がいいです。
wrongwrong163377.hatenablog.com

本文

sealed classを使ってトランポリン(Trampoline)を実装します。

sealed classとは

超簡単に言うと便利になった列挙型(enum)です。
どう便利になったかというと、sealed classを継承したクラスごとに状態や振る舞いを記述できるようになっています。

詳しい解説は以下の記事が参考になりました。
qiita.com

トランポリンとは

再帰を末尾再帰に書き直せるようにするデータ構造です。
トランポリンを用いることで、相互再帰のような、通常では末尾再帰に書き直せないコードも末尾再帰として書き表すことができます。

トランポリンそのものの動きを書くと長くなりそうだったので、sealed classを使ってトランポリンを実装することだけを書きます。
動作の仕組みについては以下にまとめました。
qiita.com

末尾再帰について

末尾再帰については以下から続けて幾つか書いているので、よければ参考にしてください。
wrongwrong163377.hatenablog.com

sealed class部分を実装する

トランポリンでは「処理継続」と「処理終了」の2状態、加えてそれぞれの状態の値が必要となります。
「処理継続」の場合は処理として関数が、処理終了の場合は結果として定数が必要となります。

というわけで、sealed classの実装は以下となります。
処理の継続をMoreが、処理の終了をDoneが表しており、値取り出し用にabstractとしてgetValue()を実装しています。

//トランポリン
sealed class Trampoline<T>{
    //処理の継続
    class More<T>(val calc: () -> Trampoline<T>): Trampoline<T>(){
        override fun getValue(): T {
            return calc().getValue()
        }
    }
    //処理の終了
    class Done<T>(private val value: T): Trampoline<T>() {
        override fun getValue(): T {
            return value
        }
    }
    //値取り出し用のインターフェース
    abstract fun getValue(): T
}
トランポリン全体の実装

トランポリンを用いて末尾再帰を行うための関数2つを書きました。
本当はトランポリンのシールドクラス内にstatic関数として実装したかったのですが、Kotlin的にはパッケージレベル関数として記述するのが正しいようなので、外に出して実装しています*1

前述したとおり、これの動きの解説は長くなるので別の機会にやるつもりです。

package trampoline

//トランポリン
sealed class Trampoline<T>{
    //処理の継続
    class More<T>(val calc: () -> Trampoline<T>): Trampoline<T>(){
        override fun getValue(): T {
            return calc().getValue()
        }
    }
    //処理の終了
    class Done<T>(private val value: T): Trampoline<T>() {
        override fun getValue(): T {
            return value
        }
    }
    //値取り出し用のインターフェース
    abstract fun getValue(): T
}

//トランポリンのランナー
fun <T> run(func: () -> Trampoline<T>): T = run(func()).let {
    when (it) {
        is Trampoline.Done -> it.getValue()
        else -> throw Exception()
    }
}
//再帰処理本体
private tailrec fun <T> run(trampoline: Trampoline<T>): Trampoline<T> = when (trampoline) {
    is Trampoline.Done -> trampoline
    is Trampoline.More -> run(trampoline.calc())
}

参考にさせて頂いたコード

実装にあたってはこちらのコードを参考にさせて頂きました。
gist.github.com

*1:参考にさせて頂いたコードでは、companion objectを用いてシールドクラス内に実装しています。

【Vue.js】JetBrains製IDEで.vueファイルのインデントを設定する

.vueファイルを2文字インデントに設定しようとして詰まったので書きます。
ideaには.vueファイルのインデント幅設定がありません。
HTMLやJavaScriptの方のインデントを設定しても反映されませんでした。

設定方法

Preferences > Editor > Code Style > Other File TypesにTab size: 2、Indent: 2を設定すると2文字インデントになります。
f:id:wrongwrongwrongwrong163377:20181214142347p:plain

問題点

当然ですが、.vue以外のファイルも2文字インデントになってしまいます。
何かいい設定方法が有れば教えてください。。。

【プログラミング】末尾再帰を使って反復法(ニュートン法)を実装する【Kotlin】

wrongwrong163377.hatenablog.com
続きです。
数値解析などで用いる反復法も末尾再帰で書いたほうがシンプルになりました。
ということで、今回は例としてニュートン法を実装します。
ニュートン法の解説はネット上にきちんとしたものが有ると思うので飛ばします。

実装

解説は大体コメントに書きました。
閾値にはFloat.MIN_VALUEを指定していますが、これは計算機的に十分小さな値という意味で指定しています。

import kotlin.math.abs

tailrec fun newton(
    f: (Double)-> Double, //f(x)
    df: (Double)-> Double, //f'(x)
    x: Double, //目的の数値
    eps: Double = Float.MIN_VALUE.toDouble() //閾値、floatの最小非0の値
): Double {
    val xnew = x - f(x) / df(x) //値を計算
    if(abs(xnew - x) < eps) return xnew //閾値を下回れば終了
    return newton(f, df, xnew, eps) //それ以外は末尾再帰
}
使う

 f(x) = x^3 - 2として以下のように使います。ただし初期値は収束するなら何でもOKです。

val ans = newton(
    { x -> x * x * x - 2.0 },
    { x -> 3.0 * x * x },
    3.0
)
println("$ans, ${ans * ans * ans}")

これの答えは 2^{\frac{1}{3}}になります。3乗すると大体2になっていることが分かります。

1.2599210498948732, 2.0

汎化

上記ニュートン法の実装では簡単のために漸化式を関数内で実装しましたが、実際には漸化式を渡して貰えば反復法を行うことができます。
漸化式を受け取る形で汎化したものが以下です。

tailrec fun iteration(
    r: (Double)-> Double, //漸化式
    x: Double, //目的の数値
    eps: Double = Float.MIN_VALUE.toDouble() //閾値、floatの最小非0の値
): Double {
    val xnew = r(x)
    if(abs(xnew - x) < eps) return xnew //閾値を下回れば終了
    return iteration(r, xnew, eps) //それ以外は末尾再帰
}

参考記事

ニュートン法の実装と例題は以下の記事を参考にさせていただきました。
qiita.com

2018/12/14追記

無名関数を使っていなかったので修正。

【プログラミング】末尾再帰を使って累乗(バイナリ法)を実装する【Kotlin】

wrongwrong163377.hatenablog.com
続きです。
ネット上のループや通常の再帰を使った実装に比べ、末尾再帰で書いた方がシンプルにバイナリ法を実装できました。

バイナリ法とは

 a^n a^{2^x}を掛け合わせた形に変形することで乗算回数を抑えるアルゴリズムです。 nが整数の時のみ適用できます。
例えば \displaystyle n = 4 = 100{\rm b}*1とした場合、 a^nは以下のように変形できます。
 \displaystyle \begin{align}
a^4 &= a^{2^2 \times {\rm flag}_3} \times a^{2^1 \times {\rm flag}_2} \times a^{2^0 \times {\rm flag}_1} \\
&= a^{4 \times {\rm flag}_3} \times a^{2 \times {\rm flag}_2} \times a^{{\rm flag}_1}
\end{align}
ここで、 \displaystyle {\rm flag} \displaystyle nのビットを示しており、 \displaystyle {\rm flag}_3 = 1, {\rm flag}_2 = 0, {\rm flag}_1 = 0です。
つまり上式は以下のようになります。
 \displaystyle \begin{align}
a^4 &= a^{4 \times {\rm flag}_3} \times a^{2 \times {\rm flag}_2} \times a^{{\rm flag}_1} \\
&= a^4 \times a^0 \times a^0
\end{align}

実装

このアルゴリズムをKotlinで実装したものが以下です。
コメントを書きたかったので改行を挟んでいますが、実質4行で関数全体が実装できています。

tailrec fun pow(a: BigInteger, n: Int, ans: BigInteger = BigInteger.ONE): BigInteger{
    if(n == 0) return ans
    return pow(
        a * a, //a^2^xを作っておく
        n.ushr(1), //nを右ビットシフトして一番下の桁をずらしていく、符号は無視
        if(n.and(1) == 1) ans * a else ans //nの最終ビットが1なら掛け、それ以外は無視する
    )
}

おまけ

バイナリ法無しの計算をpow_nとしてループを使って実装し、以下の状態で動かしてみました。

import java.math.BigInteger
import kotlin.system.measureTimeMillis

//累乗(バイナリ法)
tailrec fun pow(a: BigInteger, n: Int, ans: BigInteger = BigInteger.ONE): BigInteger{
    if(n == 0) return ans
    return pow(a * a,  n.ushr(1),  if(n.and(1) == 1) ans * a else ans)
}

//通常ループ
fun pow_n(a: BigInteger, n: Int): BigInteger{
    var ans = BigInteger.ONE
    for(i in 1..n){ ans *= a }
    return ans
}

fun main(args: Array<String>) {
    for(i in 0..100000 step 10000){
        val time1 = measureTimeMillis{
            pow(BigInteger("17"), i)
        }
        val time2 =  measureTimeMillis{
            pow_n(BigInteger("17"), i)
        }
        println("$i,$time1,$time2")
    }
}
実行結果

 17^{100000}とかまでいくとすごい差が付きますね。
f:id:wrongwrongwrongwrong163377:20181210064747p:plain

*1:100bは2進数表記