Posted at

Thenライブラリみたいにインスタンスの設定に利用できるカスタム演算子…

More than 3 years have passed since last update.

Thenというインスタンスの設定を簡潔に書けるライブラリがあります。が、デフォルトではNSObjectを継承するクラスで利用可能なだけで、独自クラス・構造体ではThenプロトコルを付与する必要があります。

それって面倒…

なので汎用的に利用できるカスタム演算子を作成してみます。


infixな演算子

infix operator  { associativity left }

func <T>(lhs: T, @noescape rhs: inout T -> ()) -> T {
var _lhs = lhs
rhs(&_lhs)
return _lhs
}

…を演算子にしてみました。使い方は以下のようになります。独自構造体でも利用できています。

let button = UIButton(type: .Custom){

$0.setTitle("title", forState: .Normal)
}
button.currentTitle // "title"

struct A {
var text: String?
}

let a = A(){
$0.text = "one"
}{
$0.text // "one"
$0.text = "two"
}
a.text // "two"


prefix/postfixな演算子

この勢いでprefixとpostfixも作ってみましょう。

prefix operator  {}

prefix func <T>(conf: inout T -> ()) -> T -> T {
return {
object in
var _object = object
conf(&_object)
return _object
}
}

postfix operator {}

postfix func <T>(object: T) -> ((inout T) -> ()) -> T {
return {
conf in
var _object = object
conf(&_object)
return _object
}
}

こんな感じでしょうか。

prefixは以下

let conf_a = {

(inout a: A) in
a.text = "prefix"
}
let a_prefix = conf_a(A())
a_prefix.text // "prefix

let conf_button = {
(inout button: UIButton) in
button.setTitle("prefix", forState: .Normal)
}
let button_prefix = conf_button(UIButton(type: .Custom))
button_prefix.currentTitle // "prefix"

postfixは以下

let a_conf = A()

let a_postfix = a_conf {
$0.text = "postfix"
}
a_postfix.text // "postfix"

let button_conf = UIButton(type: .Custom)
let button_postfix = button_conf {
$0.setTitle("postfix", forState: .Normal)
}
button_postfix.currentTitle // "postfix"

のように使うことになります。

prefixもpostfixも上記のような使い方では利用価値が無いように感じますが、高階関数で利用すると良いかもしれません。