あなたが本質的に求めているのは、計算能力と、一般的に言語(または計算システム)の表現力(または単に表現力)と呼ばれるものとの違いです。
計算力
計算能力は、問題の種類は、言語を計算することができるものを指します。最もよく知られている計算能力のクラスは、ユニバーサルチューリングマシンと同等です。Random Access Machines、λ-calculus、SK combinator calculus、μ-再帰関数、WHILE
プログラムなど、他の多くの計算システムがあります。結局のところ、これらはすべて相互にシミュレートできるため、すべて同じ計算能力を持っています。
これにより、チャーチチューリングテーゼ(λ-calculusを作成したAlonzo ChurchとUniversal Turing Machineを作成したAlan Turingにちなんで名付けられた)が生まれます。Church-Turing-Thesisは、2つの側面を持つ計算可能性に関する仮説です。
- 一般的な計算が可能なすべてのコンピューティングシステムは同等に強力であり、
- アルゴリズムに従う人間は、チューリングマシン(および他のシステム)が計算できる関数を正確に計算できます。
ただし、2番目はコンピューターサイエンスよりも心の哲学の分野で重要です。
しかし、あなたの質問に非常に関連している、教会-チューリング-テーゼが言っていない 2つのことがあります:
- どのように効率的に様々なシミュレーションであり、
- 問題のエンコードがどれほど便利か。
(1)の簡単な例:ランダムアクセスマシンでは、配列のコピーは配列の長さに比例して時間がかかります。ただし、チューリングマシンでは、配列の長さの2乗に比例した時間がかかります。チューリングマシンにはランダムメモリアクセスがないため、テープを一度に1セルしか移動できません。したがって、それらをコピーするには、配列のn 個の要素をn回移動する必要があります。そのため、実装の詳細から抽象化しようとする漸近的な場合でも、異なる計算モデルは異なるパフォーマンス特性を持つ場合があります。
(2)の例は豊富です:λ計算とPythonはどちらもチューリング完全です。しかし、Pythonまたはλ計算でプログラムを作成したいですか?
また、私がこれまで回避してきた3番目のしわもあります。これらのオリジナルシステムはすべて、コンピューター科学者ではなく、論理学者、哲学者、または数学者によって設計されました。これらはすべて、Konrad Zuseの非常に最初の実験(それでもプログラム可能ではなかった、および/またはチューリング完全ではなかった)の前でさえ、1930年代初期に遡ります。彼らは「自然数の計算可能な関数」についてのみ話します。
結局のところ、自然数の関数として表現できるものはたくさんあります。結局、私たちの現代のコンピューターはそれよりもはるかに少ないものでさえ通っています(基本的には数字0と1で3-4の関数、それだけです) )、しかし、たとえば、オペレーティングシステムはどの機能を計算しますか?
このI / Oの概念、環境と相互作用する副作用は、「自然数に対する関数」という概念にとらわれていません。それでも、サイモン・ペイトン・ジョーンズがかつて「副作用のない純粋な機能はすべてあなたのCPUを熱くする」と言っていたように、観客は「実際、それは側面だ」と答えたので、それはちょっと重要です。効果も!」
イドリスの設計者であるエドウィン・ブレイディ(半分だけ)は、「テトリス完全」という言葉を冗談めかして(彼が発明したかどうかはわかりません)「自然数で計算可能な関数を計算できる」と「できる」環境と対話する重要なプログラムを作成するために使用してください。」さらに皮肉なことに、彼はIdrisにSpace Invadersクローンを実装することでこれを実証していますが、TetrisはSpace Invadersに還元されると確信しています。
別の指摘すべきことは、チューリングの等価性が実際に「有用な」プログラムを書くことについて話すのに必ずしも十分ではないだけでなく、OTOHも必要でさえないかもしれないということです。たとえば、SQLはANSI SQL:1999でチューリングと同等になりましたが、それ以前はまだ有用でした。実際、チューリングと同等にすることは、その有用性にまったく追加されないと主張するかもしれません。チューリングと同等ではない多くのドメイン固有言語があります。データ記述言語は通常そうではありません(そうすべきではありません)。Total Languagesは明らかにTuringに相当するものではありませんが、それでもイベントループ、Webサーバー、またはオペレーティングシステムを記述することができます。チューリングと同等の言語もありますが、実際にはこれは間違いと見なされます。
したがって、全体として、プログラムを静的に分析する場合を除き、チューリング等価性はそれほど興味深いものではありません。
表現力
私たちの計算システムが問題をまったく解決するのに十分な計算能力を持っていると仮定すると、次にやらなければならないことは、そのシステムの何らかの形式の表記でその問題を解決するためのアルゴリズムを表現することです。言い換えれば、何らかのコンピューター言語でプログラムを作成する必要があります。そこで表現力の概念が生まれます。
基本的に、特定のプログラミング言語でプログラムを作成することが「簡単」または「楽しい」ことを指します。ご覧のとおり、この概念は非常に曖昧で主観的であり、技術的というよりも心理的です。
ただし、より正確な定義が試みられています。最も有名なもの(そして私が知っている最も厳格なもの)は、プログラミング言語の表現力についての Matthias Felleisenの論文です(最初の2ページには穏やかな紹介があり、残りの論文はより肉厚です)。
主な直観はこれです:プログラムを言語から別の言語に翻訳するとき、あなたがする必要のある変更のいくつかはローカルに含まれています(例えば、FOR
ループをWHILE
ループに変える、ループを条件付きにGOTO
変えるなど)、そしていくつかはグローバルへの変更を必要としますプログラムの構造。
1つの言語の1つの機能をローカル変換だけで別の言語の別の機能に置き換えることができる場合、これらの機能は表現力に影響を与えないと言われています。これは構文糖と呼ばれます。
一方、プログラムのグローバル構造の変更が必要な場合、翻訳先の言語は機能を表現できないと言われます。そして、あなたが翻訳している言語は、(この機能に関して)より表現力があると言われています。
これにより、客観的に測定可能な表現力の定義が得られることに注意してください。また、概念は機能に依存するコンテキストであり、比較であることに注意してください。言語の中のすべてのプログラムのであれば、Aは言語に翻訳することができるBのみローカルの変更で、言語に少なくとも1つのプログラムがあるBすることができないに変換され、Aのみローカルな変更では、その後、言語Bは厳密により表現の言語よりもありますA。ただし、より可能性の高いシナリオは、両方の言語の多くのプログラムが相互に翻訳できることですが、他の言語に翻訳できない両方の言語のプログラムがいくつかあります。これは、どちらの言語も他の言語よりも厳密に表現力がなく、異なるプログラムを異なる方法で表現できる異なる機能を備えていることを意味します。
これは、「より表現力豊か」であることの意味の正式な定義を提供しますが、現象の背後にある心理的概念をまだ捉えていません。たとえば、このモデルによると、構文糖はローカルの変更のみを使用して翻訳できるため、言語の表現力を高めることはありません。しかし、我々は持つことを経験から知っているFOR
、WHILE
とIF
彼らは条件付きのためだけ糖衣構文であっても、利用できるGOTO
私達の意思表現ます簡単に。
事実、異なる言語には異なる機能があり、それによって問題についてのさまざまな考え方を表現することがより簡単または難しくなります。また、意図を簡単に表現する方法を見つける人もいれば、別の方法を見つける人もいます。
StackOverflowのRubyタグで見つけた例:Rubyタグに従う多くのユーザーは、ループは再帰よりも理解しやすいと主張しており、再帰は高度な機能プログラマーのためのものであり、ループは初心者にとってより直感的ですが、次のようなコードを直観的に書く完全な新人:
def rock_paper_scissors
get_user_input
determine_outcome
print_winner
rock_paper_scissors # start from the top
end
これは通常、「これは機能しません」と「彼らはそれを間違っている」とコメントする複数の人々につながり、「正しい方法」はこれです:
def rock_paper_scissors
loop do
get_user_input
determine_outcome
print_winner
end
end
ですから、明らかに、末尾の再帰がループ構造よりも「ループ」の概念を表現するためのより自然な方法である人がいます。
概要
2つの言語がチューリングと同等であるという事実は、チューリングマシンができるのと同じ数の自然数の関数セットを計算できるという1つの正確なことを示しています。それでおしまい。
これらの関数の計算速度については何も述べていません。それらの関数の表現のしやすさについては何も言っていません。そして、自然数の関数を計算する以外に何ができるかについては何も言っていません(例:Cライブラリへのリンク、ユーザーからの入力の読み取り、画面への出力の書き込み)。
それは、各プログラミング言語が実際に解決できる問題のクラスは、これらの言語がすべて完全に調整されているにもかかわらず、言語によって異なることを意味しますか?
はい。
- 画面への印刷など、「チューリング完全」という用語(自然数の関数の計算にのみ関係する)でカバーされない問題があります。2つの言語はチューリング完全にすることができますが、1つは画面への印刷を許可し、もう1つは許可しません。
- たとえ両方の言語が同じ問題を解決できたとしても、それはエンコーディングがどれほど複雑で、このエンコーディングを表現するのがどれほど簡単かについては何も言っていません。例えば、CでHaskellインタープリターを書くだけで、Haskellができるすべての問題を解決できます。しかし、この方法で問題を解決するには、まずHaskellインタープリターを書く必要があります。