プログラミング言語の基本文法を比較する
この処理この言語だとどう書くんだっけ?が多いので
はじめに
いきなり網羅的には比較できないと思うので、今後、継続的に拡充していくつもりの記事です。
取り急ぎは、一番得意な Python をベースに js、C++を作り上げたい次第。
読者層を考えて VBA も書こうかと思いますが、機能の貧弱さに悲しくなりそう。
算術演算
| 言語 | 加算 | 減算 | 乗算 | 冪乗 | 除算 | 整数除算 | 剰余 |
|---|---|---|---|---|---|---|---|
| Python | a+b | a-b | a*b | a**b | a/b | a//b | a%b |
| JavaScript | a+b | a-b | a*b | a**b | a/b | `a/b | 0` |
| C++ | a+b | a-b | a*b | なし1 | a/b | a/b | a%b |
| VBA | a+b | a-b | a*b | a^b | a/b | a¥b | a Mod b |
動的型付けの言語では暗黙的型変換がどうなされるかについては習熟しておいたほうがよい気がします。
この例だと JavaScript の整数除算はMath.floor(a/b)としなくても0とORをとればビット演算の性質上、暗黙的に整数型に変換されることを利用しています。
VBA では冪乗に^使う点に要注意でしょう(多くの言語で^はビット排他的論理和XOR)。
ビット演算
シフト
| 言語 | 左シフト | 右シフト |
|---|---|---|
| Python | a<<b | a>>b |
| JavaScript | a<<b | a>>b |
| VBA | なし | なし |
VBA にはシフト演算をする演算子はありません。
基本
| 言語 | NOT | AND | OR | XOR |
|---|---|---|---|---|
| Python | ~a | a&b | `a | b` |
| JavaScript | ~a | a&b | `a | b` |
| VBA | Not a | a And b | a Or b | a Xor b |
VBA は論理演算子と同じものを使うので括弧をたくさん使う必要があり扱いにくいです。 (比較演算子より論理演算子のほうが演算優先順位が低いため)
特殊
| 言語 | EQV | IMP |
|---|---|---|
| Python | ~(a^b) | `~a |
| JavaScript | ~(a^b) | `~a |
| VBA | a Eqv b | a Imp b |
なぜか VBA にはEqvとImpがあります。
Python と JavaScript の欄を見ればわかりますが他の演算記号を組み合わせて表現可能です。
VBA ビット演算について
VBA のビット演算については、シフトもなくサポート外っぽいので本当に正しく評価されるかは未検証です。
一応軽く試してみた感じでは大丈夫そう。厳密にやるなら全部CIntだかCLongだかでキャストして上限ビット数揃えるとかしないとダメかも。
Rem 適当チェック用プロシージャ
Sub test()
Dim i, j
For i = -10 To 10
For j = -10 To 10
Dim ni As Long, nj As Long
ni = Not i
nj = Not j
Debug.Assert (i Xor j) = Not (i Eqv j)
Debug.Assert (ni Or j) = (i Imp j)
Debug.Assert (ni And nj) = Not (i Or j)
Debug.Assert ((ni And j) Or (i And nj)) = (i Xor j)
Next j
Next i
End Sub関係演算
| 言語 | 等価 | 厳密等価 | 小なり大なり | 存在 | 同一 | インスタンス |
|---|---|---|---|---|---|---|
| Python | ==, != | なし | <, <=, >, >= | in | is | isinstance() |
| JavaScript | ==, != | ===, !== | <, <=, >, >= | in | .is() | instanceof |
| VBA | =, <> | なし | <, <=, >, >= | なし | Is | なし2 |
C++は自分の理解がまだ追いついていないのでいったん省きます。
std::find()がどういうクラスなら適用可能なのか、とか、ポインタ変数と参照変数のどちらを使って同一を確認すべきか、とかが普段使わないからまったくわかりません。
演算子の優先順位
VBA の演算子優先順は、算術演算子 → 文字列連結'&'→ 比較演算子 → 論理演算子です。
詳しくはDocsでも見てください。
以下では、忘れがちな Python と JavaScript で主に異なる点に注目して書きます。
なぜ数ある仕様の中から演算優先順位を先立って取り扱うかというと、コードゴルフして遊ぶときに()の削減は必須だからです。
ビット演算子
優先順は Python、JavaScript ともに以下です。
~→<<,>>→&→^→|(左が優先度高)
まあ、これは基本に忠実です。上述のビット演算の項での記述を見ればどういうことかよく分かるかと思います。
コードゴルフに限らず、明示的に演算順序を指定しないと結果がどうなるかわからないというのは不健全な気がします。
明示的なコードは大事ですが、ことさらに()を多用するのも一長一短だと思っているので、最小限の()で表現する練習はしておいて損ではないでしょう。
冪乗**
Ptyhon では冪乗**が単項演算子+, -, ~より優先。JavaScript は逆。
冪乗は大きく桁が動くので重要なポイントです。
関係演算子
Python では関係演算子in, not in, is, is not, <, <=, >, >=, !=, ==はすべて同位。
JavaScript では、<, <=, >, >=, in, instanceofが==, !=, ===, !==より上位。
C++もほぼ同じで、<, <=, >, >=は==, !=より上位。
論理否定
論理否定Notは Python では比較演算子より下位。
JavaScript や C++では論理否定!はビット否定~と同位。
インクリメント・デクリメント
Python にはインクリメント用の演算子はありません。
JavaScript や C++ では後置演算子x++, x--のほうが前置演算子++x, --xより優先になります。
その他
それ以外は微妙に異なる部分もありますが、実用上は同じと捉えておいて良さそうです。
文字列操作
| 言語 | 文字数 | i 文字目 |
|---|---|---|
| Python | len(s) | s[i] |
| C++ | s.size() | s.at(i) |
| VBA | Len(s) | Mid(s,i,1)3 |
VBA は文字列をイテレータ的に扱えないので操作には難があります。
配列
| 言語 | 宣言 | 要素数 | i 番目 |
|---|---|---|---|
| Python | a=[0]*N | len(a) | a[i] |
| C++ | vector<int> a(N,0); | a.size() | a.at(i), a[i] |
| VBA | Dim a(N) as Long | Ubound(a)-Lbound(a)+1 | a(i) |
C++には他にもint a[100];やarray<int, n> a;のような配列もありますが、配列のサイズを別個にsize_t型の変数で管理しないといけなかったり、固定長配列だったりして競プロだとあまり使わないので割愛しました。
| 言語 | 末尾参照 | 先頭参照 |
|---|---|---|
| Python | a[-1] | a[0] |
| C++ | a.back(); | a.front(), a[0] |
| VBA | a(Ubound(a)) | a(Lbound(a)) |
他にも sort とか reverse とか sum とか max/min とかありますが、VBA が不憫なので今日のところは割愛します。
VBA は配列操作ライブラリを自作しないと、到底まともに扱えないですね。要するにクs
追記予定
とても一度には網羅的に書くことはできないので順次追記していきます。
特に、C++はまだ習熟度が低いので鍛錬を重ねていきます。