私が初心者だったとき、言語の構文と、言語が発明されてからは改善できないという考えを学ぶのにしばらく時間がかかりました。
しかし現在、ES5、ES6などで毎年新しい言語機能が追加されています。
ソフトウェアに戻るときに数週間または数か月間ソフトウェアを作成しない場合、最初の数日間は、文字どおりの単語and
およびor
を使用してifステートメントを作成していることがよくあります。
if (isSinglePost and isLoggedIn) {
// do something
}
さらに、他の言語が言語構文でリテラルand
およびリテラルor
を使用しているのを見てきました。
and
とor
または||
と&&
を使用するオプションが欲しいのですが。それがベストプラクティスであると言っているわけではありませんが、読みやすさと書き込みやすさのオプションがあるといいでしょう。
それで、言語が発明されたときにそもそも言語がand
とor
を言語構文で使用しなかった理由があるのでしょうか?そして、今それを追加することに何か否定的な点はありますか?
ES2019候補
Cはいくつかの演算子を選択しましたが、ほとんどのCのような言語はそれにこだわりました。ほとんどではありませんが、すべてではありません。また、いくつかはベーシック風とパスカル風の伝統が混在しています。
C++には、これらの演算子と同等のトークンがあります。トークンand
は_&&
_として解析され、or
は_||
_として解析されます。ただし、これらの使用は非常に嫌われます。
Perlには、and
演算子と_&&
_演算子の両方があります。これらは同じように動作しますが、文法の優先レベルが異なるため、優先度の低いバージョンが使いやすくなります。たとえば、次の2つのステートメントは同等です。
_open(my $file, '<', $filename) || die "Could not open $filename: $!";
open my $file, '<', $filename or die "Could not open $filename: $!";
_
Pythonはand
のようなアルファベットの演算子を好み、シンボルバージョンはありません。ただし、構文上、言語はCファミリーに属していません。
new言語では新しい演算子を導入できますが、それらを既存の言語に改造することは一般に不可能です。言語は進化しますが、下位互換性を維持する必要があります。これは、JavaScriptのようなクライアント側のスクリプト言語では、実行するエンジンを指定できないため特に重要です。一部の変更は、既存の構文と衝突しない場合は安全ですが、新しいkeywordsの導入は非常にトリッキーです。function and() {}
のようなコードを遡及的に禁止することはできません。これはcontextual keywordのような概念を生み出しますが、それらはパーサーを複雑にし、したがって下流のツールも複雑にします。
ただし、JavaScriptには、Babelなどのビルドタイムトランスパイラーによる開発時の構文拡張に適したストーリーがあります。かなりのキーワードが必要な場合は、これらのキーワードを使用してコードを記述できますが、デプロイする前にトランスパイラーで標準のJavaScriptに置き換えてください。
最大の問題は、以前に予約されていないキーワードを取得して予約した場合に発生する後方互換性の問題です。たとえば、変数の記号接頭辞がない言語(PHPの「$」など)では、古いプログラムがその語句を変数名として使用している可能性があるため、新しい予約語を簡単に追加することはできません。一部の言語では、変数名と予約済みキーワード名のどちらを意味しているのかを推測できるほどコンパイラーは賢いかもしれませんが、これはコンパイラー自体に多大な労力を追加します。
言語の定義で、Bell LabsのC言語関係者が導入したより具体的な_|
_、_||
_、_&
_、および_&&
_キーワードではなく、and
およびor
キーワードを指定した場合でも(祝福された記憶のブライアンカーニハンとデニスリッチー)、and
とor
が提供できる以上の詳細が必要です。
_ if ( expensive_function (a) && another_expensive_function (b) ) {}
_
最初の関数がfalseに戻った場合、2番目の高価な関数の評価をスキップします。安全なコードを記述できるため、これも重要です。
_ if ( a != 0 && 1.0 / a > 0.3) {}
_
_&
_の代わりに_&&
_を使用した場合、a
がゼロの場合、ゼロによる除算がスローされることがあります。
だが
_ if ( expensive_function (a) & another_expensive_function (b) ) {}
_
常に両方の関数を評価します。 2番目の関数に副作用がある場合(たとえばprintf()
など)、区別は重要です。
他の言語では、_&&
_と_&
_のスペルが異なります。しかし、両者の違いはまだ存在しています。例えば。 VB.netでは、AndAlso
はcのような言語で_&&
_と同じように機能します。
SQLは、AND
とOR
の使用を回避します。これは、SQLが手続き型ではなく宣言型言語だからです。それはほとんど副作用のない言語ですが、完全ではありません。そのため、SQLクエリプランナーは、プログラマーに言わずに、anded/oredクエリのどの部分を評価する必要があるかを決定できます。
すべては主にCに戻ります。Cは、安全でないコーディングを維持して、Assembly言語の薄層として起動されました。
アセンブリ言語で知っているように、ビットマスク、ビットANDおよびORは重要です。したがって、ビット演算子_&
_および_|
_が必要です。通常:
_#define A_BEZ (A_LEFT | A_CENTER | A_APPROX)
_
次に、ショートカット演算子and-thenおよびor-else:_&&
_および_||
_がありました。
_if (i < n && a[i] < k)
_
_&
_と_|
_を見ると、_++
_と_--
_が2倍になる、ある程度予測可能な選択。
両方の学校は部分的に並んで運営されています:
記号式演算子:_&&, ||, %, ~?~:~
_
利点:mathematical(∧、∨)
名前付き式演算子:and, or, mod, if(~)~else~
利点:不可解ではない(and、or)
名前付き演算子は、特にブール式の方が見栄えが良いため、and
およびor
をCに再入力しました。これらをALGOL68スタイルと比較する価値があります。すべてが(型付き)式である優れた言語。
_INT a := ...; # REF INT variable a becomes ... #
INT b := ...;
IF a < b THEN a ELSE b FI := ...; # Assigment to a condition LHS #
(a < b | a | b ) := ...;
(node = nil | list.head | node.next ) := ...;
BOOL c = a = b OR IF i < n AND IF v[i] < a THEN b > a ELSE a < v[i] FI;
BOOL c = a = b ∨ ( i < n ∧ v[i] < a | b > a | a < v[i]);
_
上記の_|
_は、then/else(else-if、Elif、had _|:
_)の区切り文字、FI
はend-ifです。
ALGOL68は、ASCIIに対応していない数学記号を使用することを恐れていなかったことがわかります。キーワードとタイプ/演算子に太字のフォントandを使用することもできます。実際にはAND
または_.or.
_が使用されていましたが、それでも特別なキーボードはまれでした(単純な端末ではなく)。
_
&&
_および_||
_は、ビット単位/両側論理_&
_および_|
_のショートカットバージョンでした。今後の言語によっては、
and
やor
も登場するため、これを再考する可能性があります。