だらだらしてたいなぁ

ずっとゲームしながらだらだらしてたいけど、がんばってブログ書いてみた

バカ向け言語 Scala

なぜScalaがバカ向けなのか。
ぼくの経験を元に、バカ向け言語と非バカ向け言語を比較しながら見て行きましょう

非バカ向け言語 C

プログラマーとして最初に携わったのがC言語です。
それは以下のようなものでした。

  • 何十ものファイルにまたがるグローバル変数
  • 緻密な制御が必要であるにも関わらず、無秩序に取得/開放が行われているメモリー管理

このような複雑な構造を、ぼくのようなポケコン並の処理能力しか持たないバカに把握可能でしょうか。もちろん不可能です

そこで、次のようなコーディングを心がけました。

  • グローバル変数を使わず、関数に引数を定義して渡す
  • メモリーの取得/解放を同一ファイル内に限定する

これで、メモリーや変数参照の影響範囲を限定し、ぼくのようなバカでも理解できるようになります。

ですが、わざわざそんな事をやらなくても全てを理解できるエリート様達は、
なぜ引数で渡すんだ。グローバル変数で渡せば簡単に出来るだろう。無駄な事はするな!バカ」と罵ってきます。
「すみません。こうしないとプログラムを把握出来ないんです」とひたすら謝りながら辛い日々を過ごしてきました。

しかし、そこに希望の光が差し込みました。そう、Javaです。

元祖バカ向け言語 Java

今は亡き光の帝国が生み出した仮想機械用言語

javaは、オブジェクト指向という考え方をベースに設計されています。
オブジェクト指向を利用する事によって、変数の影響範囲をクラス内に限定する事が可能です。

つまり、今まで罵られながら行なっていた変数の影響範囲を制限するコーティングを、オブジェクト指向を使うことによって堂々と行うことが出来るようになったのです。
しかも、ガベージコレクションという機能によって、メモリー管理からも開放されます。

ただ、javaはそう簡単には広まることはありませんでした。グローバル変数や複雑なメモリー管理を使いこなすエリート様達にとって、オブジェクト指向ガベージコレクションなど不要な物なのですから。
オブジェクト指向のようなバカ向けの考え方など、受け入れられるはずがありません。

それでも世間のバカには需要があったようで、少しずつではありますが普及し始めます。それに伴い理解あるエリート様もバカのレベルに合わせ、オブジェクト指向を使うようになって来たのです。

ただ、コボラーと呼ばれる上級エリート様達は「そんなバカ向けの考え方など、理解する必要も無い」と全く理解しようともせずに一切を否定していました。確かに仰る通りなので返す言葉もありませんでした。

非バカ向け言語 Ruby

Javaが出てしばらくした後、rubyと呼ばれるオブジェクト指向の動的言語が発表されました。
rubyオブジェクト指向を導入する事でバカに優しく、変数に型を持たない事で、プログラミング能力が低い人達も簡単にコードを書く事が出来る、素晴らしい言語でした。

バカでプログラミング能力も低いぼくはすぐに飛びつきました。確かに簡単にプログラミングが出来ます。しかし、規模が大きくなるにつれてバカ向けでは無い事が分かって来たのです。

まず、型が無いと言う事は、変数がどんな型なのかを全て記憶し把握しておく必要があります。
さらに、rubyでは動的にメソッドが追加出来ます。ライブラリを追加するといつの間にか利用しているクラスの挙動が変わってしまう可能性があるのです。
全ての型を把握し、ライブラリまで細かく理解する事がバカに可能でしょうか。

そうです。rubyはバカ向けを装っていますが、実際はエリート様向け言語だったのです。
もちろん、このようなエリート様向け言語では、バカが生き残る道はありません。仕方なくjavaへと戻って行きました。

第二次デザパタ戦争

javaでの平穏な日々がこのままずっと続くかのように思われていた頃、デザパタと呼ばれ「デザパタ入門」というSpell Bookを装備したエリート様達が現れました。
彼らは「どんな変更にも耐えられる」と呟きながら「リファクタリング」という呪文によって、バカでも理解出来るようシンプルに実装されたコードを複雑な物にどんどん書き換えて行きました。

ぼくは「シンプルに実装して、必要な時にすぐに書き換えるようにすれば良い」と戦いましたが、「プロパー」という強大な権力の前では、その声が届く事はありませんでした。
結果、彼らが通った後には大量のinterfaceと抽象classの荒野だけが残ったのです。
これが後に「第二次デザパタ戦争」と呼ばれるようになった戦いです。

さらに悪夢は続きます。オブジェクト指向によって葬り去られたと思われていたグローバル変数が、「シングルトン」の名の下に蘇ってしまったのです。
また、あの暗黒の時代が訪れるのか…と落胆していた時、Scalaが現れました。

「そのもの赤きオブジェクト指向の衣をまといて、金色に輝く関数型の野に降り立ち、バカ供を平穏の地に導かん」

と言う伝承は本当だったのです。

そして、Scalaへ…

おかしな方向に突き進みそうになっているので、ここで一旦軌道修正してScalaのバカ向け機能について説明しましょう。

オブジェクト指向

scala関数型言語とよく言われていますが、紛うことないオブジェクト指向言語です。javaよりもオブジェクト指向の機能が強化されているので、より扱いやすくなっています。
また、後述の関数型機能や型ライブラリと組み合わせることによって柔軟なコーディングが可能となり、オブジェクト指向の「デザインパターン」は不要になります。

関数型

scalaは関数型機能も持っています。
関数型プログラミングの手法を使うことで変数を使わずに処理を記述出来ます。 scalaでは、val宣言を利用し値を全て定数として扱い再代入を抑制する事で、変数の状態変化を覚えておく必要が無くなると言うことです。
また、参照透過性によって関数に渡された引数が同じであれば必ず結果も同じ事を保証します。
これらの特性によって、オブジェクト指向だけの場合よりさらに考える範囲を限定出来るのです。

//再代入出来ない
val x = 3
x  = x + 10 //コンパイルエラーになる

型ライブラリ

scalaには豊富な型ライブラリがあります。これらを利用する事によって非常に簡単にコーディングが可能です。
以下の例ではsplitで文字列型配列型に変換し、配列型の関数を利用しています。javaで同じ処理を書いて比較してみてください。

//CSV文字列の数字を全て合計する
"33,44,55".split(",").map(_.toInt).sum

型推論

型推論によって、動的言語のように型を書かずにコーディングする事も、型を明記する事も出来ます。
わざわざ無駄な記述をしなくても全てを把握出来るエリート様に余計な負担をかけないようにしつつ、型を書かなければ理解出来ないバカにも優しい素晴らしい機能です。

//エリート様向け
Some(140000) map (_ + 5000) map (_ - 80000)
//バカ向け
val rentSupport:Int => Int = _ + 5000
val dormFee:Int => Int = _ - 80000
val salaryCalc = rentSupport andThen dormFee
Some(140000) map salaryCalc

implicit(暗黙の型変換)

scalaも既存クラスへのメソッド追加が可能です。
暗黙の型変換機能を利用する事によってメソッド追加を行う際に、メソッド追加の影響を限られた範囲に狭める事が出来ます。
また、暗黙変数(implicit)として宣言された引数を暗黙変数のスコープ内で呼び出した場合、省略する事が出来るので、コードがよりシンプルになります。

def f(x:Int)(implicit y:Int) = x + y
implicit val x = 10
f(10) //-> 20
implicit val x = 100
f(10) //-> 110

パターンマッチ

パターンマッチは柔軟性が高くいろいろなパターンを簡単に記述する事が出来ます。
例えば以下のように記述すると、配列の先頭が"2"の場合は先頭を除いた合計を計算。それ以外の場合は全ての合計を計算する事が出来ます。

def f(lst:List[Int]) = lst match {
  case 2 :: xs => xs.sum
  case x        => x.sum
}
f(List(1,2,3,4,5)) //-> 15
f(List(2,3,4,5))   //-> 12
f(List(2,3,4))     //-> 7
f(List(3,4))       //-> 7

代数的データ型

代数的データ型を利用して列挙型を表現する事によって、パターンマッチ時に足りないパターンがあればコンパイラが警告してくれます。忘れっぽいバカにぴったりですね。

まとめ

このように、scalaにはコーディングをシンプルかつ簡単に行う為の機能が沢山搭載されています。
まさにバカ向け言語と言うに相応しいのではないでしょうか。

Scalaスケーラブルプログラミング第2版

Scalaスケーラブルプログラミング第2版


すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!