田中久美子「記号と再帰」要約

記号と再帰: 記号論の形式・プログラムの必然
記号と再帰: 記号論の形式・プログラムの必然
記号論を勉強しようとするプログラマ(どんだけ狭いんだ)にはオススメな本(その他の人にはどうだろう)。


簡単に説明しますと、プログラミング言語は当然記号でプログラムを書くんですが、それと記号論を融合させようという本です。
記号論には大きく主流として、ソシュール系二元論と、パース系三元論があります。
プログラミング言語にも流派が二つあって「関数型(Haskellなど)」オブジェクト指向(俺が使っていたJavaなど)」があります。
作者は二元論と三元論の互換性を示し(これで記号論への理解が猛烈に進む)、関数型とオブジェクト指向が二元論と三元論に対応することを示しました(これでプログラマに理解しやすくなる)。

  • 記号の種類と、プログラム言語との対応

二元論のソシュールいわく、記号にはシニフィアン(名前)シニフィエ(内容)がある。
三元論のパースいわく、記号には表意体(名前)直接対象(内容)解釈項(式)がある。
というのは記号論をやった方は何となくご存じかと思います。
ソシュールとパースで共通している部分もありますが、パースには解釈項というのがあります。これはいったい何だ、って話になります。
簡単に言いますと、解釈項とは式のことです。たとえば、「y=x+1」という式があったとしましょう。この「x+1」が式であり、解釈項であり、ということです。
「yってなんですか」「yとはx+1です」というのが内容の定義ですが、そのうち「y」の部分が名前であり、「x+1」の部分が式、解釈項であると言えるでしょう。
この本では、名前やシニフィアンのことを「指示子」、内容やシニフィエのことを「内容」、式や解釈項のことを「使用」と呼ぶことにしています。


なお、この二元論や三元論に合致するプログラミング言語があります。「関数型プログラミング言語」と「オブジェクト指向プログラミング言語」です。
関数型は、プログラム全体で使う関数(プログラマに何かさせる部分)とデータ(プログラムに何かさせる時に使う値の部分)を定義しておき、これを組み合わせて使うことでプログラム全体の処理を行います。
オブジェクト指向は、関数とデータをオブジェクトと呼ばれる枠の中に入れておいて、オブジェクトを組み合わせて使うことでプログラム全体の処理を行います。


関数やデータを定義するときに何かxとかyとかfooとかbarとかrun()とか名前をつけるんですけど(前半四つがデータ用、最後の一つが関数用)、関数型やオブジェクト指向における指示子とはこの名前のことです。
一方、内容については関数型とオブジェクト指向で分かれており、関数型ではデータや関数の式が内容になります。
オブジェクト指向ではデータだけが内容であり、じゃあ関数はどうなるかというと、これが使用に割り当てられます。
それじゃあ関数型には使用はないの? ということですが、プログラム全体が使用に当たります。


関数型ではデータをどう使うかは関数との組み合わせ次第であり、プログラム全体を見る必要があり、データの中にはない。使用は外在的です。
一方、オブジェクト指向ではデータをどう使うかはオブジェクトの中に書いてあり、使用は内在的です。
このように、関数型は二元論と親和性が高く、オブジェクト指向は三元論と親和性が高いです。

  • 記号同士の関係

ハイデガーやパースによる記号同士の関係が描かれていますが、ここでは本の題名にも書いてある再帰(後述)における関係だけを述べます。


我々の感覚では、内容がまずあり、それを指示子が表現する、と考えがちですが、ソシュールもパースもプログラミング言語もそうは考えていません。指示子がまずあり、内容はその後作られる、と考えています。
どういうことか、というのは、プログラミング言語を通してみてみましょう。プログラミング言語は当然パソコン等の上で動くものです。パソコンの記憶領域には番地があって、これをアドレスと呼びます。プログラミング言語はあるアドレスを確保して、そのアドレスの値を操作することができます。アドレスの値をそのときそのときの処理に応じて適切な値に書き換えることがプログラミング言語の骨子となります。


さて、プログラミング言語でデータを用意するのですが、一番過激な書き方では、「y;」と書いて、「値は未定義だが」「メモリにy用の場所を取るよ」と書きます。つまり、値(内容)がない変数(指示子)が可能になってしまいます。プログラミング言語ではこのような書き方が可能なのです。
こんな値のない変数は、このままでは使えないので、値を式によって定義します。「y=3;」や「y=x+1;」みたいに。さっき式が使用であると書きましたが、つまり指示子は使用によって内容を定義する、ということが言えます。
二元論でも三元論でも、記号には最低限、名前付与分節という機能を持つとありますが、指示子はそれ自体で名前付与を行い、また使用を通じて分節をも行う、といえるでしょう。いわば、

    • 指示子(名前付与)→(使用(分節))→内容

という働きがあるということになります。

  • 指示子と内容の関係(省略)

指示子と内容の関係について、二元論のイェルムスレウという人が、メタ言語記号、対象言語記号=間接指示記号、直接指示記号の三つについて論じています。同様に、指示子と内容の関係について、三元論のパースは類似記号、指標記号、象徴記号について論じています。
記号論をやったことがある人はもしかしたらこれらについて聞いたことがあるかも知れません。が、煩雑になるので省略します。ごめんなさい。

この本は「記号と再帰」という題名です。記号については、「指示子と内容と使用を持つもの」として理解できると思いますが(身勝手な願望)、では再帰とはいったい何でしょう。
ここでは「記号の再帰「記号系の再帰の二つについて説明し、特に記号系の再帰のやり方のいくつかを説明したいと思います。

まず「記号の再帰です。
そもそも再帰とは何か? それは「x=x+1」のような自己適用に端を発します。プログラミング言語で繰り返し文を書いたことのある人(ほとんどの人がそうだと思う)だと「あっあれか」と思い出すと思います。xの値がx+1に置き換えられ、それがx+2に置き換えられ、それがx+3に置き換えられ、以下略。という例のあれです。もちろんこのままだと無限大になってしまうので、普通は停止するよう上限が定められているわけですが。
再帰の骨子は、「未定義の値を持つ指示子を用意する」「何かしら使用することで内容=値を確定させていく」というところにあります。さっきの繰り返しになりますが、我々は内容がまずあり、それを指示子が表現する、と考えていますが、これもさっき説明したように、値のない指示子をあらかじめ用意することができてしまいます。このように、「将来定まる値」を「格納する場所」を「メモリに事前に割り当てる」ことを、この本の用語では「投機」と呼びます。
これが一度決まった自分の値を参照するとなると、まず「未定義の値を確定した値にする(x=0)」、次に「値を変更する(x=x+1)」というプロセスが発生します。そしてこれはさっきも書いたように、何か上限に達するまで止まりません(値が自分を参照しない場合は一回で止まります。「y=x+1」だとyが求められたらそれで終わります)。
つまり、記号は、再帰という性質のため、理論上はある種無限の広がりを持つことが可能になるような代物です(普通はメモリは有限なので、このままだとメモリがついていけずに故障してしまうので、繰り返しには上限が定められています)。


さっきの矢印に加えて、簡単に書くとこうです。

    • 指示子(名前付与、投機)→(使用(分節))→内容(未定義の値→確定された値)
  • 記号系の再帰と評価関数

記号が際限なく広がる性質を持つということは書きましたが、次は「記号系の再帰について述べたいと思います。
実は、さっきの矢印には省略したところがあります。指示子の前に入力が、内容の後に出力があるのです。プログラミング言語にはこのようにIn/Outの概念があるわけです。システム外からの未知な何かの入力があり、それを指示子が受け取り、内容に当てはめていく。そしてその結果をシステム外に返す。ということになります。
さっきの矢印に加えて、簡単に書くとこうです。

    • 入力(未知)→指示子(名前付与、投機)→(使用(分節))→内容(未定義の値→確定された値)→出力


では、出力の一部を入力に反映させることができれば?
何のことだと言われるかも知れませんが、普通これにはユーザによる入力があります。システムの出力を見て、ユーザが何かシステムに入力する、ということです(インタラクション)
ユーザにはユーザの「評価関数」があり、これにより出力のうち「良い」ものを入力に反映させることができます。この「良い」「評価関数」というのは、例えばシステムだけでやるとしたら、大量のデータを読み込んで平均を取るという戦略(「自然の鏡」評価関数)がありますが、ユーザがこれを持っている場合は、ユーザが「こうしたいのでこうする」という変更を加えることができるわけです。記号系の再帰とインタラクションの相互作用を「適応」と呼び、こうしてシステムはもっと「良く」なっていく、という次第です。これが記号系の再帰の意義です。
(なお、記号系の再帰そのものは、記号の再帰とは直接は関係ありません)
さっきの矢印に加えて、簡単に書くとこうです。

    • 入力(未知)→指示子(名前付与、投機)→(使用(分節))→内容(未定義の値→確定された値)→出力→ユーザの評価関数→入力→(以下略)


「自然の鏡」評価関数は比較的分かりやすいですが、ユーザの持つ「良い」評価関数はどんなものかよく分かりません。そのせいで、システムがどうすればよりよくなるのかは謎のままです。このせいでシステムエンジニアが努力したり発狂したりするのですが、ある種仕方のないことです。
「良さ」が行きついた先に、この本で言うと「是態」を持つ具体例が生じます。これは具体例であると同時に、どのような抽象的な本質があるべきかの最適なサンプルになるはずです。オブジェクト指向でいうところのクラス(本質)インスタンス(具体例)の関係なのですが、ここでいう「是態」は、クラスでありながら究極のインスタンスであるという、プログラミングの世界ではちょっとうまく表現できない何か(この本でいうと脱構築的な存在)になります。これをどうやって求めるかは謎が多いので、システムエンジニアが努力したり発狂したりするのですが、とりあえずそういう仕組みが働いていることはこの本で示されました。

  • まとめ
    • 記号には三種類の要素があり、指示子、使用、内容がある
    • 指示子は名前付与を行い、使用を通じて内容を分節する
    • 記号の再帰では、名前付与を行った時点では値は未定義であり、値を確定させた後で、繰り返し値を変更できるので、下手すると無限に計算できてしまう
    • 記号系の再帰では、指示子、使用、内容の前後にある入出力をつないでループさせることができる
    • 入出力にユーザとのインタラクションを導入することで、ユーザの評価関数とシステムの評価関数に沿って適応的にシステムを改善できるが、ユーザの評価関数はどのようなものか不明なので、システムエンジニアが努力したり発狂したりする


従来、内容が指示子を定めると考えられてきました。これでは記号はそれ以上発展しません。
しかし、指示子が最初は内容なしで存在しうる、そして使用を通じて内容を定めることができるとなると、記号(具体的には指示子)は内容とは独立に存在しえるし、内容の土台となる、内容より大きな領域を持ちうる、ということになります。そんな馬鹿なと思われるかも知れませんが、プログラミング言語はその実例を示していました。
しかも繰り返しが可能なため内容が無限に書き換えられうる、となると、指示子は内容をいかようにも変えられるし、それは無限に続く、ということになります。
In/Outを持つ記号系もやはり再帰ができるのですが、これは普通はユーザによるインタラクションが必要であり、ユーザの「良い」評価関数が明らかではない=自動化できないので、ユーザにとって「よりよい」システムは記号系が自動的に作れるものではなく(「自然の鏡」評価関数も大量のデータを用意するのは人だし)、ユーザが作るしかないようです。


以上、記号(指示子)は使用によって内容をいかようにでも定義できるけど、人にとって都合の良い記号系は、人にとって都合の良い評価関数が不明である以上、やはり人が関与しないといけない、ということがこの本で言いたかったことなのではないかと思います。
プログラミング言語はある種根源的なものを表わしている究極の記号であるが、人のシステムはやはりしがらみが多い、ということでしょう。
積み木を城にするときに、まったく自然の状態で放っておくのと、人が何かする時では、前者は絶望的であり、後者は容易である。この差は大きい。
しかし、それは積み木の重要性をいささかも否定するものではない。むしろ積み木なくしては何も存在しえないのだ。そんなことを考えさせられる本でした。