ろじかるんるんものがたり

病人が特に何も書かない。無駄だからだ。

Scala Advent Calendar 2017 について & sbt console を -Xfatal-warnings & -Ywarn-unused-import で使う

この記事は Scala Advent Calendar 2016、25 日目の記事です。

今年は Scala Advent Calendar が二か所、Adventar と Qiita の二つのサービスで開催されました。今年も、という方が文脈的には正しいかもしれません。

http://www.adventar.org/calendars/1492

http://qiita.com/advent-calendar/2016/scala

文脈としては、毎年どっちにしようか、と gitter の scalajp/public 等の Scala のコミュニティの一部で悩んでいるうちに、両方で作られちゃって、さあどうしよう、まあいいんじゃない?みたいになる、という流れです。

とりあえず 2016 年分について、2016/12/31 現在の様子を画像で残しておこうと思います。

Adventar

f:id:lyrical_logical:20161231161100p:plain

Qiita

f:id:lyrical_logical:20161231161013p:plain

Scala は本当にここ数年で知名度が上がりました。とはいえ、当然二か所で開催すれば 50 日分を埋めるのは大変です。

Adventar は登録者が全く足りていません。まだ書かれていない日付もありますね。

Qiita はサービスが SEO 頑張ってることもあってか(ご苦労様です)、登録者は埋まっています。が、まあこれから乗っ取るんですが、最終日である 25 日他、数日分が書かれていません。
ちなみに最終日を乗っ取るのは、単純に、来年カレンダーを(特に Qiita 側で)作る人の目に留まりやすいかな、というだけです。他の日でも、Adventar の空いてる日でも、なんなら Advent Calendar として書かなくてもいんですが、一応。

年が変わるまで(あと 7 時間…)、もしくは年が変わってから記事を遅れて書かれる方もいるかもしれませんが、矢張り年内には埋めたいですし、今の状況はとても悲しいものがあります。他の言語や何らかの Advent Calendar が穴あきだったり記事が書かれていなかったりして残念だなと思ったことはありませんか?Scala もそうなっているのが現状です。

サービスの機能を使って Advent Calendar を作ることなんてユーザの自由だ、という主張もあると思いますが、Scala という名前を冠している以上は、コミュニティの一員である、そうであると見做されることを意識してもらう必要はあると思います。

ということで、来年こそはしっかりカレンダーを埋められるように、本来の Advent Clanedra のように毎日ワクワクできるように、カレンダーを作る人はカレンダーを作る前にコミュニティに相談をするなり、コミュニティはコミュニティで先手を取って両方作っておいて片方のサービスからもう片方のサービスへ「今年はこちらのサービスで開催しています」とフォワーディングして対応をとるなり(案の一つです)、何らかの手を打つべきだと思います。

(これは余談ですが、Scala という言語は知名度が上がった割に形の定まったコミュニティというのがないので、このようなことになりやすいのかなという気がします。そういうコミュニティのほうがいいのかどうかは別の話なので、この話はここで終わりです)

Scala 2.12 のリリースは当初の予定より本当に本当に大幅に遅れましたが、それでもちゃんとリリースされました。2017 年はライブラリの 2.12 対応も進み、本格的に Scala 2.12 が使われていく年になるのではないかと思っています。躍進の年にしたいですね。
実務での採用例も一気に増えて…るんじゃないかなあ。自分の話になってしまいますが、今年夏から冬にかけて、色々な会社へお仕事の相談をさせて貰いに行ったりしたのですが、割とどこへ行っても ScalaScala でした。別に自分は Scala で営業してるわけでもないので、行く先々で ScalaScala 言われているといった感じでした。皆 Functinal だとか Resilience だとか reactive だとかに騙さ…なんでもないです。FP は fun & functional だし Resilience は大事だし reactive はサイコー、いいね?

技術的な話がないけれど、Qiita 外の記事だから大丈夫かな?良いお年を!



…やっぱり何かちょっとした Tips 位は書こう。

Scala の警告は、基本的には probably bug です(設定で警告増やしたりできますが)。ので、"-Xfatal-warnings" コンパイルオプションを付けている人は多いと思います。
この時に困るのが、sbt のプロジェクトでそのような設定をしている場合、特によくあるのが "-Ywarn-unused-import" コンパイルオプション等と組み合わさって、sbt の console タスクが使い物にならなくなることです。
これを回避するには、sbt の scalacOption キーに以下のような変更を加えることです。

scalacOption in (Compile, console) -= "-Ywarn-unused-import"

これで、Compile スコープの console タスクにおける scalacOption からは "-Ywarn-unused-import" が取り除かれ、sbt console も無事使えるようになります。万歳。
この話は一応 stackoverflow 等で昔から広まっている知見なのですが、stackoverflow と違う点としては、シーケンシャルな値を扱う SettingKey に対して "-=" メソッドが使えるように sbt が改善されたのを受けて、記述がスマートになっている、という点でしょうか。逆にいうと、この設定(コードですが)が通らなかったら、それなりに古いバージョンの sbt を使ってるということなので、バージョンアップを考えましょう。
これで技術記事としての体裁も保てられるかな?では今度こそ、良いお年を!

Scala のデフォルト引数の評価タイミングとフリップフラッパーズ

この記事は Adventar の Scala Advent Calendar 2016 の 25 日目の記事です。遅れてすいません。まあ登録したのが 25 日だったと思うので許して欲しい。あと忙しかったり体調崩したりしてた。

カレンダーの占めなのでドカンと何か書くべきだし、書きたいことも色々あるのですが、Scala にフォーカスして、となるとぱっと書けるものはないので(ぱっと書けないものはあるけど今は時間がない)、適当にクイズでも。Scala パズルです。

www.shoeisha.co.jp


というわけで早速問題。以下のコードを実行すると、何が出力されるでしょう。

def f(x: Int = { println("flip flap"); 0 }) = x

f()
f()

特に難しくはないです。いきなり正解というのもなんですし、今期の面白かったアニメイションの宣伝でもします。

今期はなんといってもフリップフラッパーズでしょう。すっかり原作付きアニメが増えた昨今ですがオリジナルアニメです(今期はオリジナル多かった気がする)。シナリオ構成が綾奈ゆにこさんだったので一応チェックはしていたんですが、完全にブラックホースでした。ちょうど今日、一部の地上波で最終話が放送されます。

www.flipflappers.com

この記事を見ている頃にはもう放送は終わっているでしょうが…良かったですね!ウェッブで、正確には abema TV で明日最終話見ることができます。なんと最終話放送前に、1 話から 12 話までの一挙放送もあるので、まだ見ていないという方にも優しい構成です。一挙放送の後に WEB での最速配信で最終話という完璧な構成。やったぜ。

abema.tv

話としては、所謂 Girl meets Girl な SF です。
女の子が突然現れた女の子に振り回されて冒険譚します。六話までは深く考えずに見ましょう。毎話毎話、テーマの違う異世界に行って冒険譚をするのが基本的な流れです。うさぎ回(?)あり、サバイバル回あり、ライバル登場回あり、ホラー回あり、シリアス回あり…たまに「あれ話とんだ?」みたいな感じになりますが、後半回収されるので気にしなくていいです。後半、箸休め的にロボ回もあります。一応ある登場人物の重要なターニングポイント回でもありますが。
繰り返しになりますが六話までは、兎に角深く考えずに見ればいいです。それだけで楽しめます。一話完結物見てるつもりで見てればいいです。良く動くし背景も劇伴も演出も凝ってるし、勿論お話も毎話良く出来ています。六話なんて違うアニメをみてたのかな?という感じになると思います。
七話から徐々に風呂敷を畳んでいく流れになります。これを書いている時点で最終回を見られていないので、どういう結末を迎えるのか分かりませんが、とりあえず 12 話までは毎話面白く見ています。

兎に角視聴しましょう。というわけで、そろそろ答え合わせです。出力結果は…

flip flap
flip flap

flip flap flip flap。簡単すぎましたかね。エンディングのサビの歌詞の一部です。もうフリップフラッパーズの話はいい?そんなあ…

デフォルト引数は、メソッド呼び出しのタイミングで毎回評価されます。そもそもデフォルト引数に副作用を伴うような値を置くなという話はありますが、ちょっとしたクイズでした。詳細は SLS 6.6.1 参照。

なんでこんなクイズを出したかというと、Python がデフォルト引数を関数定義時に評価して使いまわすことをふと思い出したからでした。ろくに書いたこともない言語の pitfalls なんてなんで知ってるのか、なんで思い出したのか全く意味が分かりませんが、人間なんてそんなものです。まるで一貫性がない。記憶は揮発性。ろくなもんじゃない。

プログラミングする上で「いつ何が評価されるか」を正しく知っておくことは重要です。例えば、有名な話ですが by-name parameter は call-by-need ではなく call-by-name に評価されます。

def twice(f: => Unit) = { f; f }
twice { println("flip flap") } // "flip flap\nflip flap\n" が出力されます

あとは、無名関数だと思って書いた部分が、実は無名関数内で評価されずに、先に評価されちゃっていた、とか。よくあるやつです。akka-http のドキュメントに丁度よい例がありますね。

val a = {
  println("MARK")
  complete("yeah")
}

val b = complete {
  println("MARK")
  "yeah"
}

`{ }` は無名関数とは関係なく、単なるブロック式だというのは Scala 初心者、初学者のはまりがちなポイントの一つだと思います。`{ case => ... }` のようなブロックが Function ないし PartialFunction が期待される文脈で記述されているとよしなに変換されるとかいう、なんでそれ文法レベルで無名関数にしなかったんだよという無駄に複雑なルールもありますしね。誤解しやすい。

他に評価タイミングネタだと shapeless の Lazy トレイトとかあるんですが、こいつはただの call-by-need な semantics を表すものかと思いきや、implicit parameter の解決に絡む闇があり、これだけで記事一つ書ける奴なので…あれ、じゃあそれについて書けばよかったんでは???

ということで、そろそろ TOKYO MX で放送が始まってしまうのでおしまいです。
Scala Advent Calendar にかこつけてフリップフラッパーズ宣伝したかっただけです、すいません。

今年中に記事書くのはこれが最後かな。良いお年を。来年頭は 2016 年に読んだ面白論文紹介記事とかになると思います。

「「What Is Functional Programming? に対する反論」を読んで考えたこと」に対する反応

mandel59.hateblo.jp


何か一々記事まで書いてもらったので、一応…

関数の外部から書き換え可能で、関数の内部から参照可能なmutable変数は、関数への入力として使うことができる。(このような入力を副原因という。)

副原因という、特に有用性のない(私感です、詳細な理由は後述)term をこれ以上使うのは止めて欲しいです。正直元記事に対する一番強い気持ちはこれです。
関数の純粋性を副作用(side-effect)を引き起こす(cause)もの、というと長いですが、前回の記事から参照した中野先生のスライド見て貰えば分かる通り、そもそも元記事で副原因(side-cause)と呼んでいるものは、「定義次第では」副作用に含まれます。

www.slideshare.net

前回の記事でも言った通り、ページ指定したリンクを貼ってもそのページは埋め込めないようなので 27 ページ、また 27 ページで参照されている各種 url を参照して下さい。

関数への入力として使うことができる。

関数への入力は、数学的にもプログラミング的にも引数を指す語として定義されるべきでしょう。認識の相違ですね。ここの認識に相違があったこと初めてなんですが。
元記事や id:mandel59 さんの主張通りに入力を引数以外も含むものとして定義していいなら、例えばプログラムを実行する時間であるとか、そういったものまで入力と解釈することが可能になるのですが、それでもいいならどうぞ、というところです。
多角的に物を見ることは大事ですが、定義が複数あればうれしいかというと、そんなわけはないという話です。腕時計を二つ付けたら、どちらを正確な時間をどうすべきか困りますね。比喩として昔ウェブ上で詩人をしていた人のポエムを使わせていただきました(ランダムにポエムが表示されるので見たい場合は表示されるまでリロードしてください)。

ここで言っている「環境」って、何を指しているんでしょうか?

環境という語は明確な定義をもってして使ったわけではありません。これはプログラミング言語の仕様として環境が定義されているものもあればそうでないものもあるとかそういう事情です、というのは今取って付けたもので環境も通じない人間いないでしょという気持ちで書いてただけです。ということで「一般的によく言われる環境」くらいの意味です。それでは足りないといわれるなら、R5RS の 14.4 辺りの定義に従ってください。

こういう場合も「暗黙的に環境内の変数を参照する」に入るんでしょうか?

前述の R5RS に従えば入ります。入らない「環境」の定義って存在するんですか…?side-cause みたいに作ればその瞬間から存在するでしょうけど…

このくだりはほとんど意味が分かりません。

すいませんがここが分からないのは完全に Ryuusei さんの勉強不足なので勉強してください以外いうことないです。環境に対する理論的な理解も実行時の実際の挙動の理解も足りてないように思います。もしくは理解しているけれど理解していない体で書いてる?いやなんというか、ここ理解できないレベルの人に何か言われたりしないだろうという気持ちがあったので、正直「意味が分かりません」と id:mandel59 さんに言われると全く思っていませんでした。

そもそも書いてもいないことを突然やりだしたように見えます。

一例目は「環境」を言語から触れるようにした例なので、環境の話の文脈からのコード例としては妥当だと主張したいです。
二例目はやりすぎました、無視していいです。

揚げ足取りに見えます。

「このコードに副作用が生じる可能性がある個所はどこでしょうクイズ」の定番なので、副作用の話をしておいてここスルーはないです。せめて前提に陽にその箇所には副作用はないと書いてもらわないと困ります。
これは理論がどうとか抜きに「実務的に」困ります。この関数は純粋ですよとかいって高階関数書いておいて渡される引数の関数が純粋である保証、もしくは precondition をドキュメンテーションなどしていないコードとか書かれたら、普通に困ります。本当に困るので三回書いておきます、困ります。
まあ正直揚げ足取りですと認めてもいいです、どうでもいい。ただ「より注意深く観察すると、ここにも副作用が潜んでいる可能性はありますね?」ということが、ボクの記事を読んだ人間に伝われば、それでいいです。

この定義では、副原因を持たないが副作用を持つ、次のような関数を除外できないのでダメです。

すいません自明すぎて書き忘れました。これは自分の凡ミスです。暇なときに修正します。

ほぼ同じこと言ってますよね

その通りですが全く同じではありません。
まず大事な点として副原因という term は使っていません。純粋性を「副作用をまったく用いない関数型プログラムないし関数型言語を純粋」と定義し、副作用を「「式の値を計算して求める」(評価(evaluation)と言います)以外の動作」と定義していることから分かるように、副原因と呼ばれるものを副作用の一部と認めても良い(陽に認める形では書かれていないが、定義からはそう解釈することができる)ものとして定義しています。ということでまずここが違います。
第二に関数の「入力」について、元記事とは違い「入力を引数、出力を戻り値とする関数を考えることにより」とあるように、明確に関数の入力を引数として定めています。

こういう説明が簡単にできるようになるので、「副作用」と「副原因」を区別するのは有意義だと思います。

前述した通り副原因という term を勝手に作られるのに対して非常に否定的です、有意義だとは思いません。前述したように、副作用の定義の中には副原因と呼ばれるものも副作用とするものが既にあるので、単に混乱させるだけの可能性があるからです。

以上です。

発声練習

声帯というのは、人間がどんなに抑えても感情が出てしまう箇所だと聞いた。例えば、怒りを隠して平静を装って、それが他人には分からなかったとしても、波形には出るそうだ。人間の耳と、声帯のだらしなさを感じる。訓練している人なら波形にも出ないようにできるのだろうか。ちなみに記事の内容とは関係がない。

物凄く久しぶりにカラオケにいったら声がでなくなっていた。
声がでなくなっていたといっても本当に声が出ないとか、高い音が出ないとか、そういうことではなくて、声帯をコントロールする筋肉がまともに仕事しなくなっていた。

一般的に声は地声、裏声の二種類に分けられる。裏声は更に、声帯を開いた息の混じった裏声と、声帯を閉じた息の混じっていない裏声に分けられる。勿論声帯の開き具合で響きが変わってくる。
同じことが地声にも言える。しかしこちらは裏声よりも難しい。声帯の「閉じ具合」が適切でないと、きちんとした発声はできない。これは 1/f の~とかいう難しい話で説明できるんだけれど難しいので省略、まあ車のギアチェンジを想像してもらえばいい。3.25 速とかは存在しない。閉じ具合は一般に高い方に関して言われることが多いけれど、低い方にもある。けれど、とりあえず高い方について書く。これをミドルボイスとか最近は言うらしい。実際にはミドルボイスと呼ばれるものにもギアがいくつもあるのでボクはミドルボイスという語はあまり使わないようにしている。
上で書いた、声が出なくなったというのは、このギアチェンジが咄嗟に、つまり歌っている最中にできなくなったということ。各ギアで声を出すのはまだできた。できたといっても大分安定しなくなっていたし、母音によってはかなり酷いものだったし、各ギアで出せる音の範囲(音域だ)も狭くなっていたけれど…こうなると最近の比較的高い音の多い J-POP は歌えない。何も楽しくなかった。

10 月は営業に忙しくてボーカルレッスンに全く行けてなかったし(月謝…)、11 月には貯蓄が尽きるので辞めたので(まあすぐには辞めれないので実際に退会したのは 12 月なので、矢張り月謝…)、もう三か月近く「適切に」声を出すことをしていなかったのが恐らく原因なんだけれど、たかだか三か月でこれは酷いというか、今までそこまで早く劣化することなかったので、歳を感じる。もしくは病人生活が続いて筋力が下がり続けているのが効いてるのか。

お仕事決まったので二月からレッスン再開することは決めているので、今年中は忙しいので、来年になったら発声練習に週二か三くらいのペースでカラオケボックスへ行って、真面目にただひたすら発声練習しよう…と誓った。

ということで今日お仕事取ってきました。来週月曜からいきなりお仕事スタートです忙しい。

あ、でも今日カラオケ前に三時間ほど話し込んできたから普通に声帯周りの筋肉疲れてただけ説あるな…

What Is Functional Programming? に対する反論

Advent Calendar の季節ですね。技術翻訳 Advent Calendar 2016 のをやっているらしく、その記事の中で、id:opapies さんが以下のような記事を書かれました(訳されました)

okapies.hateblo.jp

訳の品質は兎も角、内容が酷いなと思ったので、反論させてもらいたいと思います。元の記事を書かれた Kris Jenkins さんに届くといいんだけど。まあ別にどうでもいい。訳については、「関数型プログラミング」ではなく「関数プログラミング」と訳すべきかなあくらいしか特にいうことはない。参考。

www.slideshare.net

追記:17 ページ目のリンクを埋め込んだのに最初のページが表示される、はてなブログ君…ということで 17 ページ目を見て欲しい。


まあぶっちゃけると、そもそも英語の方の元記事を読んでいないんだけど…兎に角、さっさと始める。

追記:part2 の map, reduce の部分も含めてちゃんと読んでおきました

この記事で僕が伝えたいのは、君が書くあらゆる関数には二組の入力と二組の出力があるってことだ。

間違いなく、InboxQueue の状態はこの関数の本物の入力だ。

この隠れた入出力にはちゃんとした名前があって、その名を「副作用」という

InboxQueue は、その関数スコープから参照可能な変数の一つに過ぎない。たまたまその関数の環境から触れるというだけで、入力というよりは、環境の中の mutable な変数の一つ、以上のことはないし、これを入力とは呼べない。これはプログラムの状態だ。

言いたいことは分かる。暗黙的に環境内の変数を参照するよりも、陽に変数を取るようにしたほうがいい。例えば、以下のように。

public void processNext(InboxQueue inboxQueue) {
    Message message = inboxQueue.popMessage();

    if (message != null) {
        process(message);
    }
}

しかし * あらゆる * 関数に二つの入力がある、と記事では主張している。つまり上のコードでは不足だろう。
ならもうちょっと別の書き方をしよう。コードは疑似的なもので、こんな API がある言語は知らない。

public void processNext(Frame frame) {
    Message message = ((InboxQueue)frame.getEnvironment.getVariables.searchVariable("InboxQueue")).popMessage();

    if (message != null) {
        process(message);
    }
}||<

あるいは、InboxQueue の状態をある種の precondition としてとってもいいかもしれない。

>|java|
public void processNext(InboxQueueState state) {
    // state を使って何かしたいときもあるかもしれない。以下は一例だ。関数の意味は変わる。元記事では関数の前提条件について何も触れられていないので、これは自分が勝手に加えたものだ。popMessage は blocking API かもしれないし、そうであればこのような前提条件は妥当でない。
    if (state.isEmpty()) throw new IllegalArgumentException("InboxQueue must has some elements.");
    // これは assert を書いて precondition をコード上で陽にしているのと大した差はない。
    assert(!state.isEmpty());

    Message message = InboxQueue.popMessage();

    if (message != null) {
        process(message);
    }
}

一歩譲って、これらをもってして、あらゆる関数には二つの入力がある、という主張を受け入れたとしよう。しかしそれは「関数プログラミングにとって」大事なことなんだろうか。

そんなわけはない。グローバル変数は悪だと言われてきたし、シングルトンパターンはアンチパターンとして今では広まっている。前者はどんなパラダイムであろうと気を付けるべきだし、後者に限ってはオブジェクト指向プログラミングの事情だ。

環境に依存した関数の定義には注意すべし、それは一般に言って正しいことだと思うし、反論するつもりはない。しかしそれを「関数型プログラミングって何?」という文脈で話すのは、違和感が強い。パラダイムに限らず大切なことだからだ。その大事さは、ここでボクが長々と講釈を垂れずとも、グローバル変数やシングルトンへの悪評が保証してくれている。

というわけで、環境も入力であるというのが、妥当性のない主張とは思わないけれど、「関数型プログラミングって何?」という文脈で妥当な主張かといわれると、そうではないのではないか、というのが一つ。

次にいこう。

カプセル化とは、実装の詳細を隠蔽することだ。

実装の詳細を隠蔽すること、実装詳細の隠蔽、implementation hiding には複数の手法がある。カプセル化(encapsulation)はオブジェクト指向プログラミングにおける実装詳細の隠蔽の「手法の一つ」でしかない。
関数型プログラミングって何?」という文脈なら、関数プログラミング、もしくは関数プログラミング言語で一般的な Abstract Data Types(Algebraic Data Types と大体同じだ)による data abstraction を持ってくるのが妥当だと思う。ADT による data abstraction についてある程度知っている人なら、そも「関数プログラミングとは何か」について各自なりの答えを得てそうだけど。
別に具体的な手法に触れず、実装詳細の隠蔽という言葉を出せばよかったのではないかと思う。想定読者をオブジェクト指向プログラマだと断った上でなら、カプセル化でもよかったかもしれない。

次。

これで、この関数は入力(や出力)を隠し持たなくなった。

本当にそうだろうか。上の主張は関数内で読んでいる関数が純粋であるという仮定が成り立つときに限る。"getSchedule" "programAt" が純粋でないなら、そこには状態が潜んでいる。関数内で呼び出している関数のスコープにある状態に触れている、依存している可能性がある。

次だ。

「純粋関数」って何?

ここまでの話を踏まえたうえでなのかしらないけれど、何やら小難しいことをいっているけれど…引数にのみ依存し値を返す、同じ引数に対して常に同じ値を返す関数であるという一般的な説明でよいだろう。

さっさと次。

関数型プログラミングとは、純粋な関数を書いて隠れた入出力をなるべく取り除き、できるだけ多くのコードを入力と出力の関係だけで記述することだ。

前述の通りだ。プログラミングパラダイムに関係なく大事なことである。書籍 Effective Java に「可変性を最小限にする」という項目があったことを覚えているだろうか?

次にいこう。

関数型プログラミング言語」って何?

記事の前提が既に自分にとっては正しいとは言えないので、色々言いたいことはあるが、兎に角前提が違うのに物を語っても仕方がない。

それで全部?

そうだ。

そんなわけはない。

次、これで最後だ。

関数型言語は副作用(副原因)と戦うための道具であって、つまり:

map とか reduce があれば関数型言語になるわけではない

map や reduce を一般化していくと fold、最終的には catamorphism に行きつく。これは ADT(Algebraic Data Types) を church encoding で表現(data representation という)すれば自然に出てくるものだ。ADT は Initial F-algebra によって形式化され…これ以上は話が難しくなりすぎるのでやめよう。というか catamorphism だけでも十分難しいものが出てきてしまっている。
兎に角、これが「関数プログラミング」にとって大切かどうかと言われたら、ボクは Yes と答える。まだ「言語」については何も言及していないので、これは反論ではない。
ここからはボクの考えだけれど、関数プログラミングとは何か、と問われたときの自分なりの模範解答は「歴史的に関数プログラミング言語で行われてきた、関数プログラミング言語に一般的に備わっている機能によるプログラミング手法」となる。言語が先、パラダイムが後だ。パラダイムというのは文化的、歴史的な側面を含むと考えているので、このような主張をしている。
ADT(と pattern match)は歴史的にも現実的にも重要な言語機能であり、それを使ったプログラミングは大事なプログラミング手法だ。よって ADT と深い結びつきのある catamorphism の特殊化である map や reduce は、関数プログラミングにとって大事なものだ。
なんだか難しい話をしてしまったけれど、関数プログラミング言語で map や reduce が良く提供されてきた、利用者がよく使ってきた、これらは妥当な事実だろう。
そろそろ結論にいこう。map や reduce があれば「関数プログラミング言語」になるわけではない、という主張について反論はない。しかしそれらは「関数プログラミング」にとって大事なものだろう。「関数型プログラミングって何?」という文脈でこれらを軽視するのは妥当ではない、とだけ言わせて頂きたい。part2 の内容らしいのし全部訳されているわけではないので、でこの辺にしておく。

関数プログラミング言語とは何か、についてはちょっとしたごたごたが過去にあって、qiita (ここにあるのが悔しい…)に良い記事がある。以下の記事の内容が「ボクの考える」関数プログラミング言語とは何か、とは一致するわけではないけれど、良い記事であることには変わりないし、記事の主張も正しいものだと自分は思える。

「関数型言語」に関するFAQ形式の一般的説明 - Qiita

結論。住井先生がわざわざ記事書いてくれてるんだから、まずそれを読もう。読めば訳された記事がイマイチなのは分かると思う。記事では InboxQueue のような「状態」を「副作用」とは言っていないし、「副原因(side-cause)」なんていう独自な用語もでてこない。

蛇足:住井先生の記事について全面的に賛成するわけでもないけれど、本題から外れるし、ボクが関数プログラミングとはどのようなものだと思っているかを記述することが時間な無駄なことぐらいわかっているので、これで本当に終わる。

以上。

オートマトンと正規表現のお勉強

計算理論の基礎 1 オートマトンと言語を買っていただいたので、少しずつ読んでいる。

計算理論の基礎 [原著第2版] 1.オートマトンと言語

オートマトン正規表現も、齧ったことは何度もあるけれど、きちんと学んだことはなかった。
真っ当な情報系の学部を出ていれば普通はこのくらいの知識は持っているはずだろうけれど、真っ当とはいえない情報系の学部にいたし、卒業もしなかった。
最初は雑に読んでいたんだけれど、丁寧に読んだ方がいいなと思って読み直している。ついでに折角なので記録を取ろうと思う。

以下、メモ。

ちょっと理解に戸惑った箇所についてまとめ。二つの言語に対する連結演算の結果として、空列を受理する明らかに無駄と思われる状態が導入される。例えば p79 の正規表現 ab の例における空列を受理する状態等。これは演算の対象となる言語 A1, A2 それぞれの受理状態と開始状態を仮に q1, q2 とすると、q1 と q2 を等しいとするような操作はないので、新しく状態を導入することで連結を実現している。p71 の遷移関数の上から三番目がこの導入(された状態の遷移)に相当する。

p79 の NFA と等価な最小の NFA について "読者は、それを見つけられるだろうか?"とあるが、

で多分あってるはず… a* から考えて (ab⋃a)* について考えれば割と自明。

追記:
メモを公開すると厳しい突っ込みが入る。

ということで

二つの言語に対する連結演算の結果として、

同じΣを持つ任意の NFA N1, N2 を受理する正規言語 A1, A2 について、A1, A2 の連結演算の結果として~

とかで、以降も同じ。

病人の一日

今日は 10 時前に起きた。

起きたといっても、ボクが言う起きたには色んな意味がある。睡眠から覚醒した。布団から出た。布団から出て薬を飲んで薬が効き始めて動けるようになった。最後の意味で使うことが一番多い。最後の状態になる前に「起きた」をいう相手はいないし、ツイッターにツイートするくらいだけれど、ツイートしても大して意味はないし疲れるだけだ。今日は珍しく、覚醒してすぐ体調が良かったので、起きた旨をツイートした。服用している薬のうちの一つが四時間ほどしか効果がないので、効果が切れて痛みで目覚めればよく眠れず、眠りすぎれば起きる頃にはあちこち痛い状態になる。寝ながら薬が飲めればいいのに。

薬が効くまでは大したことはできない。ツイッターを見ていた。
今日も人々は自分の想像力のなさを認められずに騒いでいた。うんざりして、いい加減認めろとツイートした。誰が誤りのない人生をおくれるというのか。そんな聖人が現実にいるわけがない、馬鹿馬鹿しい。誰だって間違えたり、他人を傷つけたりすることはある。それを認め反省するところから始めないといけないのに、お前のあれはポリティカルコレクトでない、それはポリティカルコレクトでない、そんなことばかりいっている。一見正しそうに見える物事も、見方を変えれば間違いになったりする。主観の相違、見解の相違。命題論理程現実は単純じゃない。それなのに、一々あげつらって、最後にはポリティカルコレクトとは、なんて話をして、お前のポリティカルコレクトは正しい正しくないなんてことを言いあって、それで何がどうなるっていうんだ。
皆さんが自分の健康を主張するようなツイートをする度に、ちくりちくりと痛むボクの心は、体は、一体誰がケアしてくれるんだ。勿論そんなこと本気で望んでいない。自明に無理だとわかっているから。ボクだって、誰かの心をきっと痛め続けているんだろう。少なくとも母がボクの体調の事をずっと気に病んでいることは分かっている。

今日も人々は自分が愚かだということを認められない。

母に心配をかけたくはない。良くなりたいけれど、現実にはどうにもならない。土曜だかに浅草にいってひいたおみくじは吉、病は治るでしょうとのことだった。ボクは、母が自分のために、夫婦で旅行へ行く先々で、お守りだとか、何をすれば願いがかなうだとか、そういうものに縋っていることを知っている。母は別にオカルト信仰者ではない。多分母の気持ちの問題だ。その気持ちの強さに、ボクの 100 円のおみくじがかなうはずはなく、きっと今年も、来年も、再来年も、ボクは病人なのだろう。
ザコンだと思われるかもしれないけれど、どちからというと父親が何考えているのか分からないので、家族について話すとき母親の事しか書けないだけだ。お互い変わり者のようだから、お互いにこいつ何考えてるか分からんと思ってるんだろう。
自分の家庭は世間一般に比べれば恵まれていたと思う。その家族の父子ですらこうなのに、分かり合えるわけない。なんで皆分かり合えるなんて思っているんだろうか。もしくは思っていない、はじめから与えられた武器で相手をやっつけたいだけなんだろう。うんざりする。

閑話休題。母の話以降はこれを書いている今考えたことだ。時系列的には飛ばしていい。

人間に心底うんざりしたあと、記憶がブツンと消えてなくなっている。朧気に覚えているのは、良かったはずの体調が急に悪くなって、あちこちが痛み始めて、動けなくなる前に、何か食べてお薬増やしたほうがいいかな、とか考えていたような…体中のあちこちから発せられる痛みに耐えられなくなって、どうしようもなく、気が付いたら眠っていた。
起きたら、あわれキーボード(HHKB Pro 日本語版)は miniUSB ケーブルをはずされ、床に落ちていた。位置的に自分がふっ飛ばしたらしい。こんなだから miniUSB ケーブルばかり三度も買いなおす羽目になる。兎にも角にも、まず薬を飲んだ。充電スタンドにない携帯を、痛みを我慢しながら苦心して探した。矢張り床に落ちていた。視界の中に入っていたはずなのに認識するのにずいぶん時間がかかった。痛みがボクのすべてを緩慢にしていた。
アプリケーションで今日明日の気圧の推移をみる。見た時点で、数時間前から下がり続けていた。しかもアプリケーションの予想(この数値はどこからきているのだろう)が正しければ、明日の昼まで下がり続けるということだ。地獄だ。地獄がきてた、という旨のツイートした。いつもは気圧が下がっているときは、アプリケーションのスクリーンショットとともにツイートするのだけれど、それをする気もないほど疲れ切っていた。寝てたのに何で疲れるのかというと、寝ている間も体は痛みと、そこからくる緊張に襲われ続けているからだ。ひどい時は一日寝てるだけなのに、緊張し続けた筋肉が筋肉痛になったりする。痛みと同居している。

今日のボクは使い物にならないなと思いながら、TODO リストにどうしても今日やらないといけないものがないかを確認する。ない。横になる。ピンポンと、来訪者を知らせる音が鳴る。難儀して玄関までいくと、テレビアンテナの調子の確認で云々の日程が決まりましたといわれた。そういえばそんなことをすると前にも人がきて、言われたような…日程は大変都合の悪いものだったので、どうしたものかと思ったけれど、変更はできないのだろうなあと思っているうちに、話は終わって帰られてしまった。同じ階には今は誰も住んでいない。目下の問題は、この部屋が散らかっていて、掃除も最近できていないことだ。ここに業者の人を入れるのは忍びない。どこかのタイミングで最低限の掃除をしようと思い、TODO リストに追加した。

そのあとも、矢張り何をしていたのか思い出せない。痛みに打ち勝つぞという強い意志があるときでもないと、気圧の低下でボロボロになった体が発する痛みに、ボクの思考や理性は全く敵わない。ゲームをしようとしていた気もする。そうだ、そしたらアップデートを要求されてうんざりしてやめたのだ。今みたらアップデートは終わっていた。

それで今これを書いている。もう日付が変わる。これが病人の一日だ。勿論今日は特別に悪かった、ここまで悪い日はそう多くない、と思う。良い日もある。

疲れている時は悪いことばかり考えてしまう。痛みに耐えて、無理にでも眠ってしまうのが一番いい。んだけれど、寝ていたものだから眠気が一切ない。どうしたものか。もしかしたら病人の一日はこれから始まるのかもしれない。大層長い一日だなあ…

普段は兎も角、こういう日は、冗談抜きで要介護状態だと思う。結局ご飯も食べられていないし。これが毎日続くのなら違うのだろうけれど、そうではないので、ボクは生活保護以外に受けられる社会的なサポートはないらしい。ご飯も食べられない、まともに動けない、何もできない病人が、信じられる、想像できるだろうか。

これを読む前に想像できた人間だけがポリコレとやらで人間を叩けばいいんだろう。右わき腹の辺りが痛い。何か食べたい。指も疲れたし終わる。