プログラマ英語学習日記

プログラミングと英語学習のまとめなど

Customize switch/when of Swift/Kotlin

  • Swift and Kotlin, which are mainly used for Mobile Application, have more powerful functions than their based languages - Java and Objective-C, and the two langauges have similar functions.

I think that many people using those language love Non-Null and Extension-Function, but that few people use Customized-Switch-Statement. You can create your switch-condition in both languages. and it's useful (when properly used).

In this article, I'll make customized switch(when)-case that takes 2D-Point as a paremeter and checks the point within specified Rectangle areas.

Swift

In Swift, You need to create ~= Custom Opertion

The the type of first argument is the type used in case condition and the second is the parameter passed to switch statement.

Here's an example:

struct Point {
    let x: Int
    let y: Int
}
struct Rectangle {
    let x: Int
    let y: Int
    let w: Int
    let h: Int
}
//custom operation
//return true when r contains p.
func ~=(r: Rectangle, p: Point) -> Bool {
    (r.x...(r.x + r.w)).contains(p.x)
    && (r.y...(r.y + r.h)).contains(p.y)
}
//
let p = Point(x: 5, y: 10)
let ra = Rectangle(x: 1, y: 1, w: 5, h: 5) //not contains p
let rb = Rectangle(x: 3, y: 4, w: 8, h: 10) //contains p
let rc = Rectangle(x: 10, y: 1, w: 10, h: 20) //contains p

//
switch p {
case ra: print("A")
case rb: print("B") //match
case rc: print("C")
default: print("Default")
}

//Result
// B

This function is not only used in switch but also in if condition. (Because it is only a operator function!)

if r1 ~= p {
    print("A")
} else if r2 ~= p {
    print("B")
} else if r3 ~= p {
    print("C")
} else {
    print("Default")
}

You should consider the balance of Writability and Readability. These functions sometimes make your code less readable.


Kotlin

To create similar program in Kotlin, you need to create contains in Rectangle.

object IsEven {
    operator fun contains(value: Int): Boolean {
        return (value % 2) == 0
    }
}
fun main() {
    for (i in 0..5) {
        when (i) {
            // use `in` keyword
            in IsEven -> println(i)
            else -> {}
        }
    }
}

//Result
// 0
// 2
// 4

To adapt Point and Rectangle problem that we saw above, create contains method in Rectangle class.

data class Point(val x: Int, val y: Int)
data class Rectangle(val x: Int, val y: Int, val w: Int, val h: Int) {
    operator fun contains(p: Point): Boolean {
        return this.x <= p.x && p.x < (this.x + this.w)
          && this.y <= p.y && p.y < (this.y + this.h)
    }
}

fun main() {
    val p = Point(3, 4)
    val r1 = Rectangle(1, 2, 1, 2)
    val r2 = Rectangle(2, 3, 4, 2)
    when (p) {
        in r1 -> println("R1")
        in r2 -> println("R2")
        else -> println("Nothing")
    }
}

//Result
// R2

Another way: You can create special class for when-pattern.

data class Point(val x: Int, val y: Int)
data class Rectangle(val x: Int, val y: Int, val w: Int, val h: Int)

class RectCheck(val r: Rectangle) {
    operator fun contains(p: Point): Boolean {
        return r.x <= p.x && p.x < (r.x + r.w)
         && r.y <= p.y && p.y < (r.y + r.h)
    }
}


fun main() {
    val p = Point(3, 4)
    val r1 = Rectangle(1, 2, 1, 2)
    val r2 = Rectangle(2, 3, 4, 2)
    when (p) {
        in RectCheck(r1) -> println("R1")
        in RectCheck(r2) -> println("R2")
        else -> println("Nothing")
    }
}

This pattern enables you to create more complex pattern for it can handle two or more arguments that are passed to the constructor (or instance-variable: I suppose this makes code complex).


Conclusion

In this article I showed the way to create custom when(switch) pattern.

This sometime enables you to write code easily but sometimes make the code less-readability. Please be careful when you use these patterns.

Enjoy Coding!


今回はプログラミングネタでいってみました。それも初心者ネタでなく、初心者から中級者ぐらい向けのネタでしょうか?
タイトルは短く、かつキャッチーにしたいので本文以上に難しいですね。

あと接続詞を使わないようにするのがむずかしい。日本人的に使ってしまう(テキトーな英語記事みてると意外と使われている気はしますが。禁じ手らしい文頭Butなどなど)

付け加えるなら、普通は上記の機能を使わなくても組めます。というより便利になるケースがあるかな?(本文といってること違いますが...)。
自分も以前ちらっと見たことはあったのですが詳細は知らなかったので、調べ上げて記事にしてみました。いい勉強になりました。

ちなみに記事作成に約2時間。うち1時間半は調べ物でググってコードを書いてただけです。あまり英語練習になってません(笑) そもそも英語の量が少ないですからね...

また自分でもまとめれそうなネタあったら書いていきたいと思います