web-dev-qa-db-ja.com

慣用句とは何ですか?

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

i = i + 1;

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

++i;

しかし、誰かが「慣用的」という用語を使用する場合、それを理解する方法がわかりません。コードの一部を「慣用的」にするのは何ですか?

22
void.pointer

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

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

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

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

27
Klaim

通常の定義

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

プログラミング定義

[言語の挿入]プログラマにとって自然な式の使用、包含、または表記

12
ChaosPandion

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

特にRubyではWordの慣用句がよく出てきます。 Rubyには大規模なメタプログラミング機能があり、慣用的なRubyコードを書くには、通常これらを使用する必要があります。

コードの一部が慣用的であるからといって、それがクリーンであったり簡潔であったりするわけではないことに注意してください。多くの場合、妥協する必要があります。

したがって、基本的に、慣用句は、最も一般的には、何かを「言語」で書く最も一般的な方法を指します。コードの一部が慣用的ではない場合、完全に読みやすく、簡潔で、簡潔で、正しい可能性がありますが、使用する言語でぎこちなく感じることがあります。このようなコードを慣用的に書き直すことが実際に良いことであり、ケースバイケースで判断する必要があるかどうかは好みの好みです

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

8
Earlz

頭の中で、私が考案できる最も良い例は、慣用的なものとして、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は、一意ではありませんが、ユビキタスではないオブジェクトとの相互作用についての哲学を持っています。

セマンティックノートでは、単語が慣用句として聞かれると、脳は自動的に「慣用句...」としての思考を完成させます-特定の主題に関連するものとして反射的に解析します。

3
asfallows

イディオムは通常、言語で一般的で比較的複雑な状況を表現する最良の方法です。インクリメントはイディオムや種類の何かではありません。 postfixの代わりにprefix incrementを使用すると、C++イディオムであると主張できます。

イディオムは、エキスパートユーザーによって決定される、言語を使用する最良の方法です。実際のC++イディオムは関数オブジェクトになります。別のイディオムはRAIIです。言語には、デストラクタのリソースを解放する必要があることを示すものは何もありません。しかし、そうするのは慣用的です。別の例はテンプレートです。できる限りすべてのテンプレートを使用するのは慣用的ですが、継承の使いすぎを防ぐものは何もありません。

2
DeadMG

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

非慣用的なものについて話すことで説明する方が簡単かもしれません。 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;を見たことがなく、それが何をするのか本当にわからない場合は、問題になる可能性があります。

2
Kate Gregory

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

1
hotpaw2