プログラミング言語の構文は実装に依存していますか?


12

しかし、私の質問はまったく無関係かもしれませんが、ほとんどのプログラミング言語と公式の実装との間のパターンを感じました。

PythonやLuaなどの解釈された(バイト解釈?)言語は、通常、非常に寛容で簡単な構文を持ち、一般に型がなく、開発者がソースコードに変数の型を明示的に記述する必要はありません。

C、C ++、Pascalなどのコンパイルされた言語は通常、厳密な構文を持ち、一般に型を持ち、ほとんどの場合より多くのコード/開発時間を必要とします

Java / C#のように公式実装がJITコンパイルされている言語は、通常、上記の2つの間の優れた機能を備えた独自の妥協案です。

DやVala(およびJavaのGNU GJC実装)のような最新のコンパイル済みプログラミング言語の一部は、おそらくこの規則の例外であり、JavaやC#などのJITコンパイル言語の構文と機能に似ています。

私の最初の質問は、これは本当に関連性がありますか?または、これはほとんどのインタープリター言語が簡単な構文を持っていることと単なる偶然の一致であり、JITコンパイルされた言語は中程度の構文と機能を持っています

第二に、これが偶然ではない場合、なぜそうなのですか?たとえば、たとえば、JITコンパイルしている場合にのみ、プログラミング言語で実装できる機能はありますか?


@YannisRizosすみません、引用ではありません。強調したかっただけです。編集します。
ApprenticeHacker

1
クールですが、引用ではありませんでしたが、回答者がそれを1つだと考え、反論しようとしない(または盲目的に同意する)ことにつながる可能性があります...似たようなパターンに気づきましたが、残念ながら良いものがありません回答。
ヤニス

@ R.MartinhoFernandes申し訳ありませんが、私はそれを知りませんでした。(もう一度)編集します。
ApprenticeHacker

4
Perlは、ユーザー定義型に対して動的に型付けされ、配列、ハッシュ、スカラー、およびサブルーチンの区別に関して静的に型付けされ、strict、interpreted、およびJITコンパイルを使用して強く型付けされます(もちろん同時にではありません)...言語設計の意味を理解するために、いくつかのPerlで投げることは...いつも楽しいです
ヤニス

3
「厳密な構文」と「厳密な構文」とはどういう意味ですか?それらはすべて正式な言語であり、構文エラーのあるソースコードを実行するものはありません。
ニキーー

回答:


17

セマンティクスと構文の間には何の関係もありません。Schemeのようなホモイコニックコンパイル言語には、最小限の構文が付属しています。Forthのような低レベルのコンパイル済みメタ言語は、それよりもさらに単純です。一部の非常に厳密に型指定されたコンパイル言語は、簡単な構文に基づいて構築されます(ML、Haskellを考えてください)。OTOH、Python構文は、多くの構文規則の点で非常に重要です。

そして、はい、タイピングは構文とは何の関係もありません。それは言語のセマンティクス側にあります。ただし、すべてのタイピング情報がなければ解析することさえできないC ++のような異常なものでない限りです。

一般的な傾向は、あまりにも長く進化し、構文の逸脱に対する設計上の保護手段をまったく含まない言語は、遅かれ早かれ構文的憎悪に進化することです。


私を作るための+1は、「homoiconic」見上げる...そしてPHPへの微妙なうなずきのために...
ヤニス

1
+1、あまりにも長く進化し、設計上の安全策が含まれていなかった言語、これはDelphi / Object-Pascalも参照していますか?
ApprenticeHacker

1
@ThomasEding、あなたは間違っています。同じセマンティクスを、構文のない言語(LispやForthなど)でも、非常に広範囲の構文スタイルの上に実装できます。同じ構文を非常に幅広いさまざまなセマンティクスで使用できます。たとえば、CとVerilogの式の構文はほぼ同じですが、セマンティクスは劇的に異なります。
SKロジック

1
@ SK-logic-複雑でチューリング完全だからといって、それがプログラムの構文の少なくとも非常に大きな部分ではないという意味ではありません。さまざまな言語の構文解析はチューリング完全であり、「構文とは無関係」の構文解析を魔法のようには行いません。構文は「スコープ」に関するものではなく、言語のステートメントの構造に関するルールに関するものです。これらのステートメントの意味については何も言いません。チェック入力し、型推論は、それらを実行せず、プログラムの構文木を操作する-彼らはプログラムの構造に関する事柄を決定については何も言わずに...
ジャック

1
@ジャック、あなたは構文が何であるかを再定義しようとしています。チューリング完全なパーサーを必要とする実用的な言語はありません。ほとんどはコンテキストフリーにすぎません。そして、これは構文が留まるべき場所です。この(すでに伸びすぎている)概念を他のどこにも拡張しないでください。そして、私はすでにカリー-ハワード同型に言及しました-それは意味論に関するものであり、単なる正しさのルールをはるかに超えています。「type checking」という用語は非常に非生産的であり、使用すべきではありません。誤解を招きやすく、型システムの性質を反映していません。
SKロジック14

6

ほとんどこれは偶然です。

プログラミング言語は時間とともに進化しており、コンパイラーとインタープリターのテクノロジーは改善されています。基になる処理の効率(つまり、コンパイル時間、解釈のオーバーヘッド、実行時間など)も、主流のコンピューティングプラットフォームが成長するにつれて重要性が低下しています。

言語構文に影響があります。たとえば、Pascalは非常に慎重に設計されているため、シングルパスコンパイラを使用できます。一方、Adaはこれに注意を払わず、Adaコンパイラーは書くのが難しいことで有名です-ほとんどは複数のパスを必要とします。(私が何年も前に使用した非常に優れたAdaコンパイラは、8パスコンパイラでした。ご想像のとおり、非常に低速でした。)

Fortran(コンパイル済み)やBASIC(解釈済みまたはコンパイル済み)などの古い言語を見ると、非常に厳密な構文規則と意味規則があります。[BASICの場合、Billsの古いBASICではありません。その前に元に戻す必要があります。]

一方、APL(たくさんの楽しみ)のような他の古いものを見ると、これには動的なタイピングがありました。また、一般的に解釈されましたが、コンパイルすることもできました。

寛容な構文は難しいものです。それは、オプションのものや推論できるものがあることを意味する場合、その言語には十分な豊富さがあり、meansされる可能性があることを意味します。そして再び、BASICには、何年も前に「LET」ステートメントがオプションになったときがありました。

現在見られるアイデアの多く(たとえば、型なしや動的な型付け)は実際には非常に古く、1970年代または1980年代初頭に最初に現れました。それらの使用方法、およびこれらのアイデアが使用される言語は変化し、成長しました。しかし基本的に、新しいものの多くは、実際には新しい服を着た古いものです。

ここに私の頭の上のいくつかの例があります:

  • APL:動的型付け。一般的に解釈されます。1960年代/​​ 1970年代から来ました。
  • 基本:強力または動的な型指定。解釈またはコンパイル。1970年代以降。
  • Fortran:強い型付け。編集済み。1960年代以前。
  • Algol68:強い型付け。編集済み。1960年代。
  • PL / 1:強い型付け。編集済み。1960年代。
  • パスカル:強い型付け。編集済み。1970年代。(しかし、1980年代には、JITコンパイラに非常によく似たPシステムコンパイラがありました!)
  • 初期のDECによるFortranやその他の実装の一部は、部分的にコンパイルされ、部分的に解釈されました。
  • Smalltalk:動的型付け。解釈されるバイトコードにコンパイルされます。1980年代。
  • プロローグ:より奇妙。機能的。コンパイル済み(Turbo Prolog、誰か?)。1980年代。
  • C:強い(ハハ)タイピング。編集済み。1960年代..今日
  • Ada:非常に強力なタイピング。編集済み。1980年代。
  • Perl:動的型付け。(強力な構文)。解釈済み。1990年代(?)

続けられた。

  • Nitpickersコーナー:多くのインタープリター言語は、ソースが読み込まれた/読み込まれた時点でトークン化または「バイトコンパイル」されます。これにより、インタープリターのその後の操作が非常に簡単になります。コードのバイトコンパイルバージョンを保存できる場合があります。できないこともあります。まだ解釈されます。

更新:十分に明確ではなかったため。

入力は大きく異なります。

コンパイル時の固定静的型付けが一般的です(C、Ada、C ++、Fortanなど)。これは、タイプのTHINGを宣言する場所であり、その方法は永遠に続きます。

また、動的型付けを行うこともできます。動的型付けでは、割り当てられている型を取得します。たとえば、PHPと初期のBASIC、およびAPL。変数に整数を割り当て、それ以降は整数型でした。後で文字列を割り当てた場合、それは文字列型でした。等々。

そして、たとえば、数値整数(引用符で囲まれた文字列)を変数に割り当ててから数値を追加するなど、本当に奇妙なことを実行できるPHPのように、緩やかな入力があります。(たとえば、 '5' + 5は10になります)。これは奇妙な国ですが、時には非常に便利です。

ただし、これらは言語に組み込まれた機能です。実装はまさにそれを実現します。


13
厳密な型指定は、動的な型指定に対応していません。それは弱いタイピングの対応物です。動的型付けの対応物は静的型付けです。1つは、プログラム内の式の型を静的に(つまり、プログラムを実行せずに)知ることができます。別の方法では、型は動的にのみ知ることができます(つまり、プログラムを実行する必要があります)。
R.マルティーニョフェルナンデス

はい。BASICとAPLのいくつかのバリアントは両方とも1970年代後半にこれを行っていました。APL型は、今日理解されているほど完全ではありません(普遍的に型付けされた整数/浮動小数点数のようなものですが、ベクトル、文字列、多次元行列でもかまいません)。
すぐに

Fortranインタープリターはまだ広く使用されています(CernlibおよびPAWを参照)。そして、その子孫であるROOTはC ++インタープリターに基づいています。
SKロジック

正直に言うと、構文が強い/弱いタイピングと静的/動的なタイピングがどのように関係するのか完全にはわかりません。しかし、答えの質はかなり良かったので、私はただ投票を避けています。私はクラスCを「静的/弱」としてタイプします(保存された値を別の型であるかのように見れば、値が間違っている可能性があります)。
Vatine

@Vatine-コンパイル時は強い、実行時は存在しない-実際にそのようにしたい場合。多くの言語でポインターとそれに相当するものを使用してそれを行うことができます。バリアントレコードを使用する従来のパスカルや、UNCHECKED_CONVERSIONを使用するAdaでも可能です(ただし、困難ですが可能です)。
すぐに

2

私はそれが他の方法だと思う:実装は構文に依存します。たとえば、構文がリフレクションを許可している場合、実装はそれをサポートするランタイムを提供する必要があります。


@IntermediateHacker:私は素晴らしいでなければなりませんので、それは、Javaでだ
sehe

2

あなたの観察は主に歴史の結果であるという点で、私は一般的にすぐに同意します。とはいえ、根底にある推論は次のようなものに要約されます。

The more modern a language is, the more comfortable it should be to use.

(実際には引用ではなく、私自身の定式化です。)私がcomfortableここに書いているとき、私はあなたが呼んだものを参照しますbest features of both。より正確には、静的/動的タイピングや厳格/寛容な構文について賛否両論したくありません。代わりに、開発者に焦点を当て、言語で作業するときの快適さのレベルを高めることが重要です。

以前の回答で言及されていないいくつかの理由を次に示します。これらは、これらのことを観察する理由についてのアイデアを提供する可能性があります(すべての種類のプログラミング言語開発の歴史に基づいています)。

  • 最近、何百ものプログラミング言語があります。新しいものが登場したら、どのようにして幅広い視聴者を見つけることができますか?これが主な理由であり、新しい言語が常に開発者の快適レベルを向上させようとする理由です。言語が古い言語と同じことができるが、はるかに簡単/簡単/よりエレガント/などできる場合。実際に切り替えることを検討してください。

  • 学習曲線はそれと連動します。過去には、言語がほとんどなかったため、時間をかけて学習する価値がありました。それが多くの時間を投資することを意味したとしても。開発者が非常に迅速に学習できる言語を考え出せば、快適さが再び向上します。あらゆる種類の複雑さ(f.ex.、複雑で複雑な構文など)はこれに有害であり、したがって、新しい言語ではますます減少しています。

  • 技術の進歩(ここでの直接的な歴史的理由)は、コンパイラビルダーが開発者の快適さにより重点を置くことができるようになった原因です。初期の頃は、コンパイラをまったく作成できて満足でした。ただし、それはしばしば、厳しい制限が行われることを意味します。技術的ノウハウが増加するにつれて、これらの制限を再び解除することができました。

そのため、一般的に、プログラミング言語とコンパイラーは、典型的なエンドユーザーアプリケーションと同様の開発を経験しています。

  1. 初期段階:持っているのはクールなことですが、最先端のテクノロジーにより、快適さ/使いやすさ/その他が犠牲になります。
  2. 技術的改善:これらのものをより堅牢、高速、簡単に構築できます。
  3. ユーザーに焦点を当てる:ユーザーエクスペリエンスに焦点を当てたWeb2.0の動きと同様に、新しいプログラミング言語は開発者の視点に焦点を当てています。

(Not a quote really, just my own formulation.)まあ、あなたは
ブロック

3
快適さは明らかに味に依存します(常に完全に主観的です)。私が最も快適な言語は1959年に設計されたものであり、今世紀に登場した言語のいくつかに対処するのは我慢できません。
SKロジック

1
快適さも目的に依存します。洗濯機コントローラー用の8k組み込みマイクロでPHPまたはPrologを実行するのはプログラムに「快適」かもしれませんが、実際に適合させて許容可能なパフォーマンスで実行するのは大変です。
すぐに

0

特定のプログラミング言語は、コンパイラが実行時の決定を追加せずに実行可能コードに還元する方法を推測するのに十分なセマンティック情報を公開または制約する場合としない場合があります(「この変数はどんな型ですか?」など)この制約は必須、または簡単に決定できます。

コンパイラがよりスマートになると、それらの決定を公開または制約するように明示的に設計されていない言語であっても、最も可能性の高いパスの実行可能コードを生成するのに十分な情報を推測またはプロファイリングできる場合があります。

ただし、実行時にコード(evalString())を作成または入力できる言語(およびコンパイラーが推測または推測できないその他のもの)では、事前に処理しようとしても、実行時にインタープリターまたはJITコンパイラーを使用可能にする必要がある場合がありますそれらをコンパイルします。

過去に、プログラミング言語とその実装は、インタープリターが4kまたは16kに収まるかどうか、コンパイラーが1分未満のCPU時間で終了するかどうかなど、ハードウェアの制約に適合するように進化していた可能性があります。マシンが高速化するにつれて、プログラマーがリターンキーを押すのと同じ速さで、以前に解釈されたプログラムを(再)コンパイルしたり、以前にコンパイルされたプログラムのソースコードを、少し古いハードウェアが最適化されたコンパイル済み実行可能ファイルを実行するよりも速く解釈することが可能になりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.