参照透過性という用語はどういう意味ですか?「equalsをequalsに置き換えることができる」と説明されていると聞きましたが、これは不十分な説明のようです。
15 に答える
「参照透過性」という用語は、論理と数学の方法に基づいて自然言語の構成要素、ステートメント、および引数を分析する哲学の一分野である分析哲学に由来します。言い換えれば、コンピューター サイエンス以外では、プログラミング言語のセマンティクスと呼ばれるものに最も近い主題です。哲学者のウィラード・クワインは、参照透過性の概念を開始する責任がありましたが、バートランド・ラッセルとアルフレッド・ホワイトヘッドのアプローチにも暗示されていました。
本質的に、「参照透過性」は非常にシンプルで明確なアイデアです。「参照対象」という用語は、分析哲学で表現が参照するものについて話すために使用されます。これは、プログラミング言語のセマンティクスで「意味」または「表示」が意味するものとほぼ同じです。Andrew Birkett の例 (ブログ投稿) を使用すると、「スコットランドの首都」という用語はエディンバラ市を指します。これは「指示対象」の簡単な例です。
文中のコンテキストは、そのコンテキスト内の用語を同じエンティティを参照する別の用語に置き換えても意味が変わらない場合、「参照透過」です。例えば
スコットランド議会がスコットランドの首都で開催されます。
と同じ意味
スコットランド議会がエジンバラで開催されます。
したがって、「スコットランド議会が ... で会合する」というコンテキストは、参照透過的なコンテキストです。意味を変えずに、「スコットランドの首都」を「エジンバラ」に置き換えることができます. 別の言い方をすれば、コンテキストは用語が何を指しているかだけを気にし、それ以外は気にしません。これが、コンテキストが「参照透過」であるという意味です。
一方、文では、
エジンバラは、1999 年以来、スコットランドの首都となっています。
そのような交換はできません。もしそうなら、「Edinburgh has been Edinburgh since 1999」となるでしょうが、これは非常識なことであり、元の文と同じ意味を伝えません。したがって、「Edinburgh has been ... since 1999」というコンテキストは参照的に不透明 (参照的に透過的の反対) のように見えます。それは明らかに、用語が指すものよりも何かを気にかけています. それは何ですか?
「スコットランドの首都」のようなものは明確な用語と呼ばれ、長い間、論理学者や哲学者の頭を悩ませることはありませんでした。Russell と Quine は、それらが実際には「参照」ではない、つまり、上記の例が実体を参照するために使用されていると考えるのは誤りであると言って整理しました。「エジンバラは1999年以来スコットランドの首都である」を理解する正しい方法は、
スコットランドには 1999 年から首都があり、その首都はエジンバラです。
この文は、くだらない文に変換できません。問題が解決しました!クワインの要点は、自然言語は実際に使用するのに便利なように作られているため、ごちゃごちゃしている、または少なくとも複雑であると言うことでしたが、哲学者や論理学者はそれらを正しい方法で理解することによって明確にする必要があります. 参照透過性は、そのような意味を明確にするために使用されるツールです。
これはプログラミングと何の関係があるのでしょうか? 実際にはあまりありません。前述したように、参照透過性は、言語を理解する、つまり意味を割り当てる際に使用されるツールです。 プログラミング言語セマンティクスの分野を創設したクリストファー・ストラチーは、セマンティクスを意味の研究に使用しました。彼の基礎論文「プログラミング言語の基本概念」は Web で入手できます。それは美しい紙であり、誰もがそれを読んで理解することができます. ですから、そうしてください。あなたは大いに悟るでしょう。彼はこの段落で「参照透過性」という用語を紹介しています。
式の最も有用なプロパティの 1 つは、Quine 参照透過性によって呼び出されるものです。本質的に、これは、部分式を含む式の値を見つけたい場合、部分式について知る必要があるのはその値だけであることを意味します。内部構造、コンポーネントの数と性質、それらが評価される順序、またはそれらが書き込まれるインクの色など、サブ式のその他の機能は、メインの値とは無関係です。表現。
「本質的に」の使用は、Strachey がそれを簡単な言葉で説明するために言い換えていることを示唆しています。関数型プログラマーは、この段落を独自の方法で理解しているようです。この論文には他に「参照透過性」が 9 箇所ありますが、他の箇所については気にしていないようです。実際、Strachey の論文全体が、命令型プログラミング言語の意味を説明することに専念しています。しかし、今日、関数型プログラマーは、命令型プログラミング言語は参照透過的ではないと主張しています。Strachey は彼の墓を回っていたでしょう。
私たちは状況を救うことができます。自然言語は実用上便利なように作られているため、「ごちゃごちゃ、または少なくとも複雑」であると言いました。プログラミング言語も同じです。それらは、実際の使用に便利になるように作られているため、「面倒、または少なくとも複雑」です。それは彼らが私たちを混乱させる必要があるという意味ではありません。意味を明確にするために、参照透過性のあるメタ言語を使用して、正しい方法で理解する必要があります。私が引用した論文で、Strachey はまさにそれを行っています。彼は命令型プログラミング言語の意味を初歩的な概念に分解することで説明し、明確さを失うことはありません。彼の分析の重要な部分は、プログラミング言語の式には 2 種類の「値」があることを指摘することです。r値。Strachey の論文以前は、これは理解されておらず、混乱が支配していました。今日、C の定義では日常的に言及されており、すべての C プログラマーはその違いを理解しています。(他の言語のプログラマーがそれを同じようによく理解しているかどうかは、言うのが難しい.)
Quine と Strachey はどちらも、何らかの形の文脈依存を含む言語構造の意味に関心を持っていました。たとえば、「エディンバラは 1999 年以来、スコットランドの首都である」という例は、「スコットランドの首都」が考慮されている時間に依存するという事実を意味します。このようなコンテキスト依存は、自然言語とプログラミング言語の両方で現実のものです。関数型プログラミングでも、自由変数と束縛変数は、それらが現れるコンテキストに関して解釈されます。あらゆる種類のコンテキスト依存は、何らかの形で参照透過性をブロックします。依存する文脈に関係なく用語の意味を理解しようとすると、やはり混乱に陥ります。クワインは様相論理の意味に関心を持っていました。彼はそれを保持したモーダルロジックは参照的に不透明であり、それを参照的に透過的なフレームワークに変換することによってクリーンアップする必要があります (たとえば、必要性を証明可能性と見なすことによって)。彼はこの論争に大敗した。論理学者も哲学者も同様に、クリプキの可能な世界セマンティクスが完全に適切であることを発見しました。同様の状況は、命令型プログラミングにも当てはまります。Strachey によって説明された状態依存性と Reynolds によって説明されたストア依存性 (クリプキの可能世界意味論と同様の方法で) は完全に適切です。関数型プログラマーは、この研究の多くを知りません。参照透過性に関する彼らの考えは、大雑把に受け止めるべきです。
[追記: 上記の例は、「スコットランドの首都」などの単純なフレーズに複数のレベルの意味があることを示しています。あるレベルでは、現時点での首都について話しているかもしれません。別のレベルでは、スコットランドが時間の経過とともに持っていた可能性のあるすべての首都について話すかもしれません. 特定のコンテキストを「ズームイン」し、「ズームアウト」してすべてのコンテキストを非常に簡単に広げることができます。自然言語の効率性は、そうする私たちの能力を利用します。命令型プログラミング言語は、ほぼ同じ方法で効率的です。変数xを割り当ての右辺 ( r-value ) で使用して、特定の状態でのその値について話すことができます。または、その左辺値について話すかもしれませんこれはすべての州にまたがっています。人々がそのようなことに混乱することはめったにありません。ただし、言語構造に固有の意味のすべての層を正確に説明できる場合とできない場合があります。そのような意味の層のすべてが必ずしも「自明」であるとは限らず、それらを適切に研究することは科学の問題です. しかし、一般の人々がそのような重層的な意味を説明するのが苦手であることは、彼らがそれらについて混乱していることを意味するものではありません.]
以下の別の「追記」は、この議論を関数型プログラミングと命令型プログラミングの懸念に関連付けています。
関数型プログラミングで一般的に使用される用語である参照透過性は、関数と入力値が与えられると、常に同じ出力を受け取ることを意味します。つまり、関数で使用される外部状態はありません。
参照透過関数の例を次に示します。
int plusOne(int x)
{
return x+1;
}
参照透過性関数を使用すると、入力と関数が与えられた場合、関数を呼び出す代わりに、それを値に置き換えることができます。したがって、パラメータ5でplusOneを呼び出す代わりに、それを6に置き換えることができます。
もう1つの良い例は、一般的な数学です。関数と入力値が与えられた数学では、常に同じ出力値にマップされます。f(x)= x +1。したがって、数学の関数は参照透過性です。
この概念は、参照透過性の関数がある場合、自動並列化とキャッシュを容易にするのに役立つため、研究者にとって重要です。
参照透過性は、Haskellのような関数型言語で常に使用されます。
-
対照的に、参照の不透明性の概念があります。これは反対を意味します。関数を呼び出すと、常に同じ出力が生成されるとは限りません。
//global G
int G = 10;
int plusG(int x)
{//G can be modified externally returning different values.
return x + G;
}
もう1つの例は、オブジェクト指向プログラミング言語のメンバー関数です。メンバー関数は通常、そのメンバー変数を操作するため、参照が不透明になります。もちろん、メンバーの機能は参照透過性にすることができます。
さらに別の例は、テキストファイルから読み取り、出力を出力する関数です。この外部テキストファイルはいつでも変更される可能性があるため、関数は参照的に不透明になります。
参照透過性関数は、その入力のみに依存する関数です。
[これは、機能的/命令型プログラミングの懸念に議論を近づけるための努力で、3月25日からの私の答えへの追記です。]
関数型プログラマーの参照透過性の考え方は、次の3つの点で標準の概念とは異なるようです。
哲学者/論理学者は「参照」、「外延」、「指定」、「bedeutung」(フレーゲのドイツ語)などの用語を使用しますが、機能プログラマーは「値」という用語を使用します。(これは完全に彼らのしていることではありません。Landin、Strachey、およびその子孫も参照/表示について話すために「値」という用語を使用していることに気付きました。これは、LandinとStracheyが導入した用語の簡略化にすぎないかもしれませんが、素朴な方法で使用すると大きな違いがあります。)
関数型プログラマーは、これらの「値」がプログラミング言語の外部ではなく、プログラミング言語の内部に存在すると信じているようです。これを行う際に、彼らは哲学者とプログラミング言語の意味論者の両方とは異なります。
彼らは、これらの「価値」は評価によって得られるはずだと信じているようです。
たとえば、参照透過性に関するウィキペディアの記事には、今朝、次のように書かれています。
式は、プログラムの動作を変更せずにその値に置き換えることができる場合(つまり、同じ効果と同じ入力で出力されるプログラムを生成する場合)、参照透過性があると言われます。
これは、哲学者/論理学者の言うこととは完全に異なります。彼らは、そのコンテキスト内の式を同じものを参照する別の式(相互参照式)に置き換えることができる場合、コンテキストは参照または参照透過性であると言います。これらの哲学者/論理学者は誰ですか?それらには、フレーゲ、ラッセル、ホワイトヘッド、カルナップ、クイン、チャーチが含まれますそして無数の他。それぞれがそびえ立つ姿です。これらの論理学者の総合的な知的力は、控えめに言っても驚異的です。それらはすべて、指示対象/外延が形式言語の外に存在し、言語内の表現はそれらについてのみ話すことができるという立場で一致しています。したがって、言語内でできることは、ある式を同じエンティティを参照する別の式に置き換えることだけです。指示対象/外延自体は言語内に存在しません。機能プログラマーがこの確立された伝統から逸脱するのはなぜですか?
プログラミング言語のセマンティストがそれらを誤解したのではないかと推測する人もいるかもしれません。しかし、彼らはしませんでした。
(a)各式はネストされた部分式構造を持ち、(b)各部分式 は何か(通常は数値、真理値、または数値関数)を示します。(c)式が示すもの、つまりその「値」は、それらの他のプロパティではなく、そのサブ式の値。[強調を追加]
ストイ:
式に関して重要なのはその値だけであり、任意の部分式は他の等しい値に置き換えることができます[強調を追加]。さらに、式の値は、特定の制限内で、発生するたびに同じになります。」
式の値は、その構成式(存在する場合)の値にのみ依存し、これらの部分式は、同じ値を持つ他の式に自由に置き換えることができます[強調を追加]。
したがって、振り返ってみると、「参照」/「表示」を「値」に置き換えることによって用語を単純化するためのLandinとStracheyの努力は害を及ぼした可能性があります。「価値」を聞くとすぐに、それにつながる評価プロセスを考えたくなる誘惑があります。それが外延ではないことは明らかかもしれませんが、評価が生み出すものは何でも「価値」として考えることも同様に魅力的です。それが、関数型プログラマーの目から見た「参照透過性」の概念に起こったことです。しかし、初期の意味論者によって話されていた「価値」は、評価や関数の出力などの結果ではありません。それは用語の意味です。
表現のいわゆる「価値」(古典的な哲学者の言説における「参照」または「外延」)を複雑な数学的/概念的対象として理解すると、あらゆる種類の可能性が開かれます。
- Stracheyは、3月25日の回答で述べたように、命令型プログラミング言語の変数をL値として解釈しました。これは、プログラミング言語の構文内に直接表現されていない洗練された概念オブジェクトです。
- 彼はまた、構文内の「値」ではない複雑な数学オブジェクトの別のインスタンスである状態間関数などの言語でコマンドを解釈しました。
- Cでの副作用のある関数呼び出しでさえ、状態を状態と値のペアにマップする状態トランスフォーマーとして明確に定義された「値」を持っています(関数型プログラマーの用語ではいわゆる「モナド」)。
関数型プログラマーがそのような言語を「参照透過性」と呼ぶことに消極的であることは、単に「値」などの複雑な数学的/概念的オブジェクトを認めることに消極的であることを意味します。一方、彼らは、状態トランスフォーマーを自分の好きな構文に入れて「モナド」のような流行語でドレスアップすると、完全に「値」と呼んでいるようです。彼らの「参照透過性」の考え方にはある程度の一貫性があると私たちが認めたとしても、彼らは完全に矛盾していると言わざるを得ません。
少しの歴史が、これらの混乱がどのようにして生じたのかを明らかにするかもしれません。1962年から1967年までの期間は、クリストファー・ストレイチーにとって非常に集中的な期間でした。1962年から65年の間に、彼はモーリスウィルクスの研究助手としてパートタイムの仕事に就き、CPLとして知られるようになったプログラミング言語を設計および実装しました。これは命令型プログラミング言語でしたが、強力な関数型プログラミング言語機能も備えていることが意図されていました。コンサルタント会社でStracheyの従業員だったLandinは、Stracheyのプログラミング言語の見方に大きな影響を与えました。画期的な1965年の論文「 Next700プログラミング言語」で、Landinは関数型プログラミング言語を恥ずかしがらずに宣伝しています(それらを外延的と呼んでいます)言語)および命令型プログラミング言語を「アンチテーゼ」として説明します。その後の議論で、StracheyがLandinの強力な立場に疑問を投げかけていることがわかりました。
...DLはすべての言語のサブセットを形成します。それらは興味深いサブセットですが、慣れていない限り使用するのは不便です。現時点では、命令法やジャンプを含む言語で証明を作成する方法がわからないため、これらが必要です。[強調を追加]
1965年に、Stracheyはオックスフォードでリーダーの地位に就き、命令法とジャンプの理論の開発に本質的にフルタイムで取り組んできたようです。1967年までに、彼はコペンハーゲンのサマースクールで「プログラミング言語の基本概念」に関するコースで教えた理論の準備ができていました。講義ノートは出版されたはずだったが、「残念ながら、編集が遅れたため、議事録は実現しなかった。しかし、オックスフォードでのストレイチーの作品の多くと同様に、この論文は影響力のある私的な回覧を持っていた」。(マーティンキャンベルケリー)
ストレイチーの著作を入手することの難しさは、人々が二次資料と伝聞に依存するという混乱を広めることにつながる可能性があります。しかし、「基本的な概念」がWebですぐに利用できるようになったので、作業を推測することに頼る必要はありません。私たちはそれを読んで、Stracheyが何を意味するのかについて自分で決心する必要があります。特に:
- セクション3.2では、「R値の参照透過性」について説明する「式」を扱います。
- 彼のセクション3.3は、「L値参照透過性」について説明する「コマンド」を扱っています。
- セクション3.4.5で、彼は「関数とルーチン」について話し、「R値コンテキストでのR値参照透過性の逸脱は、式をいくつかのコマンドとより単純な式に分解することによって排除する必要があるか、またはこれは難しいことが判明しました、コメントの主題です。」
L値、R値、および命令型プログラマーの概念の世界に存在するその他の複雑なオブジェクトの違いを理解せずに「参照透過性」について話すことは、根本的に間違っています。
式は、アルゴリズムを変更せずにその値で置き換えることができれば、参照透過性があり、同じ入力で同じ効果と出力を持つアルゴリズムが生成されます。
参照透過性関数は、数学関数のように機能する関数です。同じ入力が与えられると、それは常に同じ出力を生成します。これは、渡された状態が変更されておらず、関数に独自の状態がないことを意味します。
簡潔な説明が必要な人のために、私はそれを危険にさらします(ただし、以下の開示を読んでください)。
プログラミング言語の参照透過性は、等式推論を促進します。参照透過性が高いほど、等式推論が容易になります。たとえば、(疑似)関数定義を使用すると、
fx = x + x、
この定義の範囲内で f(foo) を foo + foo に (安全に) 置き換えることが容易であり、この削減をどこで実行できるかについてあまり多くの制約がないことは、プログラミング言語の参照透過性がどの程度かを示す良い指標です。もっている。
たとえば、C プログラミングの意味で foo が x++ である場合、このリダクションを安全に実行することはできません (つまり、このリダクションを実行すると、開始時と同じプログラムにはなりません)。
実用的なプログラミング言語では、完全な参照透過性は見られませんが、関数型プログラマーはそれを最も気にかけています (Haskell を参照してください。これが中心的な目的です)。
(完全な開示:私は関数型プログラマーなので、一番上の答えまでに、この説明を一粒の塩で受け取る必要があります。)
語源に興味がある場合 (つまり、この概念にこの特定の名前が付けられている理由)、このトピックに関する私のブログ投稿をご覧ください。この用語は、哲学者/論理学者のクワインに由来します。
- 表示的意味論は、表示可能な値を構成するドメインを構築することによるモデリング言語に基づいています。
- 関数型プログラマーは、値という用語を使用して、言語の書き換えルールに基づく計算の収束を説明します。その操作的意味論。
1では、問題の2つの言語が明確になっています。
- モデル化されているもの、オブジェクト言語
- モデリングの言語、メタ言語
2では、オブジェクトとメタ言語が近接しているため、混乱する可能性があります。
言語の実装者として、私はこの区別を常に覚えておく必要があると思います。
ですから、レディ教授はあなたを言い換えることができます:-)
関数型プログラミングとセマンティクスのコンテキストでは、参照透過性という用語は参照透過性ではありません。
この「意味」の概念は、観察者の頭の中で起こることに注意してください。したがって、同じ「参照」でも、人によって意味が異なる場合があります。たとえば、ウィキペディアにエジンバラの曖昧さ回避ページがあります。
プログラミングのコンテキストで現れる可能性のある関連する問題は、ポリモーフィズムかもしれません。
そしておそらく、私たちの目的のために、異なるポリモーフィックケースが意味的に同等である (単に似ているだけではなく) ポリモーフィズム (またはおそらくキャスト) の特別なケースの名前を持つ必要があります。たとえば、数値 1 -- これは表現される可能性があります整数型、複合型、またはその他のさまざまな型のいずれかを使用すると、ポリモーフィックに処理できます)。