関数、メソッド、ラムダってなに?

数学が本当に苦手なので、このあたりの違いがモヤモヤしたまま時間が数年過ぎた気がする。

Rubyはオブジェクト指向言語って言われる。

オブジェクト指向言語の世界では、オブジェクトがあって、メソッドがオブジェクトに生えている。
私たちが何かしたいと思ったら、オブジェクトに生えているメソッドをつっつけばいい。
オブジェクトは何ができるの?という疑問は、私たちは持たなくても大丈夫。
オブジェクトがどんなメソッドを持っているのか見ればいい

Rubyでは「名前重要」という文化があるので、メソッドの名前を見ればその動作がだいたいわかる。

一方で、関数はそういうわけにはいかない。
オブジェクトに、あなたに適応できる関数は何ですか?と聞いても「さあ…?」と言われる。
この世界のオペレータたる人間は、頭の中に関数リストを保有していて、それぞれの関数の具体的な操作内容をよく把握していなければならない。

ここからは想像の話になる。私はRubyが好きで数学が苦手である。Rubyの開発者は松本さんである。とあるインタビューによるとRubyの開発者の松本さんも学生時代に数学が苦手だそうである。だから私も松本さんもRubyが大好きで数学が苦手である。よって私はRubyは数学が苦手な人に親和性があるという仮説を持っている。Rubyプログラミングの特徴は、数学が苦手な人にやさしく設計されれているのではないか。

それが、Rubyでは人間が関数のリストを管理しなくてもよいという点だと思う。

Rubyでは、methodはオブジェクトではない。そのかわりProcというものがある。lambdaというものもある。
lambdaは使ってみるとたぶん結構便利なのだが、あまり使われていない。

それに対して、データサイエンスの世界の言語、JuliaやRでは、関数が一級市民である
Rでは、ライブラリーを読み込むと、トップレベルににょきにょきと関数をはやす。
Ruby市民としては、こんなにトップレベルに関数を生やして大丈夫なのかと心配になるほどだ。

コンピュータの中で実際に何がどう動いているかはともかく、私はRubyでオブジェクトのメソッドを呼ぶとき、
オブジェクトが主語となって、何かを処理しているようなイメージを持っている。プログラミングとはオブジェクトに司令を出すことである。
思うに、関数を実体として把握するのに向いている脳の人間と、そうじゃない人間がいる。

個人的には関数のざらつきみたいな質感を感じることができない。これが数学が苦手な理由だと思っている。
(でも物理は好きだ。そこでは力とか電磁場とか、何かしら実体の触れそうなものが登場するから。)

関数の主語は一体誰だろうか?オブジェクトが主語でない以上、コンピュータや人間が操作していると考えなければならない。
主語不在のまま操作だけの思考を進められるかどうかは、数学の特異と不得意の分かれ目になっているのかもしれない。

話は変わって、関数型言語では参照透過性とかいうのが尊ばれる。
参照透過性が何かっていうのはよくわかっていないが、Jupyter Notebookで、セルの実行順序を色々変更すると、結果がぐちゃぐちゃになるようなアレが発生しにくいことではないかと個人的に思っている。
Rubyのようにオブジェクト指向を追求している言語は、その性質上参照透過性が保障されにくいような気がするけどよく理解していないのでわからない。

最近はGitHubとか流行って、有限なリソースである「開発者をたくさん集めたら勝ち」みたいな風潮もあるけれども、Rubyがデータサイエンスや機械学習であまり普及しない理由はこういう基礎的なプログラミング言語の性質に求めるではないかという気がしている。開発者を集める話は、あまりおもしろく
ないからである。

個人的には便利すぎる map とlambda の関係の間には闇があって、それがデータサイエンス用のツールを作る上で大きな障害の一つになっていると思っている。データフレームDaruなどを見てそれを感じた。

C言語見ている

C言語を見ている。

 C言語ってすごく難しいイメージがあるけど、表面的には、Rubyのオブジェクト指向から、オブジェクト指向を取り除いたような雰囲気を感じる。そう考えればそんなに難しくないのかもしれない。初心者向けの本を読んでいるとポインターという難しいのがあってだな…、という感じで解説されているけど、個人的には「?」である。プログラミングって難しい場所がたくさんあって、その中でポインターは確かにややこしいけど、そんなに特別視するほど難しい箇所なのかなあと思う。でもやっぱりC言語難しい…なんかわかんないけど難しい。

RとかJuliaとか(たまにPython)みてる

今までRubyしか見ていなかったけど、急に他の言語をたくさん見ている。
Rとか、Juliaとか、Pythonもちょっとだけ見ている。

それで頭のなかがゴッチャゴッチャになっている。
新しい概念の切れ端が、あっちこっちにプカプカ浮かんで。
ちゃぷんちゃぷんと衝突している。

それで、プログラムの世界って広いなあって思っている。

でも思ったのと違って全然つらくない。

勉強は他人から求められたり、追われたりしてやるからしんどいのであって、
マイペースでやってるうちは、案外いけるということがわかった。
そのかわり上達しないかも知れないけれど。

散歩をしながら、この世にはこんな景色があるんだな〜って思いながら
一歩ずつ進んでいる、そんな気持ちだ。

それで、あれ?これは、こうなんじゃないか?
っていう仮説とかが、いろいろ思い浮かんだりするけど、まだ、よくわからない。
ある程度全貌がみえてくるまで、数ヶ月かかる気がする。
だから今日はポエムだけ。具体的なことは、なにも書かない。

というか書けない。

オブジェクト指向じゃない世界ばっかり見ている気がするけど、
世間では静的型付け言語が流行っているらしいので、いつかはそういう概念も理解したいね。

RとBioconductorに触れている

Juliaの次はBioconductorのライブラリを試している。

世間ではPythonが人気のようだけれども、生命科学の領域ではPythonが人気とまでは言えない。
Bioconductorの審査制度があったりして、これからも末永くRの天下が続くのではないかという気がする。

Rに慣れていないので、勘違いだったらいけないけれども、
Rubyと全然違うところは、トップクラスにニョキニョキと関数を生やしていくことである。
ネームスペースとか、オブジェクトとかの概念は、弱いようだ。

そういう意味では単純でわかりやすい言語なのかもしれない。

WEB+DBのJulia特集を読んだ

ここ数日、Juliaに少しずつ触れようとしている。

Ruby言語しか知らないので、新しい言語にふれるとものすごくストレスを感じる。
Juliaのデータフレームが使いやすいとは思えず、Daruって意外とよくできているんだなと思ったりした。
Pythonも何回か挑戦したけどあきらめてしまった。Juliaは粘り強くやらないとね。

WEB+DBのJulia特集が出たので読んでみた。Julia1.0が登場した時期なので、これからJuliaを始めるにはちょうどいい時期らしい。

読んでみて、やっぱりJuliaはRubyに似ているなと思った。

 だから一番記憶に残ったところは、Rubyとは全く違うところ…「多重ディスパッチ」だ。データの操作とデータの定義が分離しているとのことだ。これはRubyと違う。真っ先に思い出したのは、Crystalのオーバーロードである。Crystalは、メソッドの中で型を判定しようとはせず、引数の型ごとにメソッドを別々に定義する。これは便利な機能である一方で、制約にもなると思う。

 Rubyの場合、引数の型が何であるかはわざと曖昧になっていて、型の判定はメソッドのなかでゴチャゴチャやることも多く、その方法も必ずしも一通りではないと思う。最近にはRubyにも型を導入しようとする流れがあるみたいだけど難しいことはよくわからない。

 けれども、JuliaはCrystalとも違う。Crystalはデータ解析向けのパッケージは充実していない。もしもCrystalに優秀な統計・行列計算のパッケージが付属すればJuliaのような言語になったのかもしれない。

 Crystalで特に素晴らしいと思ったのは、crystal コマンドであった。Rubyにおいてbundler(パッケージ管理), yard(ドキュメント), pry(REPLなど)が提供している機能が統一感のある簡潔なインターフェイスで提供されていて美しいと感じた。Rubyのbundlerやyardやpryはもともと外付けのツールで、Crystalのほど一体感があるわけではない。 ところがJuliaはこの点はむしろRubyよりもさらにいい加減にする方針のようだ。パッケージ管理やプロジェクトの管理についてはすべてREPLで行い、コマンドラインツールは使わないようである。確かにREPLの中で新しいライブラリを追加できたり、プロジェクトを作れるのは便利である。でも、これはとりあえず一つのメソッドを作って、その中で様々な型を判定して使い分けるRuby方式に近く、多重ディスパッチの努力までしているJuliaっぽくない…と感じたりする。

 だから、REPLの中で全部やるっていうのは、スタートアップ時期に人を集めるための工夫で、黎明期は便利だけど、ひょっとすると普及後の未来には足かせになるかもなと思った。

 Pythonを勉強している時は、Rubyの方がわかりやすいと感じることが多くて、なんでPythonが群を抜いて素晴らしい言語のように言われているのだろう?控えめに見てもRubyよりも劣っている点いっぱいあるよね?欧米人はこういうのが好きなの?と納得いかないことも多かったけど、Juliaの場合は、Rubyっぽい記法が随所に見られて「これならRubyから乗り換えても仕方ないか。やっぱりPythonの文法よりもRubyの文法の方が使いやすいと欧米のみなさんも思ってたんだね。納得〜」と感じる謎の安心感がある。引き続き勉強していきたい。

Juliaを使ってみた

最近、Juliaという言語がすごいらしいので使ってみた。使ってみたといっても文法とか何もわからないので、Jupyterのセルに、サンプルをコピーアンドペーストして実行しているだけだ。コードの内容はまるでわかってない。

実行してみて思ったのは、なるほど〜これなら普通に流行るだろうなという感想。あと、Pythonのコードを見てるとどうしても聞こえる(コレジャナイ…、ナゼRubyジャナイノ?)という心の声があんまりしない。どーせCodeなんかまともに書けないんだから違いはないはずなのにね。なんでかね。

Julia早いと言われてるけど、実際にはプリコンパイル入るので特に初回の実行に関しては早い印象ない。むしろ遅い。それから、すでにNumPyやNarrayをゴリゴリに入れてる計算に関しては、何倍も早くなるということはなさそうである。

それからデータフレームとか、データを集めてくる部分についてはまだ弱いし、そういう雑多な機能でごちゃごちゃしてくるとJuliaどうなっちゃうのだろうという感じが少しある。そういうJuliaの欠点の萌芽のようなものもすでにありそう。

Python、とくにpandasを置き換えるかどうかはわからないけど、相当流行るのは間違いなさそう。

バイオでもゲノムのマッピングのようなマシンパワー食う操作についてもC++で書かれたツールと匹敵するぐらいの速さが出たら面白いと思う。

Orangeすごいなあと思った

世間ではCloud AutoMLが流行しているようだ。

Google先生の戦略は「生産手段の私的所有が基本となっており、生産手段を持つ資本家が労働力を購入して商品を生産する。」みたいな大昔マルクス先生が主張された世界観を一世紀遅れで実現しているような気がして、あまり好きになれない。

生産手段を誰もが手にするためには、データセンターをみんなが作れるようになる必要があり、誰でもCPUを生産できるようにする必要がある。けれども、さまざまな政治的な思惑から、技術を禁止しようとする動きがあちこちで起きているようである。

これはそんなにおもしろい話ではない。なので注目している人が少ないであろうOrangeの話を書く。

Orangeは、スロベニアの リュブリャナ大学が開発しているScikit-Learn, Numpy, ScipyなどをGUIで操作できるようにするラッパーである。Githuのリポジトリをちらっと見た感じだと、全部Pythonで書かれているようだ。

なぜOrangeを知ったかというと、Anaconda-Navigatorがゴリ押ししてきたからである。ゴリ押しだなあ!と思ったので最初はいい印象がなかったが、とあることから使ってみて「これはすごい」と思った。

少なくとも、僕のようなど素人が、せこせことPythonやRubyのコードを、拾ってきてはJupyterにコピペするよりも、遥かに高速にかつ確実に解析ワークフローが作れるのである。Orangeが実現したUIは、将来的にどこか大企業が製品を発表して、Excelのように普及していくのではないだろうかと思った。MSがパトロンをやっているAnacondaがOrangeをゴリ押ししているので、Microsoft製品がそっちの方向に進化していく可能性もありそうだ。

しかし「すごい」と「普及」はまったく次元の違う話である。OrangeはPythonですべてGUIを書いている。ここから想像されるように、動作はもっさりしており、信頼性はあまり高い感じではない。そういうわけでOrange自体が今の形で普及することはないだろう。

なによりもスロベニアの大学が開発しているところが厳しい。プロダクトが普及するかどうかは、そのプロダクトの最初のコンセプトの輝きよりも、開発団体の体力で決まってしまうところが大きい。たとえ開発が継続できても、より大きなプロジェクトがやってきて飲み込まれてしまう。

そういうわけでOrangeは10年後にはなくなっている可能性が高いとは思うけど、言いたい。私はすごいと思いました。

どうしてOrangeがマイナーな存在なのか、ということを考えると、「データのローカリティ」ということが思い浮かぶ。Ruby用のクラスタ計算ソフトPwrakeでもデータのローカリティが計算速度に大きな影響を及ぼすとしている。ゲノム解析ではデータのサイズが大きすぎるので、データのダウンロードが一番大変な作業である。

OrangeはWebを用いたGUIではなく、Qtを使用している。もちろんsshでX11を使うという方法もあるかもしれないが、このソフトウェアは、基本的には手元のPCで手元のデータを処理することを考えているといっていいだろう。

私たちは、データは価値そのものだという現代的な価値観に染まりすぎているので、データのローカリティについて考える時、どうしても何か感情が邪魔をする。そんなことを考えた。

Rumale の分類器を比較してみる その1

Rumaleの分類器を比較してみた。
Gnuplotを使っているのだが、missing blank lineという残念な仕様があったりして、なかなかコードがキレイにならない。Gnuplotは高機能だけど一貫性がなくて流行らないわけだと思う。
今日できたところまで。ちゃんと整理ついたらQiitaとかに投稿したい。

RubyとDaruのイテレータについて

最近RubyのDaruを使っていて、もやもやと考えていることがある。

しかし頭がまとまらない。理由の一つはRubyのコードしか書いたことがないので知らないプログラミング概念がたくさんあるからかもしれない。そういうのを勉強すれば、もっとクリアな理解が得られるかもしれないという気がする。

習熟できなくても、概念に触れることはできるはずで、無理だと思わずに、C++やらrustやら難しいものを適当にかじってみた方がいいのかもしれない。しかし、今考えていることをアウトプットしておく。

Daruの使い方を調べていて、混乱したのが、イテレータであった。map や each である。私はmapが大好きだ。しかし、どうも最近mapがいかがわしく感じるときがある。

DaruにはVectorというクラスがある。データフレームは、ArrayとHashとNumPyの機能が全部必要だから、新しいクラスが必要なのだ。mapすると、Arrayが返される。これが直感に反する。Arrayではなく、Vectorが返ってきた方がよいのではないか。

それに、Daruを全面的に信頼できなくて、結局to_aを使ってしまうのである。こうなると、ArrayやHashを使うことになり、Daruの機能を使わないことになる。

そして、一度mapに疑問を持つと、いかがわしく見えてくるものがある。ブロックである。

私は上のコードが好きだ。わかりやすい。一方で、自分でイテレータや、yield を書くほど、プログラミングできるわけではない。ブロックを受け取るようなメソッドを自分で作ることない。

話がとぶが、Rubyを使い始めた頃、メソッドがオブジェクトではないのがすっきりしなかった。動的にメソッドを定義したり、削除したりすることはできても、メソッド自体はオブジェクトではない。

みたいな書き方ができない。Rubyでは、メソッド、Proc、lambda、lambdaのあたらしい書き方、ブロックなど、関数っぽいもがたくさんあって、ゴチャゴチャしているのである。

最初はDaruのイテレータが混沌としているのは、Daruの設計が悪いからだと思った。

けれども、ひょっとするとこれはArrayやHashを使わずに独自のクラスを設計すると常に発生する問題かもしれないと感じたのである。なんでもやってくれるArrayと、mapと、オブジェクトではないブロックの組み合わせは、ひょっとすると、本当はいびつなのかもしれない。どんな作業でもArrayを使うからあまり気にならないだけで。

だとすると、Arrayによく似たオブジェクトとイテレータを設計するのは難しい。もしApache ArrowのようなバックエンドのライブラリがRuby用の新しいデータフレームに採用されても、Rubyらしいイテレータを作成しようとするとまた困ってしまう。

map はブロックではなく、オブジェクトを引数に取る方がきれいかもしれない。そして、ブロック、メソッドは1種類のオブジェクトの方が美しいかもしれない。mapはArray以外のオブジェクトに対しても適応されることがあるので、Array以外のオブジェクトを返却する方が自然かもしれない、などと素人考えで思ったりする。

ruby 2.6 が出たので触ってみて、python と比較してみた
という記事を読んでみて、lambdaをフル活用したRubyが新鮮だったこともあり、そんなことを考えた。

こういう素朴な記事は、よく知っている人にとっては、恥ずかしくて書けないんだろうと思う。わからないことだらけだ。

想像だけど、きっとブロックをオブジェクトにするには、なにか実装に大きな問題があるのだと思う。そうでなければ、何でもオブジェクトにしたがるRubyで、ここまでグチャグチャしているはずがない。ブロックは、周囲のスコープを眺めることができる。つまり、ブロックは定義された位置に依存する存在なので、オブジェクトにするのには何か支障があるのかもしれない。

日本語でもそういうことはよくある。「県立図書館」がどの建物を意味するのかは、その単語が使われた都道府県によって全然違うだろう。ヒトは情報を処理する時に、そういう位置依存・文脈依存的な処理をフル活用している。自分だけではなくて、周囲環境が考えてくれてると言ってもいいかもしれない。

データをクレンジングを行う作業のうちいくらかの部分は、そのような文脈依存を剥ぎ取るための作業だと感じるときがある。

Daruのメリットを考える

Qiitaに投稿したDaruを使うから主観が強すぎるところをブログに移動しました。

Daruのメリットを考える

データサイエンスのツールとしてプログラミングをやりたい人が気にするのは次のような点だろう。

  • Daruは信頼できるのか?
  • Daruには継続性があるのか?
  • Daruのバグは少ないのか?

 正直に言うと、いずれもあてはまらない。Daruの信頼性はあまり高くなく、熱心に使い始めると小さなバグをそこかしこに見つけることができるだろう。Daruはビジネス上の緊急の問題解決に応えるためのツールではないのである。しかし、Daruのソースコードは小さく、速度に最適化されていないため、詳しくない人でも読むことができる。

 Daruを使ったデータ分析は、ビジネス上の問題を解決することや、Kaggleで高得点を出すことから、少し離れたところにある。一番効率的なツールを使って、最高の手段で問題解決に資したいと思うのは自然なことだ。そして、そのことで周囲から評価されたらなお嬉しいと思うだろう。
 ところが、そうやって問題解決のために自分を最適化することは、よいことばかりではなく、一歩引いて見るとある種過学習のような状態におちいっているケースがある。
 よくもわるくも、Daruにはそのような心配がない。これがRubyでデータ処理をやろうとする隠れたメリットの1つかもしれない。

もちろん、そのようなメリットがあるのは理解できるけれどもデメリットの方が大きいだろう、というのが一般的な考え方だろうなとは思います。