CLOSE

"Simple Made Easy" Made Easy(全2記事)

Clojureの設計に見る"simple"という考え方 Simple Made Easyを解説 Part2

2019年7月29日、Opt Technologiesが主催するイベント「Fun Fun Functional (2) 関数型言語Lightning Talks!!」が開催されました。関数型プログラミングについて楽しく学び、知見を共有することを目的に開催されている本勉強会。今回は6名のエンジニアが、関数型プログラミング言語にまつわるユニークな発表を行いました。プレゼンテーション「"Simple Made Easy" Made Easy 」に登壇したのは、lagenorhynque氏。講演資料はこちら

なぜ"simple"を重視するのか

なぜsimpleが大事なのかと言うと、人間には限界があるからです。わけがわからないものに対して信頼ができないので理解をしながら進める必要がありますし、能力的に普通の人は5個ぐらいはできても、10個や20個のものは同時に考えられません。なので、絡まったものを一緒に扱うのは厳しいわけです。絡まっていたら一緒に考えるしかない。なので、絡まっているものは避けようという話です。

結局、絡まっている複雑さは、理解を困難にするということです。

逆に、simpleにすると何がうれしいかと言うと、理解しやすいです。

それに変更もしやすい。当然テストやデバッグもしやすくて、きっとリファクタリングもしやすいでしょうね。関連して、きっと柔軟でしょう。絡まっていないので、途中で差し替えたり置き換えができます。

残念ながら今日の発表は僕はClojureのコードが出せません。哲学的な話ですね。

どのように"simple"にするのか

では最後に、どうやったらsimpleになるのか。これは難しいことですね。分析・デザインの問題になるのでスキルは求められますが、発表の中ではヒントが語られています。

まず「simpleなものってなんだろう?」と考えるきっかけとして、逆に何によって複雑さが生まれるかという話です。そこでRich Hickeyは「complect」という動詞を持ち出しています。

この言葉は現代語ではあまり使われませんが、complexとすごく関係のある動詞です。これは「絡めさせる・もつれさせる」という意味で用いられていて、つまり、あるのもをcomplectさせるというというのは、絡めさせる、複雑な状態に陥れるという意味です。

なので、そのcomplectしているものを探そうという話になります。もしくは、明らかにsimpleなものを最初から使えば良い。

あとは、1から何かを考えるときは抽象化をしようという話です。ここで抽象化とはどういう意味かと言うと、これも本来の意味に戻るとabstract、"tract"は「引っ張る」という意味ですが、"ab-"は「離す」という意味なので、まさにdraw awayのように「引き離す」という意味です。詳細を隠そうというより、むしろ分離する、simpleにするということは、個々の役割に切っていって、それ自体を独立した扱いにしようということです。

なので観察の観点としては5W1H的な話です。whoとかwhatとかwhenとかwhereとかwhyとかhowとか、そういう観点で分析をするのは良いかもしれないと言われています。とは言っても、これはあくまでも抽象的に言っているだけなので、具体的にどう考えるかは難しいかもしれません。

4点目ですかね。simpleにするといったときに、解決をsimpleにするものもちろん大事ですが、問題をあらかじめsimpleにする努力。つまり、分けて考えるようにすることが重要かもしれません。

Clojureの設計に見る"simple"

というわけで、ここまでいろいろ概念的な話をしてきましたが、最後に「Clojureという言語では実際どうなのか」という話をします。

まず1つは括弧の話です。今日の最初で最後のLispコードだと思いますが、Clojureの特徴は括弧を使い分けることです。

これはLisper的には賛否ありますが、これはsimpleを基準にこうなったと言われています。どういうことかと言うと、これは偶然さっきも出てきたFizzBuzzです。

(会場笑)

素朴なFizzBuzz実装の、上がCommon Lisp版で下がClojure版です。

書き分けたときにCommon Lispのコードを見ると、良くも悪くも全部丸括弧ですね。Lispらしい。「美しい」と言う人もいますが、これは丸括弧が役割という面においてcomplectしているという批判があります。例えば引数リストなんですが、defunというのが関数定義で、fizzbuzzが関数名、そのあと引数リストでnという名前の引数を1個取るという意味なんですが、この引数リストの丸括弧、これは関数コールやグルーピングの丸括弧もありますし、役割がごちゃごちゃごちゃしています。

それに対してClojureは、一定程度それを緩和しただけで絶対的に読みやすくなったかは意見が分かれるかもしれませんが、引数リストは角括弧にしたし、グルーピングはやめました。これも賛否ありますが、少なくとも括弧の意味をオーバーロードし過ぎている問題は、一定の解決がなされているということが言えるだろうとRich Hickeyは言っています。

他の例もあります。ここからはまた抽象的な話ですが、Clojureはオブジェクト指向に批判的です。隣の言語という感じがしますけど、ScalaについてはFunctional Programmingとオブジェクト指向プログラミングで仲良くしようという感じがありますが、Clojureは「OOPとかどうかしている」みたいな批判的なことが公式サイトに書いてあります。日本語版もあるのでぜひ読んでみると楽しいんですけど「オブジェクト指向は評価され過ぎだろう」と堂々と書いています。

なぜオブジェクト指向がダメかと言うと、とくにミュータブルオブジェクト(mutable object)を考えると状態の概念、あとは「どれとどれ」という識別、あとはバリュー(value)で値の3つの要素が普通に絡まっているじゃないかと批判をしています。それに対して、あくまで値がほしいなら値が使えばいいという指摘、実際、Clojureはそういう実装/設計になっているのでクラスが出てきません。あくまでマップやベクターなど、イミュータブル(immutable)なデータ構造をそのまま生で使うのが好ましいという文化です。

次に、これは関数型言語だと当たり前です。

とくにHaskellの人も共感できるかもしれませんが、いわゆる変数は値と時間による変化、それを再代入するということは、タイミングによって変化があります。つまり、値と時間が絡まっている。どう切り離すかというと、値は純粋なイミュータブルな値として扱う。時間については専用の参照型で安全に管理します。

Haskellも確かそういうものを扱う管理用の変数がある。Clojureの場合は、atomとかrefとかagentとかを使うと、そんな感じでイミュータブルな値を時間の変化も含めて安全に管理できる仕組みがあります。

また、これもオブジェクト指向批判感がありますが、継承です。継承は型の階層という意味で複数の型が絡まっていると批判されます。

あとはパターンマッチ(pattern matching)。とくに静的関数型言語、ErlangやElixirはパターンマッチを使いますが、パターンマッチはsimpleという観点から見ると、条件分岐かつ、どの値がどうなるかというwhoとwhatの関係が絡まっていると考えることができます。

それに対して、いわゆるアドホック多相(ad hoc polymorphism)的な仕組み、プロトコル(protocol)とかマルチメソッド(multimethod)とかCommon Lispだと総称関数(generic function)とか、もしくはHaskellにある型クラス(type class)とか、そういう仕組みのほうがよりsimpleと言えるでしょう。その観点においては絡まっていません。そもそも(拡張に対して)閉じていないということも言える。

今度こそ最後です。ElixirやScalaで出てくるアクター(actor)も、これもsimpleという観点で見たときに操作する側と操作対象が絡まっているという批判があります。それに対してキュー(queue)を使ったほうが、厳密に言うとブロッキングキュー(blocking queue)を使ったほうがコード的にsimpleです。

例えばClojureだとcore.asyncというライブラリがありますが、これはGo言語のチャネル(channel)みたいな仕組みで、ブロッキングキューを使ってsimpleに並行処理を実現するものです。

あくまでごく一部の例ですが、Clojureのsimpleという考え方が実際の言語に、もしくはライブラリに活かされているという話でした。

Scalaのアクターはcomplectか

というわけで、simpleというのを理解するには「Simple Made Easy」は動画もあるし、もしくは日本語で解説記事を読むこともできるので、ぜひ一通り把握してみるとおもしろいです。ぜひClojureという言語を使ってみてください。

以上です。ありがとうございます。

(会場拍手)

けっこうLTじゃないくらい時間を使わせていただいてしまいましたが、もしこの場でご質問等があれば今……もしくはこのあと懇親会でお話をすることもできると思います。何かあったりしますか? 大丈夫ですか?

質問者:さっきのアクターモデルがcomplectされているという話をされていましたが……。

lagenorhynque:僕はElixirは勉強したてで、あとScalaのアクターはあまり知らないのでそこは具体例を交えて正確に言えないんですけど……そこら辺に詳しい人いますよね?

(会場笑)

彼らに聞いたほうが早い気はしますが、とりあえずイメージの話だけをさせてもらうと、アクターってメッセージを受け取ったらどうなるかというのが並んでいるわけですよね。それを結果的にパターンマッチでやるわけですが、この場合にこうする、というパターンマッチの問題が内蔵されていますね。かつ、そのアクターの実体の中に処理が埋め込まれているという点において、モノと処理というので絡まっている。

それこそオブジェクト指向的な意味での批判がアクターモデルに対しては言えます。よく「アクターモデルは真のオブジェクト指向」という言い方がありますが、まさにそれゆえにその観点においてはsimpleじゃないと言える気がします。

他に何かこの場でありますか? なければ以上です。ありがとうございました。

(会場拍手)

続きを読むには会員登録
(無料)が必要です。

会員登録していただくと、すべての記事が制限なく閲覧でき、
著者フォローや記事の保存機能など、便利な機能がご利用いただけます。

無料会員登録

会員の方はこちら

関連タグ:

この記事のスピーカー

同じログの記事

コミュニティ情報

Brand Topics

Brand Topics

  • 1年足らずでエンジニアの生産性が10%改善した、AIツールの全社導入 27年間右肩上がりのサイバーエージェントが成長し続ける秘訣

人気の記事

新着イベント

ログミーBusinessに
記事掲載しませんか?

イベント・インタビュー・対談 etc.

“編集しない編集”で、
スピーカーの「意図をそのまま」お届け!