「Syntax」と「Syntactic Sugar」の違いは何ですか


45

バックグラウンド

Syntactic SugarのWikipediaページには次のように記載されています。

コンピューターサイエンスでは、構文シュガーは、読みやすく、表現しやすいように設計されたプログラミング言語内の構文です。これにより、人間が使用する言語が「より甘く」なります。物事をより明確に、より簡潔に、または一部の人が好む代替スタイルで表現できます。

私は、Syntactic SugarとSyntaxの違いが本当に理解できません。

私は、甘いバージョンがより明確で簡潔になり、おそらくいくつかの定型的なものがなくなる可能性があるという点に感謝します。しかし、ある程度のレベルでは、すべての構文が本質的にそれを行って、コードがコンパイルされるものを抽象化することを感じています。

同じウィキペディアのページから:

コンパイラー、静的アナライザーなどを含む言語プロセッサーは、しばしば「デシュガー化」と呼ばれるプロセスの前に、シュガー化されたコンストラクトをより基本的なコンストラクトに拡張します。

思考演習として、このステートメントで「頻繁に」「常に」を意味する場合:コンパイラが次の段階に進む前に構文を「デシュガー」するかどうかだけでは、内臓を知らないコーダーはコンパイラの何がSugar'd Syntaxとは何かを知っている(または気にしている)?

このサイトに関する非常に関連した質問「構文糖の厳密な定義?」始まる答えがあります

私見私はあなたがフレーズがBSであり、「本当のオペレーティングシステム」で「本当のツール」を使用して「本当のプログラマー」について話す人々によって使用される可能性が高いので、構文糖の定義を持つことができるとは思わない

おそらく、この言語を使用しているコーダーに大きな違いはないことを私に示すかもしれません。おそらく、違いはコンパイラの作者にしか認識できないのでしょうか?言語を使用するコーダーがSyntactic Sugarの内部にあるものを知ることが役立つ場合がありますか?(しかし、実際には、主題に関するどんな言説でも、炎の餌としてこの用語を使用する傾向がありますか?)

質問の核心

だから...質問の短いバージョン:

  • SyntaxとSyntactic Sugarの間に本当の違いはありますか?
  • 誰が重要ですか?

思考のための余分な食べ物

トピックの矛盾に関するボーナス:

ウィキペディアのページに例を示します。

たとえば、C言語では、a[i]表記法は*(a + i)

上記のリンクされた質問に関する別の答えは、同じ例について語っています:

考えてみてくださいa[i] == *(a + i)。実質的な方法で配列を使用するCプログラムについて考えてください。

そしてそれを要約します:

[]表記は、この抽象化を容易にします。構文糖衣ではありません。

同じ例の反対の結論!


9
引用された質問に対する私の答えでは、構文糖は、いくつかの一般的なイディオムを表現するのは簡単ですが、新しいセマンティクスを導入しない代替言語であると説明します。この意味で、構文糖はコンテキスト(使用される言語)に依存します。同じ表記法は、ある言語では通常の構文、別の言語では構文糖にすることができます。この説明は役に立ちますか?
ジョルジオ

7
1つの問題は、一部の人々は、「統語論的シュガー」はそうではないが、汚い言葉だと思っているように見えることです。システムに追加する各関数またはクラスは、「シンタックスシュガー」と見なすことができます。これは、言語ですでに明確に表現できるアイデアを少し(または多く)表現しやすくするためです。
ジョリスティマーマンズ

どうやら、それはあなたにとって重要です。
シャヒーン

11
結局のところ、それはすべて電気を介した単なる合成糖です。
アンソニーペグラム

回答:


34

主な違いは、構文は言語で定義された文法であり、いくつかの機能を公開できることです。その機能に到達できるとすぐに、同じことを実行できる他の構文はすべて砂糖と見なされます。それはもちろん、2つの構文のどちらが糖であるかについて奇妙なシナリオにぶつかります。特に、どちらが最初に来たのかが常に明確ではないためです。

実際には、構文糖は、中にinfix lhs + rhsmapを作成するなど、使いやすさを促進するために言語に追加された構文を記述するためにのみ使用されますlhs.Add(rhs)。私はCの配列のインデックス付けは構文糖とみなします。

エレガントなデザインが複製の量を制限する傾向があるため、それは主に重要です。シンタックスシュガーが必要な(または少なくとも欲しがる)ことは、デザインが失敗する兆候と見られる人もいます。


「その機能が得られるとすぐに、同じことができる他の構文はすべてシュガーと見なされます。」:これは、構文シュガーを持つには十分ではありません。 。糖化プログラムと脱糖化プログラムは同じセマンティクスを持っている必要があります。
ジョルジオ

3
@Giorgio「これらの2つのプログラムは同じセマンティクスを持っています」とはどう違うのですか?それ以外は、構文要素ではなくプログラムに焦点を合わせています。プログラム全体を構文上の砂糖にすることはできません。演算子、一種のステートメントなどは、構文上のシュガーです。

@Giorgio-確かに、セマンティクスが異なる同様の機能は、異なる機能であると考えています。ええ、同じセマンティクスを持つ独自のコンパイラーを作成し、それを「シュガー」と呼ぶようなフープジャンプがあります。率直に言って、このような非公式の概念については、正式な定義は行われません。
テラスティン

1
@Giorgio繰り返しになりますが、私の牛肉は、同等性についての見解ではありませんが、構文糖の概念をプログラムに適用してみてください。この用語はプログラム全体を指すものではありません!定義に応じて、アトミックビルディングブロックのみか、短いプログラムフラグメントのみです(最初の部分は> 80%をカバーしているようですが、一般的にシンタックスシュガーと見なされるすべてをカバーしているとは思いません)。

3
@Giorgioたとえば、プログラム全体;-)または、両方の定式化がいくつかの無関係な言語キーワードを含むのに十分な大きさ。シンタックスシュガーとして扱われたことのないものはif (a) return blah; ...result_type res; if (a) res = blah; else {...}; return res;です。これらのプログラムの違いを見つけるには、特定の言語を想定し、非常に言語の専門家(多くの場合、小さなステップの操作上のセマンティクスのポイント)を取得する必要があります。

10

構文は、言語プロセッサが言語の構成要素の意味を理解するために使用するものです。構文糖とみなされる構成体も言語プロセッサによって解釈される必要があるため、言語構文の一部です。

構文シュガーを言語の残りの構文と区別するのは、その言語で記述できるプログラムに影響を与えることなく、言語から構文シュガーを削除できるということです。

より形式的な定義を与えるために、私は言うだろう

構文糖は、その効果が言語の他の構文構成要素によって定義される言語の構文の部分です。

構文糖を使用すると、意図がより理解しやすいプログラムになることが多いため、これは構文糖またはそれを使用する言語を中傷することを意味するものではありません。


「構文糖は言語の構文の一部であるため、「これは構文糖であり、構文である」と明確に言う方法はありません。」:False。すでに言語に存在し、構文を持っているいくつかの構造の構文糖としていくつかの構文を導入するのは言語設計者です。構文糖は通常、アドホック(一般的ではありません)ですが、読みやすく/使いやすいです。
ジョルジオ

@Giorgio:最初の段落は少し厄介だったので書き直しました。しかし、構文糖が通常アドホックに追加されることに同意しません。最も広く知られている構文糖衣のビットはおそらくCの->演算子であり、その演算子が他のどの演算子よりも一般的でないかはわかりません。
バートヴァンインゲンシェナウ

1
@Giorgio:その場合、単一のアセンブリ命令に直接マッピングされないものはすべて、常により単純な部分(関数を含む)に分解される可能性があるため、構文シュガーと見なされる必要があります。私はあなたがその見解を共有する多くの人々を見つけるとは思わない。
バートヴァンインゲンシェナウ

1
「アドホック」とは、特別な制限された状況で使用されることを意味します。この用語には、一般的に否定的な意味合いはありません。アドホックソリューションという用語には、特定のソリューションではなく一般的なソリューションが必要になるため、否定的な意味合いがあります(同様の問題を何度も解決しないようにするため)。
ジョルジオ

1
「アドホックソリューション」はしばしば悪いので、「アドホック」自体が悪いことを意味するように見えるかもしれません。しかし、「アドホックポリモーフィズム」AKA関数のオーバーロード(en.wikipedia.org/wiki/Ad_hoc_polymorphism)もあり、これは悪くありません。少なくともイタリア語(母国語)では、ラテン語の「アドホック」の使用自体は否定的ではありません。英語で否定的な意味合いがある場合は、私の無知をお許しください。
ジョルジオ

6

他の回答では、主要な概念に言及していません: 抽象構文 ; それなしでは、「構文糖」という用語は意味をなしません。

抽象構文は、言語の要素と構造を定義し、その言語のフレーズを組み合わせてより大きなフレーズを作成する方法を定義します。抽象構文は、具体的な構文とは無関係です。「構文糖」という用語は、私が理解しているように、具体的な構文を指します。

一般に、言語を設計するときは、抽象構文の各用語に対して具体的な構文を作成して、プレーンテキストを使用して言語でコードを記述できるようにします。

ここで、fooの扱いにくい具体的な構文を作成するとします。ユーザーから苦情があり、同じ抽象構文を表す新しい具体的な構文を実装します。その結果、抽象構文とセマンティクスは変更されていませんが、同じ抽象構文用語に対して2つの具体的な構文があります。

これは、人々が「構文糖」と言うときの意味であると思います。具体的な構文にのみ影響するが、抽象的な構文やセマンティクスには影響しない変更です。

したがって、「構文糖」と「具体的な構文」の違いは明確になりました。私に。:)

この解釈はまた、アランペルリスが「シンタクティックシュガーがセミコロンの癌を引き起こす」と言ったときの意味を説明するのに役立ちます。実際の問題である抽象構文に対処するために費やしていない努力。


また、これは単に私の意見です。それは私が考えることができる唯一の解釈であり、私にとって理にかなっているからです。


1
抽象構文と具体的な構文の比較についても考えていましたが、これが常に構文糖を説明するかどうかはわかりません。たとえば、Cでp、fieldを含む構造体へのポインタを指定するとx、式は同じ抽象構文(*p).xp->x持ちますか?しかし、すべてが抽象構文と具体的な構文に要約されれば素晴らしいと思います。
ジョルジオ

@Giorgio残念ながら、どちらかがもう一方の構文糖であるかどうか、またはそれらの抽象的な構文ツリーがどのように見えるかを自信を持って述べるのに十分なCを知りません。または、Cの仕様が実際に抽象構文を定義している場合でも。:(

1
最初の式は.、ルートにを持つツリーとして解析できます。ルートの左サブノードはa *で、その子はpです。ルートの右側のサブノードはxです。2番目の式では、抽象構文ツリー->のルートにがあり、ルートには2つの子pとがありxます。同じ抽象構文ツリーを持つように両方の式を異なる方法で解析することが理にかなっているかどうかを把握しようとしていますが、現時点ではわかりません。
ジョルジオ

3
この解析ツリーは、ASTと呼ばれることが多い場合でも、Mattが話している抽象的な構文と同じだとは思いません。両方の式のアクションは同じです(ポインター型を参照型に変換してから、メンバーへの参照を取得しますx
役に立たない

1
「両方の式には同じアクションがあります(ポインター型を参照型に変換してから、メンバーxへの参照を取得します)」:これはセマンティクスであり、抽象構文ではありません。抽象構文とは、プログラムの実際の構造を反映するツリーを生成するために、具体的な構文((またはなど;)の無駄な詳細を省くことを指します(en.wikipedia.org/wiki/Abstract_syntax_treeを参照)。ただし、抽象構文では、プログラムのセマンティクスについて(まだ)何も言われていません。
ジョルジオ

4

構文糖は、言語構文のサブセットです。基本的な考え方は、同じことを言うには複数の方法があるということです。

何が落札困難シンタックスシュガーであり、その作品は「純粋な構文」ですそれはだ」または「それは言語の作者が意図した方法を知るのは難しい」または「それは、フォームが最初に来たと言うのは難しい」のような文である作品と言うことどのフォームがよりシンプルかを判断するのはややarbitrary意的です」。

何がそれを作る簡単に特定のコンパイラやインタプリタの枠内で質問をするために、純粋なまたは甘いですされている作品を決定します。純粋な構文とは、コンパイラがマシンコードに直接変換するもの、またはインタープリターが直接応答するものです。砂糖は、これらの直接的なことが起こる前に最初に他の構文に変換されるものです。実装に応じて、これは、著者が意図したものと、または言語仕様が主張するものと同じである場合とそうでない場合があります。

実際には、これは問題の現実が決定される方法です。


この答えは、構文の実装を、それが砂糖であるかどうかに誤って結び付けます。言語の要素が「砂糖」であるかどうか、それが要素の実装方法に関係するかどうかについて、arguments =を見たことはありません。純粋に、異なる、い要素を構文的に複製するかどうかについてです。
GreenAsJade 14

3

本当に、ウィキペディアからの最初の引用は、「...読みやすくするために...」、「....人間が使用するのにより甘くする...」と言っています。

執筆では、「しない」や「持っていない」などの短縮形は構文糖と見なすことができます。


(1)「今すぐ行くべきです」対(2)「今すぐ行くべきです」を検討してください:(1)は(2)の構文糖ですか?
ジョルジオ

1
@Giorgio私はノーと言うでしょう。
ozz

読みやすさ(「すべき」は「すべき」より読みにくい)または意味(「すべき」と「すべき」は異なる意味を持つ)のため。
ジョルジオ

@Giorgioフェア:)
ozz

1
ああ、私はそう思います:)もっと直感的に推測します。その例では、一方が他方より読みやすいとは思いません
-ozz

3

通常、構文シュガーは言語の一部であり、一般性を失うことなく既存の言語の一部(構文)で表現できますが、明快さを失う可能性があります。コンパイラには、ソースコードによって作成されたASTを変換し、シュガーに対応するノードを削除するための簡単な手順を適用する明示的なデシュガー化ステップがある場合があります。

たとえば、Haskellには再帰的に適用される次のルールを持つモナドの構文シュガーがあります

do { f }            ~> f
do { g; h }         ~> g >> do h
do { x <- f; h }    ~> f >>= \x -> do h
do { let x = f; h } ~> let x = f in do h

今のところ、それが正確に何を意味するかは問題ではありませんが、LHSの特別な構文はRHSのより基本的なもの(つまり、関数アプリケーション、ラムダ、およびlet)に変換できることがわかります。この手順により、両方の長所を維持できます。

  1. LHSの構文は、既存のアイデアをより明確に表現するプログラマー(構文糖)にとって簡単です。
  2. ただし、RHSコンストラクトに対するコンパイラーのサポートは既にコンパイラーに存在するため、パーサーとデシュガーイング以外の特別なものとして扱う必要はありません(エラー報告を除く)。

同様に、Cでは、脱糖書き換えルールを想像できます(演算子のオーバーロードなどのため、C ++には当てはまりません)。

f->h ~> (*f).h
f[h] ~> *(f + h)

あなたは使用せずに、すべてのプログラムを書いて想像できる->か、[]今日このような構成を使用しCに。しかし、プログラマーがそれを使用することはより困難であり、それゆえ構文シュガーを提供していました(70年代にはコンパイラーの作業も簡略化されると思います)。次の完全に有効な書き換えルールを技術的に追加できるため、あまり明確ではありません。

*f ~> f[0] -- * and [] have the same expressiveness 

構文砂糖は悪いですか?必ずしもではありません-より深い意味を理解せずに貨物カルトとして使用される危険があります。たとえば、次の関数はHaskellでは同等ですが、多くの初心者は構文シュガーを使いすぎていることを理解せずに最初のフォームを記述します。

f1 = do x <- doSomething
        return x
f2 = doSomething

さらに、シンタックスシュガーは、言語を複雑にしすぎたり、一般的な慣用コードを許可するには狭すぎたりする可能性があります。また、特定のことを簡単に行うには言語が十分に強力ではないことを意味する可能性があります-設計による(開発者に鋭いツールや、より強力な構造を追加すると他の目標を損なうような特定のニッチ言語を与えないで)または省略による可能性がありますフォームは構文シュガーに悪い名前を与えました。言語が、構文シュガーを追加せずに他の構成要素を使用するのに十分強力な場合、それらを使用する方がよりエレガントであると考えられます。


3

最も明白な例は、Cの「+ =」構文だと思います。

i = i + 1;

そして

 i +=  1;

まったく同じことを行い、まったく同じ機械語命令のセットにコンパイルします。2番目の形式では、数文字の入力を節約できますが、さらに重要なことは、現在の値に基づいて値を変更していることを非常に明確にすることです。

標準的な例として「++」ポスト/プレフィックス演算子を引用するつもりでしたが、これは構文上の砂糖以上のものであることに気付きました。i = i + 1構文を使用して単一の式で++ iとi ++の違いを表現する方法はありません。


+ =は、などの場合に便利a[f(x)] += 1です。
フロリアンF 14

1

最初に、他の回答のいくつかを具体的な例で説明します。C ++ 11の範囲ベースのforループ(他のさまざまな言語のforeachループによく似ています)

for (auto value : container) {
    do_something_with(value);
}

(つまり、砂糖バージョン)とまったく同じです

for (auto iterator = begin(container); iterator != end(container); ++iterator) {
    do_something_with(*iterator);
}

現在、新しい抽象構文やセマンティクスを言語に追加していませんが、実際の有用性があります。

最初のバージョンでは、意図(コンテナ内のすべてのアイテムを参照)が明示されます。また、トラバース中にコンテナを変更したりiterator、ループ本体をさらに進めたり、ループ条件を微妙に間違ったりするなどの異常な動作も禁止します。これにより、考えられるバグの原因が回避され、そうすることで、コードの読み取りと推論の難しさが軽減されます。

たとえば、2番目のバージョンでの1文字の間違い:

for (auto iterator = begin(container); iterator <= end(container); ++iterator) {
    do_something_with(*iterator);
}

過去1日のエラーと未定義の動作を提供します。

そのため、砂糖を使用したバージョンはより制限的であり、したがって信頼と理解がより簡単であるため、まさに有用です。


第二に、元の質問へ:

SyntaxとSyntactic Sugarの間に本当の違いはありますか?

いいえ、「構文糖」は(具象)言語構文であり、言語の抽象的な構文またはコア機能を拡張しないため、「砂糖」と見なされます。これに関するマット・フェンウィックの答えが好きです。

誰が重要ですか?

他の構文と同様に、言語のユーザーにとって重要であり、その中で特定のイディオムをサポートする(ある意味祝福する)砂糖が提供されています。

最後に、ボーナス質問について

[]表記は、この抽象化を容易にします。

これは、構文シュガーの定義によく似ています。配列としてポインターを使用することをサポートしています(そして、言語作成者の祝福を提供します)。p[i]フォームは、より実際より制限ではありません*(p+i)ので、唯一の違いは、意図(と若干の読みやすゲイン)の明確なコミュニケーションです。


最初に、「[forループに基づく範囲]は[その他のこと]とまったく同じです(つまり、砂糖バージョン)」と言います。しかし、あなたはそれが違うと言います、それはトラバース中にコンテナを変更することを禁止するということです...そしてあなたが説明した単なる単純な構文変換以上のものにする他の違いがあります(例えば「コンテナ」が一時的なときの振る舞い)。これらの違いは、それ単なる構文上の砂糖ではないことを暗示していますよね?したがって、これは構文糖衣の良い例ではないようです。
ドンハッチ

一般的なループと同等とは言いませんでしたが 、特定のループと同等と言いました。特定のループは、コンテナを変更して、非常に一般的なイディオムを表していない-しかし、あなたはまだそれがその共通のイディオムを以下だ、または異常な何かがループ本体に潜むされている場合かどうかを伝えるために、慎重にすべての一般的なループを読む必要があります。新しいループは、その一般的なイディオムの砂糖であり冗長性が低く、使用中のイディオムをより明確に伝えます。それはそうではありませんし、私はそれがそうであると主張したことはありませんが、何らかの形でループの一般的なアイデアのための砂糖です。
役に立たない

0

フレーズの元の意味が何であれ、今日では主に軽jor的であり、ほぼ常に「ジャスト」または「オンリー」の構文糖としてフレーズされています。読み取り不可能な方法で作業を行い、それを同僚に正当化するための簡潔な方法を望んでいるプログラマーにのみ重要なのです。彼らの観点から、今日主にこの用語を使用する人々による定義は次のようになります:

言語を実際に理解していないプログラマーに松葉杖を提供するために、他のより広く適用可能な構文と冗長な構文。

そのため、同じ構文要素に対して2つの反対の結論が得られます。配列表記の最初の例は、Bartの答えに似た用語の元の肯定的な意味を使用することです。2番目の例は、軽jor的な意味での構文糖であるという告発に対する配列表記の防御です。言い換えれば、構文は松葉杖ではなく有用な抽象化であると主張しています。


この用語の軽jor的な意味(「構文糖衣のみ」)は、構文糖衣は情報を追加しないという事実に由来すると思います。
ジョルジオ

1
構文は情報を追加しないという考えに由来するかもしれませんが、その考えは事実ではありません。意図に関する情報(たとえば、よく知られているイディオムを使用する)は、依然として情報です。
役に立たない

@役に立たない:情報によると、プログラムは構文糖の有無にかかわらず同じように動作します。もちろん、構文糖衣(読み手に情報/文書を追加する)で読みやすくすることができます。これは利点です。
ジョルジオ

偽物。構文糖は軽jor的ではありません。自分の塩に値するプログラマーは、同じコードをコピーして貼り付けるのではなく、より複雑なタスクをカプセル化して簡素化するライブラリーを作成します。これにより、動作が改善され、保守性の高いコードが作成されます。これは基本的に、一般的な複雑なパターンをより単純な構文に抽象化することにより、構文糖が達成することです。
クレイグ

私は、人々は通常、この言葉をas辱として意味していると言っています。「ばか」という言葉は軽jor的であると言っても、すべての人がばかであることを意味するわけではありません。人々が実践について前向きに話したいとき、彼らは通常「抽象化」や「カプセル化」などの用語を使用します。
カールビーレフェルト
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.