慣用句とは何ですか?


19

「イディオム」は、特定の言語では整数インクリメントなどのコア言語構文によって単純化されない一般的な操作またはパターンであると理解しています。

i = i + 1;

C ++では、このイディオムは演算子によって簡素化されます。

++i;

しかし、誰かが「イディオマティック」という用語を使用するとき、どのようにそれを理解するかわかりません。コードの一部を「イディオマティック」にするものは何ですか?


これはここと同じようにenglish.stackexchange.comに属します。
S.Lott

@ perl.j:洞察力。english.stackexchange.comに「慣用句」の定義が含まれない理由を本当に明確にしました。非常に役立ちます。
S.Lott

回答:


24

あるコードを書く慣用的な方法は、他の言語にはない言語固有のイディオムのために、非常に特定の方法でそれを書くときです。

たとえば、C ++では、RAIIイディオムを活用することで、慣用的なリソースを管理するC ++コードを作成する方法につながります。

もう1つの例は、Pythonでリスト内包表記を使用してリストを生成することです。慣用的なPythonでリストの内包表記を使用していましたが、他の言語やPythonでもジェネレーター関数を使用して同じことを行うことができたため、これは慣用的です。

多くの場合、この言語固有のイディオムを使用せずに新しい言語を試す人は、慣用的なコードを作成しません。


優れた説明。C#では、TryAdd()Generic Dictionaryクラスで呼び出される拡張メソッドを作成して最初にチェック!Contains()してから呼び出すとAdd()、これは慣用的でしょうか?C#に固有の機能-拡張メソッドを使用しています。
void.pointer

1
ほとんどの経験豊富なC ++コーダーが、可能であれば、メンバーを追加する代わりに、クラスを拡張するための無料の関数を書くように言っているほど正確にはわかりません。C#の拡張メソッドとは異なりますが、非常に近く、無料の機能を許可するすべての言語で使用できます。私が確信しているのは、プロパティを使用してC#で "set / getters"を記述することは慣用的です。
クライム

しかし、これはC ++ではないため、「C ++の方法」を使用しても「イディオマティック」では不十分な場合があります。ここで拡張メソッドを使用するのは合理的で、非常にC#に似ています。いずれにせよ、これは例でしたが、拡張メソッドはC#に非常に慣用的です。
void.pointer

はい、だから私は「わからない」と言ったのです。それは慣用的な感じがしますが、他の言語の他の基本的な機能にとても近いのでわかりません(私はC#開発者ではないからです)。別の例があります:ループはすべての関数型言語で再帰によって行われます。他の言語でもできますが、明らかに関数型言語のイディオムです。それが役立つかどうかわからない。
クライム

1
もちろん、Pythonは、イディオムコードを参照するイディオム的な方法、つまりpythonicを使用することにより、さらに一歩前進します。* 8 ')
マークブース

12

通常の定義

ネイティブスピーカーにとって自然な表現の使用、包含、または表示

プログラミング定義

[Insert Language]プログラマーにとって自然な表現の使用、包含、または表示


1
この用語の「グーグル」定義が役立つと思ったら、ここには投稿しませんでした。例付きのより良い説明(チュートリアルのようなもの)が必要でした。
void.pointer

3
@Robert-なぜあなたが理解していないのか理解できないと思う。
ChaosPandion

2
最初にあなたの答えを読みましたが、それははっきりしていませんでした。現在、私の回答としてマークされている応答を読んだ後、「イディオマティック」の意味が非常に明確になり、今ではそれを理解しています。あなたの答えを読んだ今、それは理にかなっています。ただし、例やさまざまなシナリオを説明してくれなかったため、答えは役に立たなかったと思います。技術的には正しいが、私が理解できる限り役に立たない「ウェブスター」の回答がありました。あなたの助けに感謝します。
void.pointer

7

プログラミングの文脈での慣用的な表現は、通常、「言語で何かを表現する最も自然な方法」と定義できます。

Rubyでは、イディオマティックという言葉が特に多く登場します。Rubyには、大規模なメタプログラミング機能があり、慣用的なRubyコードを作成するには、通常これらを使用する必要があります。

コードがイディオムであるという理由だけで、それがクリーンまたは簡潔であることを意味しないことに注意してください。多くの場合、妥協する必要があります。

したがって、基本的に、慣用句は最も一般的には、言語で何かを書く最も一般的な方法を指し、しばしば「スラング」(イディオム)を含みます。コードの一部が慣用的でない場合、完全に読みやすく、簡潔で、きれいで、正しいかもしれませんが、使用されている言語では気まずく感じます。このようなコードを慣用的に書き換えることは実際には良いことであり、ケースバイケースで判断する必要があるかどうかは好みの好みです

たとえば、慣用的な英語は地域によって異なります。単語の使用bumはおそらく慣用的な英国英語にbuttは必要ですが、米国英語にはより適切です。(悲しいことに英国の英語はあまり知りません:/)


ありがとう(賛成)、あなたの定義は私のためにその場でヒットしたと思います!
アシャマンキングピン

3

頭の中で、イディオムな何かのために考案できる最良の例は、Rubyから来ています。

豊富な言語で、次のように反復できます。

for( start; end; increment){
    code;
}

または非常によく似たもの。多くの言語にもforeach(x in SetOfXes)構造があります。しかし、Rubyのイディオムである反復には、次のようなものが含まれます。

collection.each do |current|
  current.do_stuff
end

そしてさらに

10.times do |x|
  puts x
end

これらは、あまり一般的ではない何かを行う方法を表し、その領域の哲学の中核にある何かを表すので、これらを慣用的と見なします。Rubyには、オブジェクトとの相互作用に関する哲学がありますが、それは一意ではありませんが、遍在的ではありません。

セマンティックノートでは、イディオマティックという言葉を聞くたびに、私の脳は自動的に「...へのイディオマティック」という考えを完成させます。


とはどうcollection.each do |current|違いforeach(current in collection)ますか?どちらものcurrent各要素に設定されるループ構造ですcollection
MSalters

2

通常、イディオムは、一般的な比較的複雑な状況を言語で表現するための最良の方法です。インクリメントは、イディオムでもありません。接尾辞の代わりに接頭辞インクリメントを使用すると、C ++のイディオムであると主張できます。

熟語は、専門家のユーザーによって決定された言語を使用する最良の方法です。実際のC ++イディオムは関数オブジェクトです。別のイディオムはRAIIです。言語には、デストラクタのリソースを解放する必要があることを伝えるものは何もありません。しかし、そうすることは慣用的です。別の例としてはテンプレートがあります。テンプレートを使用するのは慣習的ですが、可能な限りすべてのものを使用しますが、継承の過剰使用を妨げるものは何もありません。


ウィキペディアでは例として増分を使用しているため、質問で言及しました。なぜイディオムは複雑である必要があるのですか?これは、他の回答に基づいた定義の一部ではないようです。
void.pointer

4
@Robert Dailey:インクリメントはイディオムになる可能性がありますか?それは言語の一部です。イディオムは言語のユーザーによって作成され、時間とともに変化します。インクリメントはイディオムではなく、言語の基本的な機能です。その論理を取ると、他の基本的な言語機能はイディオムであると言えます。したがって、すべてのプログラムは慣用的ですが、そうではありません。
DeadMG

2

あなたの定義は正しいとは思いません。イディオムは、他の言語では可能であるかもしれないし、そうでないかもしれない何かを書く方法ですが、それはこの言語では一般的です。通常、代替よりも短いですが、それは実際には要件ではありません。

非イディオマティックなものについて話すことで、それを説明する方が簡単かもしれません。C ++では、次のように書くのがかなり慣用的です。

Foo* p = SomeThingThatReturnsAFooPointer(arg, param, x, y);
if(p)
{
 // whatever
}

書くことはさらに慣用的です:

Foo* p; 
if(p = SomeThingThatReturnsAFooPointer(arg, param, x, y))
{
 // whatever
}

このコードはまったく同じことを行います。C++を初めて使用する一部の人は、pが関数が返す値と等しいかどうかをテストするためにそれを読むかもしれませんが、それはそうではありません。

別の言語から来た誰かが非常に非定型的に書くかもしれないものと比較してください:

Foo* p = SomeThingThatReturnsAFooPointer(arg, param, x, y);
if(p !=NULL)
{
 // whatever
}

また、このようなものが非イディオマティックとしてノックされていることがわかります。

if (x>0)
  return true;
else
 return false;

慣用的なアプローチは

return (x>0);

非イディオマティックな方法は間違っていませんが、イディオムを知っている人にとっては、タイプするのに時間がかかり、読むのに常に時間がかかります。私があなたを「オオカミを泣かせた少年」と呼んで、あなたが物語を知っているなら、それは私が誤った警報が人々にあなたを無視させる原因を説明するよりも速いです。もちろん、問題は、あなたが物語を知らず、オオカミが私たちが話していることとどう関係しているのか分からない場合です。同様に、これまでに見たことがなくreturn x<y;、実際にそれが何をするのか分からない場合、問題になる可能性があります。


1
慣用的なアプローチが確実にポインターを宣言するだろう、それはNULLでなければ、それはアクセスすることはできませんのでことを、もし条件。if(Foo* p = SomeThingThatReturnsAFooPointer(arg, param, x, y))
DeadMG

mm、おそらく。または、このブロック全体で使用されるため、1000行前です。または、ヘッダーファイル内のメンバー変数です。私が宣言したのは、読者がそれがFoo *であることを知るようにするためでした。実生活では、それはそこで宣言されないのはあなたです。
ケイトグレゴリー

1

何かを表現する方法が複数ある場合、最も一般的または一般に受け入れられている方法。たとえば、gotoステートメントを使用した場合とまったく同じではなく、Cで構造化ステートメントを使用します。

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