すべての表現が意味をなすプログラミング言語


23

推奨に従って、私はこれをStack Overflowから再投稿しています。

最近、次の問題を考えています。

標準の「Hello world!」のコードを検討してください。プログラム:

main()
{
    printf("Hello World");

}

これで、このコードのほとんどすべての変更は完全に役に立たなくなり、実際、ほとんどすべての変更はコードのコンパイルを妨げます。例えば:

main(5
{
    printf("Hello World");

}

さて、実際の質問に。シンボルのあらゆる可能な組み合わせ、つまりすべての表現が意味をなすプログラミング言語はありますか?私はある種の解決策について考えてみましたが、2つ考えました

  1. 限られた数の変数を持つPostfix。基本的に、コードを記述する前にすべての変数が既に定義されているので、それらを操作する必要があります。理論的には、多くの単純なプログラムのチェーンを形成して、それぞれが他の人に結果を供給することにより、任意の数の操作を実行できます。コードは、後置記法の一連の文字として書くことができます。

  2. 変数のスタックを持つ「Postfix」。変数はスタックに保存されます。すべての操作は、上から2つの変数を取り、その場所に結果を置きます。プログラムは、最後の操作または変数に到達すると終了します。

個人的に私はこれらの両方が嫌いです。それらは限られているだけでなく、優雅でもありません。これらは回避策のような実際のソリューションではなく、本質的に外部プロセスへの一部の作業の「オフショアリング」です。

この問題を解決する方法は他にありますか?


48
コンパイラ、次のように機能する新しいコンパイラC を作成します。ソースsを指定して、それをCに渡します。場合Cはそれに満足し、実行可能ファイルを生成し、それはそれですが、場合Cは、出力を文句出力し、実行可能コンパイラCは、有効なプログラムとして、すべての文字列を受け付けます。CCsCCCYou are a bimbo.C
アンドレイバウアー

1
BFには、一致する[ ]コマンドが必要です(Wikiページによる)。私の考えは、CPUオペコードを見ることでした。しかし、それでも、パターンによっては問題が生じる場合があります(たとえば、オペコードが3ビットで、プログラムが2ビットしかない場合)。余分な0ビットでパディングする可能性があるこの問題を除いて、 「すべての文字列が有効なプログラムである」という主張を満たす完全なオペコードセット。無意味かもしれませんが、まだ有効です。
ランG.

1
ハードウェアを64k RAMのZ-80 CPUにします。ASCIIコードのソースコードを64kメモリにコピーするだけのコンパイラを作成します(必要に応じて切り捨てまたはゼロパディング)。このコンパイラは構文エラーを決して出しません。
ベン・クローウェル

1
@RanG。任意のビットストリームを処理し、特定のプロセッサのオブジェクトコードの有効なビットになるように修正する「コンパイラ」は、OPの要件を満たすと思います。x86のような複雑な命令セットを持つシステムであっても、それほど難しくはないでしょう。x86プログラムとしてのランダムバイトの有効性に関する論文を数年前に読みましたが、x86は実際に著者が当初予想していたよりもはるかに堅牢であることがわかりました。
オタクコード

2
これ以上の条件がなければ、この質問は退屈です。AndrejのコメントとDavidの答えは「些細な」答えを与えます。あなたが望むものをより正確に特定する必要があります。
ラファエル

回答:


31

コードウォーの背後にあるアセンブリ言語であるRedcodeは、停止命令が非常に少ないように明示的に記述されています。

プログラムを実行したいだけでなく、期待どおりに実行したいので、実際にはそのような言語はほとんどありません。タイプミスをしてプログラムの実行方法を変更できる場合、それは元の予想される動作、またはフラストレーションの中で見ているプログラマーに許容できるほど近いものでなければなりません。

フォーマル言語ではなく自然言語を使用することにより、そのようなことにはある程度の優先順位がありますが、フォーマル言語の使用と比較すると、私が大きなフィールドと呼ぶものではありません。そのようなプログラミング言語に興味があるなら、自然言語処理コミュニティが私が見たい場所です。

あなたが見ることができる別の分野は遺伝学です。単純に無効な遺伝子配列はほとんどありません。複製にはあまり効果的ではないが、無効なものはほとんどありません。


1
遺伝学は良い例ではないようです。有効または無効という点で、レプリケーションについて話しているだけですか?もちろん、すべての文字列は、可能な唯一の命令である言語の有効なプログラムになりますreplicate this string。しかし、Turing Completeにはほど遠いため、実際には意味のあるプログラミング言語ではありません。
tel

2
@tel:Cortは、おそらく複製ではなく、mRNAを介したタンパク質合成について話しているでしょう。ほぼすべての遺伝子配列を転写して、タンパク質合成機構に入れることができます:出てきたタンパク質が十分に安定していて、構築された時点までに分解されていないかどうか、もしそうなら何かに役立つかどうか生物は、別の問題です...
スティーブ・ジェソップ

3
遺伝暗号は、それ自体を再現するための暗号ではありません。これは(一般的に)タンパク質のコードです。タンパク質が有用かどうかは、しばしば異なる質問です。もちろん、もっと面白くなります。遺伝的シーケンスの「コード」の一部は、「数行下のコード-それを無視する必要がある」という行に沿った命令のようになります。あらゆる種類のクールな「プログラム」セルがあり、ウイルスは互いに戦いを書きました。
ジョエル

TECOはもう 1つの実例です。
cjm

1
@cjmうわー。「APIは、すべてを追加し終えたときではなく、すべてを取り出し終えたときに完成します。」あなたがTECOでない限り、意味を割り当てるためのキャラクターがなくなったら終了です。
コートアンモン-復帰モニカ

16

普遍的なチューリングマシンのアイデアは、まさにそのような「プログラミング言語」を使用します。自然数としてのチューリングマシンのコーディング。たとえば、すべての自然数がチューリングマシン、つまりプログラムを表します。この言語では、ゼロと1のすべての文字列がプログラムです。

一部の数値が無効なプログラムをコーディングするのではないかと心配している場合は、次のように回避できます。プログラミング言語(たとえば、Java)の文字セットのすべての文字列を、辞書式順序で、長さ1、2、3の文字列で書き始めることを想像してください。次に、番号を入力して新しいプログラミング言語を作成します。は、リスト内の有効なJavaプログラムであるn番目の文字列を表します。新しいプログラミング言語では、プログラムは単なる自然数であり、すべての自然数は有効なプログラムです。nn

すべての文字列がプログラムである難解なプログラミング言語もあると確信しています。ただし、それらのリストを求めているだけの場合は、ここでの質問はトピックとは無関係だと思います。


13

すべての式が意味をなすようにプログラミング言語を拡張することは常に可能ですが、面白くありません。たとえば、元の言語が拒否する表現に「何もしない」という意味を割り当てることができます。

すべての式が「実行できる」方法で意味をなすプログラミング言語を設計することは、特に有用ではありません。優れたプログラミング言語とは、サルがキーボードで入力して有効なプログラムを作成できるものだけでなく、プログラマーが意図したプログラムを簡単に作成できるものです。有効なプログラムを書くことは、プログラミングの難しい部分ではありません。難しい部分は、期待されたものを実行するプログラムを書くことです。この点で明らかに不正なプログラムを拒否することは非常に役立ちます。

これに取り組む別の方法は、すべての可能な入力のセマンティクスを完全に定義することです。これには、各入力に対して生成されるコンパイル時、ロード時、または実行時エラーを指定します。つまり、「Syntax error at line 42標準エラーストリームに出力した後にプログラムを中止する」は、言語の定義済みセマンティクスの一部です。すべての表現は、定義された意味を持つという意味で「意味をなします」。それは便利な意味ですか?たぶん—結局のところ、プログラムが明らかに間違っているなら、それを拒否することは有用です。


12

組み合わせロジックに基づくチューリング完全言語であるJotを調べてください。0と1のすべてのシーケンス(空のシーケンスを含む)は有効なプログラムです。


2
これはコンピューターサイエンスの答えではありません。
ラファエル

2
@Abdulrhmanバイナリ文字列と自然数の間の全単射を定義するのは簡単です。そのため、必要に応じて任意のプログラムを自然数としてエンコードできます。
CodesInChaos

7
@Raphael批評の根拠を提供していただければ、詳しく説明するか、答えの改善を提案してください。改善させていただきます。
ペトルプドラク

+1、自然数に基づいた架空のプログラミング言語についても同様の答えをしようとしていましたが、これは似ています。私の知る限りがあり、この機能を持っている(実用上)はプログラミングはありませんが、一つは数字だけを使用して1を構築することができ、すべての組み合わせが意味を持っていると言う、(事業者だけでなく、オペランドとして動作)これが鍵ですができます
ニコスM.を

8

良い例の1つは、空白です。適切な言語では、演算子の任意の組み合わせが有効です。演算子は、スペース、タブ、および改行(具体的には「\ n」)です。他のすべての文字はコメントと見なされます

この回答と実際の質問(およびこのWebページ全体)は、有効な空白プログラムの例です(特に興味深いことは何もしませんが)。


私はブレインファックの答えを投稿した後にこれについて考えていました(あなたの答えは正しいので良いです)が、私は疑問に思っています-空のプログラムはまだプログラムですか?(つまり、これら3文字がファイルストリーム全体から欠落している場合)。-例えば、もし私の車がそれを車にするすべてのものを失っていたとしても、それはまだ車なのでしょうか?
BrainSlugs83

これはコンピューターサイエンスの答えではありません。(また、「すべての空白文字列」!=「すべての文字列」)
ラファエル

2
@Raphael:しかし、可能なすべての文字列(空白を含まない文字列を含む)は有効な空白プログラムです-空白ではない文字は空白プログラミング言語の単なるコメントであることに注意してください
-slebetman

2
@slebetmanあなたは私の括弧コメントを文字通りに解釈しすぎていました。対になっていないループトークンについて話していました。空白のいくつかの同様の問題は次のとおりです。(としてエンコード[LF][Tab][LF])空のスタックをポップするとどうなりますか?未定義のラベルにジャンプするとどうなりますか?重複したラベルを定義するとどうなりますか?
CodesInChaos

7

私は、多くのポスターが与えた、そのような言語は「役に立たない」という考えに取り組みたいと思います。おそらく、人間が特定のタスクを解決するために手動で書くことは無意味でしょう。ただし、プログラミング言語の大多数のユースケースであるにもかかわらず、それが確かに唯一のユースケースではありません。そのような言語が有用な場合、いくつかのユースケースが思い浮かびます。そのような言語の例については、それらのフィールドを調べることができます。

(代わりに問題のプログラムの変換:まず遺伝学へCortのアンモンのほのめかしは上のスポットである)ためには5)として見ることができる変異が。この種の操作は、進化的計算の分野では一般的です。特に遺伝的アルゴリズム文字列でそのような変換を行いますが、遺伝的プログラミングはプログラムを変換します。どちらの場合でも、通常はあらゆる可能性に意味を割り当てたいと思います。なぜなら、それは最もコンパクトな検索スペースを生成するからです。

遺伝的アルゴリズムは、文字列について何らかの評価関数に依存しています。評価関数としてプログラミング言語インタープリターを使用する場合、考えられるすべての文字列に意味を割り当てるプログラミング言語が役立つシナリオがあります。遺伝的プログラミングでは、評価関数はプログラミング言語インタープリターであると想定されていますが、プログラムにはさまざまな表現を選択できます。たとえば、多くのシステムは抽象構文ツリーで動作します。文字列を表現として選択する場合、遺伝的アルゴリズムと同じシナリオを回復します。

すべての文字列を有効なプログラムにしたい別の状況は、プログラムを列挙するときです。これはCodesInChaosで言及された全単射に関連していますが、いくつかの理由から、自然数よりも文字列を操作する方が好ましい場合があります。

  • 言語に何らかの構造がある場合、例えば サブストリングに意味を割り当てることができます。これは、自然数に変換するときに失われる可能性があります。この場合、プログラム全体を数値として表すのではなく、部分文字列をローカルで推論および変換するために、文字列を使用することをお勧めします。これは、各ビットに個別の意味がある場合に、算術式ではなくintでビット演算を使用する方法に似ています。これは、基本的に進化シナリオの一般化です。
  • オンデマンドでプログラムを生成したい場合があります。たとえば、完全に決定されていないプログラムの実行を開始し、命令ポインタが到達した場合/到達した場合にのみ個々の命令(たとえば文字)を(ランダムに)生成します。これは、プログラムがチューリングマシンテープであるアルゴリズム情報理論で一般的であり、目的は、ランダムに生成されたプログラムの動作を特徴付けることです。たとえば、ランダムテープを備えたユニバーサルチューリングマシンがその文字列を出力する確率として、任意の文字列よりも前にSolomonoffを定式化できます。

言語の例では、多くの進化的計算システムはプッシュファミリのようなスタック言語に基づいています。これらは、トークンの任意のストリームを許可する傾向があります(個々の文字として表すことができます)。時には(BrainSlugs83のBrainfuckの例のように)括弧のバランスをとるのに制限があります。しかし、我々はこれを関連付けることができ、自己区切りのプログラムのような文字列があることで、[有効ではないかもしれないプログラムが、それはある有効なプログラムの接頭辞。コンパイラー/インタープリターがstdinからソースコードを読み取ることを想定している場合、のような文字列を拒否せず、[続行する前にさらに入力を待機するだけです。

Binary Combinatory LogicやBinary Lambda Calculusのような言語は、アルゴリズム情報理論の研究から直接生まれました。http://tromp.github.io/cl/cl.htmlから

ミニマルな普遍的なコンピューターのこの設計は、個々のオブジェクトのランダム性を研究するコルモゴロフ複雑性の具体的な定義を考え出すという私の願望に動機付けられました。


2

実際のプログラミング言語は、コンピューターではなく人々に意味を伝えることです。ほぼランダムにシャッフルされた文字が「ショー」ショーの周りに浮かんでいるたくさんの楽しいテキストとして、人々はあからさまにマングリングに気付かなくても、意味不明な文章を読んでそれを理解することができます。テキストのタイプミスやその他のエラーを見つけるのがどれほど難しいかを考え直してください。

あなたが求めるもののようなプログラミング言語は、人々に書かれているものではなく、読みたいものを理解させるでしょう。限られた法的​​声明文が存在する言語でのデバッグ、あいまいさの可能性があまりない場合は、すでに十分に困難です。良い言語は、たとえば記号やタイプミスを置き換えることにより、解釈の可能性を減らします。自然言語も同様の理由で、冗長性で有名です。


0

Brainfuckプログラミング言語ほぼすべての可能なバイナリ表現は、プログラムとして解釈することができます。-つまり、完全に優れたプログラムを使用して、大量のゴミを入力すれば、問題なくコンパイル/解釈可能です。

編集:開き角かっこと閉じ角かっこを一致させる必要がありますが、それ以外の場合は上記が当てはまります。)

次の2つの簡単な方法でこれを実現します。

  1. それが理解するコマンドはすべてシングルバイトです(BFでは、それらはすべて単一のASCII文字です*)。

  2. 理解できない文字はすべて、コメントとして破棄します。

プログラミング言語はチューリング完全です(つまり、他の言語でできることは何でもできます)。

*: すべてのBFコマンドが単一のASCIIバイトであるわけではないことがわかります(つまり、括弧を一致させる必要があります)。つまり、その言語は最初の基準を満たしていません。-しかし、両方の基準を満たしている言語は、OPが求めているものを満たします。


2
これは質問に答えないだけでなく、コンピューターサイエンスの答えでもありません。
ラファエル

1
言語を再定義して、それらを適切な方法で処理できます。たとえば、プログラムの開始時に十分な開き括弧を挿入し、プログラムの最後に閉じ括弧を挿入して、バランスを取ります。実際にプログラムを書き換えずに、それらの括弧が存在するかのようにプログラムを処理するインタープリターを書くのは簡単です。もちろん、開き括弧を使用してブレインファックプログラムを開始することは、対応する閉じ括弧までのすべてを無視するため、むしろ役に立たない。
CodesInChaos

1
@RaphaelのOPの質問は、「考えられるすべてのシンボルの組み合わせ、つまりすべての表現が意味をなすプログラミング言語がありますか?」でした。-私の答えは、「はい、近いものの例です。その背後にある理論は次のとおりです。」-OPの要件を満たす言語の1つのクラスに対して正確なルールをレイアウトする以外に、ここに科学の余地がどれほどあるかはわかりません。ここで見たいと思っているリソースの例やリンクを教えていただけますか? - ありがとうございました。
-BrainSlugs83

2
DavidとGillesはコンピューターサイエンスの答えを提供します。彼らは原則を探求し、「言語Xはそれを(ほぼ)行う」だけではありません。彼らの答えを読むと、後者の形式の答えもかなり退屈であることがわかります。それはあなたのせいではありませんが、OPの問題(コンピューターサイエンスの質問として)は退屈です。複雑さの誤った感覚があります。
ラファエル

任意の文字列が受け入れられるようにBFを簡単に「修正」することができます。]ソースの最後に一致しないすべて[のs に一致する十分な文字があり[、最初に一致しないすべてに一致するふりをするだけ]です。のセマンティクスは[]これと同等になるように簡単に変更できます。(一致が存在しない場合など]、その後[のデータポインタのバイトがゼロである場合にだけ実行を停止します。]ちょうど同じような状況でのプログラムの開始にジャンプします。)結果の言語はチューリング完全であろうと、任意の文字列を受け入れるだろう。
ナサニエル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.