プログラミング言語 予約語比較
はじめに
こんにちは。高校2年の樅山です。
2020/11 から始まった、ものづくりをする高校生のための新しいグループ、「Palettte」が主催する Palettte Advent Calendar 2020 の5日目の記事となります。
Twitterを眺めていたところ、「モダンな言語ほど関数を宣言するための予約語が短い」「現代は補完が効くのだからfunctionのように正式な予約語を採用するべき」というような議論を拝見しました。
個人的には、それらの予約語がプログラミングの体験を大きく変化させる印象はありません。
しかし、多くの言語が微妙に異なるキーワードを採用しているのは事実です。例えば、私が好んで利用している言語 Nim ではProcedure[1]の略で proc という予約語を用いて関数を宣言します[2]。
そこで非常に多くの言語が生まれる中、どの言語でどのようなキーワードが使われているかを比較できるようにしようと考え、まとめることにしました。
予約語比較
比較する言語の一覧です。
各言語で、存在しない概念の場合は「-」と書くことにします。
C, C++, Objective-C, D, C#, F#, Java, Kotlin, Scala, Go, Swift, Nim, Rust, Dart, JavaScript, TypeScript, Haskell, Lisp, OCaml, Erlang, Elixir, PHP, Python, Ruby, R
変数 / 定数
変数宣言 | 不変変数宣言 | コンパイル時定数宣言 | |
---|---|---|---|
C | <type> | const <type> | - |
C++ | <type> | const <type> | constexpr <type> |
Objective-C | <type> | const <type> | - |
D | <type> | const <type>[3] | - |
C# | <type> | const <type> | - |
Java | <type> | final <type> | - |
Dart | <type> | final | const |
Kotlin | var | val | const val |
Scala | var | val | - |
Go | var | const | - |
Swift | var | let | - |
Nim | var | let | const |
Rust | let mut[4] | let | const |
Lisp | let | defconstant | - |
JavaScript | let[5] | const | - |
TypeScript | let | const | - |
Haskell | - | -[6] | - |
F# | let mutable | let | - |
OCaml | - | let[7] | - |
Erlang | - | -[8] | - |
Elixir | - | -[9] | - |
PHP | -[10] | const | - |
Python | -[11] | -[12] | - |
Ruby | -[13] | -[14] | - |
R | -[15] | - | - |
変数宣言 <type>
- C, C++, Objective-C, D, Java, Dart が該当します。
- 全て、元を辿るとCから影響を受けた言語です。
<type> - const <type>
- C, C++, Objective-C, D, C# が該当します。
- better Cを意識してスタートした言語に多いように思えます[16]。
- C++では、コンパイル時に評価される定数であるコンパイル時定数が
constexpr
で宣言できます。 - Cの文法の特徴が後発の引き継がれたようです。元を辿ると、Cに影響を与えたB言語では
auto 変数名
のように変数を定義していました。B言語には型がなく(それがCが生まれる要因の一つとなりました)、型が導入されたことでauto
の代わりに型名を使って変数を定義するようになったのはごく自然な構文のように思えます。
<type> - final <type>
- Java, Dart が該当します。
- 不変変数に final キーワードを採用した言語はJava以前には私は発見できませんでした。
- Dartは、Javaの影響を受けている言語ですので、自然な構文に思えます。
変数宣言 var
- Kotlin, Scala, Go, Swift, Nim が該当します。
-
var
は、variableという「変数」を意味する英単語の略です。 - これらの言語は、それぞれ 2011年 2003年 2009年 2014年 2008年 と、比較的 最近開発された言語に多く見られ、最近の変数宣言の主流は var か、後述する let が多いように思えます。
変数宣言 let
- Rust, Lisp, JavaScript, TypeScriptが該当します。
-
let
は、「...させる」のような使役の意味を持った英単語で、let foo = "bar"
のような宣言では、「foo
を"bar"
にする」と訳すことができます。 -
let
はとても英文法に近いキーワードで、var
と同様に最近の言語によく見られる傾向があります。
宣言キーワードなし
- PHP, Python, Ruby, Rが該当します。
- これらの特徴として、全て動的型付けインタプリタ言語であるというものがあります。
可変変数という概念がない
- Haskell, Erlang, Elixirが該当します。
- これらは関数型言語の特徴を持っており、全ての変数は不変変数でなければなりません。[17]
関数
関数宣言 | 純粋関数宣言 | メソッド宣言 | |
---|---|---|---|
C | <type> | - | - |
C++ | <type> | - | <type> |
Objective-C | <type> | - | - (<type>) |
D | <type> | - | <type> |
C# | <type> | - | <type> |
Java | <type> | - | <type> |
Dart | <type> | - | <type> |
Rust | fn | - | fn |
Kotlin | fun | - | fun |
Go | func | - | func |
Swift | func | - | func |
Nim | proc | func | method |
Elixir | def[18] | - | - |
Scala | -[19] | - | def |
Python | def | - | def |
Ruby | - | - | def |
Erlang | function | - | - |
JavaScript | function | - | function |
TypeScript | function | - | function |
R | function | - | function |
PHP | function | - | function |
Lisp | defun | - | demethod |
F# | let | - | member |
OCaml | let | - | method |
Haskell | - | -[20] | - |
終わりに
変数と関数のみの比較となりましたが、今後も少しずつ更新していきたいと思います。
もし、この言語を追加して欲しいという要望があれば、「変数宣言」「不変変数宣言」「コンパイル時定数宣言」「関数宣言」「純粋関数宣言」「メソッド宣言」の有無・キーワードをコメントしていただければ対応します。
また、私が普段使いしていない言語も調べて書きましたので、誤りがあればご連絡ください。
-
Procedure は、「手続き」という意味の英単語です。 ↩︎
-
厳密に言えば、数学的な関数の概念に似た、ある値を与えると必ずある一つの値を返す副作用のない関数の宣言の場合には func を用います。今回は、プログラミングにおける副作用のある関数を「関数」と呼ぶべきか、という点については一切触れません。 ↩︎
-
D言語には、
const
の他に、immutable
という概念もあります。const
の場合、const
で宣言された不変変数の参照からは値を変更することはできませんが、可変変数で宣言された、同じ値への参照からは破壊的操作が可能です。しかし、immutable
で宣言された値に関しては、可変変数からの参照でも変更されることはありません。 ↩︎ -
Rustでは、変数がデフォルトで不変であるため、可変変数の束縛には
mut
(mutable、可変の略)をつける必要があります。 ↩︎ -
JavaScriptには、
var
という概念もあります。そもそもvar
が先発で、let
、const
はES2015という後発バージョンで追加された機能です。var
は再宣言可能であり、ブロックスコープではなく関数スコープを持っており、さらに「巻き上げ」が発生しうるため非常に扱いが難しい変数です。現在は、let
を標準的に用いることが推奨されています。 ↩︎ -
Haskellの不変変数は、宣言キーワードを持ちません。恐らく、変数は「束縛する」もので再代入が存在せず、キーワードが必要ないからです。 ↩︎
-
ただし、参照型の変数に関しては破壊的代入することができます。(ご指摘いただきました) ↩︎
-
Erlangの不変変数は、宣言キーワードを持ちません。恐らく、変数は「束縛する」もので再代入が存在せず、キーワードが必要ないからです。 ↩︎
-
Elixirの不変変数は、宣言キーワードを持ちません。恐らく、変数は「束縛する」もので再代入が存在せず、キーワードが必要ないからです。 ↩︎
-
PHPの変数は、宣言キーワードを持ちません。 ↩︎
-
Pythonの変数は、宣言キーワードを持ちません。 ↩︎
-
Pythonには定数が存在しませんが、慣習的に全て大文字で命名された変数は開発者には定数として扱われます。 ↩︎
-
Rubyの変数は、宣言キーワードを持ちません。 ↩︎
-
Rubyの定数は、宣言キーワードを持ちません。全て大文字で命名された変数が定数として扱われ、再代入すると例外が発生します。 ↩︎
-
Rの変数は、宣言キーワードを持ちません。 ↩︎
-
要検証 ↩︎
-
実際には、標準ライブラリに可変変数として振る舞う概念が存在していることもありますが、本記事では省略します。 ↩︎
-
Elixirは匿名関数を用いるときに、
fn
キーワードを用います。また、その省略記法である&
がよく使われます。 ↩︎ -
Scalaでは、
Function0
〜Function2
のトレイトの無名サブクラスのインスタンスのことを関数と呼びます。 ↩︎ -
Haskellの関数は、宣言キーワードを持ちません。 ↩︎