読者です 読者をやめる 読者になる 読者になる

default引数

備忘 Python swift3

ぱくりと言われようと、便利なモノは便利なわけで。

swiftもPythonと同じようにdefault引数設定ができるわけだけど、Appleのドキュメントにはあまり明示的にこう使えと書いていないので、備忘。

 

まず、Pythonでもswiftでも私がdefault引数をよく使うシーンは、リファクタリングの時。

例えば、ある関数が外部とのIFとして立てられていたとする。

internal func hoge( ) {....

 ただ、今この瞬間から似て非なる新仕様をぶち込まれ(みたくなっ)て、hogeに引数を待たせたバージョンがあると、全体設計として非常に管理しやすくなるじゃんという状況になったとしよう。

 

Javaなんかだったらこうする。

// テストが通っているのでこれは凍結

internal func hoge( ) {....} 

 

// 新IFとして、新規コードからはこれを呼ぶ

internal func hoge(abc : [Abc]) {...

一般にコンパイラシグニチャで関数宣言を見分けるから。

これはswiftでもPythonでも同じようにできたのでサブセットして道具箱に入れておくといいかもしれない。

 

ただしこれが、デフォルト引数を持っている言語だとこう表現できる

 internal func hoge(_ abc: [Abc] = []) {

    if abc.isEmpty {

        // 昔のhoge()を一文字違えず埋め込むか、sub関数管理にする

        ....

    } else {

        // 新規コードからのIFとして引数版のhoge処理

    }

 Java版もそうだけど、これらの何が嬉しいのかというと、既にコード中にアホほど存在するcaller hoge()はびた一文書き換えなくてすむし、挙動変化が管理しやすい。あと従来関数と機能のfusionがしやすい。

 

なおJava版のほうも決して悪いわけではない。

ファイル長に寛大で、関数単位でバージョン管理するのがしっくりくるようなチームならむしろJava版の方が合っているでしょう。こっちもfusionするならhoge(abc:...)の中で条件によってhoge()を呼べばいい。

要はwrapperで統一IFにする。

 

私的になるたけ1ファイルは低ノイズで主張点だけに絞ってざっと読み込みたいほうなのと、Python流が苦ではないので後者のほうが好きというだけの話。

大事なのは、十分テストされたといえる既存コードは可能な限り保存して、新規コードとは分離できるところ。これがOOPの基本嬉しいこと。

なんなら引数に関数を放り込むIFにして、default nilにしておいてもいい。

 

こうするのがややこしくて、少人数で作ってて、連絡コストがそう高くないなら、hogeをnewHogeと改名する方向でもいいかも

// internal func hoge ...

available(*, deprecated: X.x, message: "ツカウナキケン")

private func hoge() {...}

 

internal func newHoge(....

こちらの方が、新IFからは確実に使えなくなり境界がはっきりするので、状況によっては一貫性を保ってテキスト全置換でいっそ変えてしまった方が理想。

コンパイラは関数名なんざ数列にしか見えてないので。

 

ただし文字ヅラに騙されて変なミス入れ込むのが人間。これが現実。

特に私は間抜けなので、よく全置換をやって、かつコメントも何も残してないもんだから、何時間もうんうん唸って(泣きながら)ふて寝したあとに、そういえばそうだった!とさもエウレカを得たような気分になって正常軌道に戻すことはあるけれど。。。でもそれって気をつけていれば一切支払わなくていいコストだったわけで、結局損失なのでよほどじゃない限り避けるようにはしている。

 

 ちなみに、availableに頼るときはprojectで一貫したwarning controlがされていて、意識的にwarningの見分けが付く状況でないと意味はない。

砂丘の砂粒ほどwarningが存在する中で、"ツカウナキケン"を意識して見わけるのはもはや拷問。