(なんかRustが嫌いみたいなブログがバズったようなので、それに便乗してみるw)
自分はプログラミングやプログラミング言語が好きで、いくつかのプログラミング言語を勉強してきたので、それを振り返る形で書いてみたい。
BASIC
最初に覚えたプログラミング言語はBASIC。
なんと言っても、エディターの起動速度なら一番だろうw
MSX-BASICなら、パソコンを起動すればBASICのエディター画面になるからね!(パソコンの起動時間は、エディターの起動時間には含めないよね?w)
試行錯誤しながら覚えるには、インタープリター言語であるBASICは最適。
行番号を付けて命令を入力すればプログラムとして保存され、RUNと打つだけで実行できる。なんて分かりやすいw
当時は雑誌にプログラムが掲載されていて、それを見ながら手打ちで1文字1文字プログラムを入力していったものだ。
当然打ち間違いが発生して、エラーが発生することもしばしば。
一番の思い出は、長編RPGの長いプログラムを入力して、時間をかけてクリアして、さあエンディングだ!ってなったときにピッとSYNTAX ERRORが出たことかな(爆)
(プログラムを修正して、さすがにゲーム本編をやり直す気はしなかったから、goto文でエンディングに飛ばせた^^;)
アセンブリ言語
アセンブリ言語は、CPUが実際に読み込む機械語に対応したニーモニックで記述する言語。
BASICはインタープリター言語だけあってやはり実行速度が遅いので、アセンブリ言語で書いてアセンブルしたアプリケーションは速くて素晴らしかった。
アセンブリ言語は命令セットがシンプルなので、シンプルな言語が好きな人にはお勧めw
ただ、MSXだと命令を間違うとすぐに青い画面になるから、デバッグは大変かも。
(ここで言う青い画面とは、MSX2や2+の起動画面のこと。起動時に青い画面の中央にMSXの文字が出るのだ。つまり、プログラムが暴走してパソコンがリセットされるという意味^^;)
(それに比べて、Windowsのブルースクリーンはエラー情報を出してくれる分、だいぶマシかも?)
C言語
C言語の便利なところは、何と言ってもポインター。
C言語を勉強するとポインターで躓くという話をよく聞くけれど、アセンブリ言語を学んだ後ならポインターの利便性はよく分かる。
アセンブリ言語では、アドレス(ポインター)が指している先のデータが1バイトなのか2バイト整数なのか文字列なのかといった情報は、プログラマーが管理する必要がある。
しかしC言語では、int* ならそのポインターが指しているデータがintなのがすぐ分かる。とても便利だ。
あと、個人的には記号を駆使しているのが好きだ。代入が=で加算が+、それを合わせて+=とか。インクリメントが++とか。
アセンブリ言語の「ADD A, B」がBASICだと「A = A + B」、C言語だと「A += B」と書ける。
同様に「INC A」がBASICだと「A = A + 1」だがC言語だと「A++」。なんてシンプルなんだ。
Pascal
大学に入って講義で使われたのがPascal。
C言語に似ているけれど、C言語がソースコードの短さを目指しているように感じられるのとは異なり、Pascalは「理論的にこうあるべき」というのを目指した言語という印象。
Lisp
括弧が多いことで有名な言語。
実際、括弧は多い^^;
大学で自分が所属した研究室で独自のLisp実装が作られていたけれど、開き括弧に比べて閉じ括弧が余分にあってもエラーにならないようになっていた。
つまり、プログラムは「(hoge)))))))」みたいに余分な閉じ括弧が常に付けられていた^^; プログラムを変更したときに括弧の対応付けをするのが面倒だったんだろうね^^;
C言語やPascalでは関数呼び出しは「関数名(引数)」という書き方だが、Lispでは「(関数名 引数)」のようになっていて、そんな書き順もいいんだというカルチャーショックのようなものを感じた。
Prolog
大学の講義で聞いただけなので、実際に使ったことは無いんだけど。
第5世代言語とか言われて、人工知能につながると考えられていたっぽい。
BASICやC言語等の汎用的なプログラミング言語とは一線を画していて、こういうのもプログラミング言語って言うんだ…とちょっと思った^^;
Yacc/Lex
大学で学んだことで驚いたことのひとつは、プログラミング言語を作るための言語があるのだということ。
ここでYacc/Lexを勉強したことでで、会社に入ってからDMDL Editorを作ることが出来た。
AWK
大学でYacc/Lexを使ってAWKのインタープリターを作るという実習があって、AWKを勉強した。
なので、UNIX上で文字列を加工したいときは、sed等よりawkの方が慣れているw
C++
C言語にオブジェクト指向を取り入れた言語。(一番最初のC++コンパイラーは、C言語に変換するものだったらしい)
オブジェクト指向の概念は衝撃的だった。
自分もC言語を使っていていくつか不便な点を改善した言語を作りたいなぁと思ったことはあるけど、オブジェクト指向の発想には絶対至れなかったと思う。
自分がオブジェクト指向に一番価値を見出している部分は、クラスの責務の概念。
C++のクラスの元になったのはC言語の構造体だと思うが、構造体のフィールドはどの関数からも更新することが出来る。つまり予期しない場所でも更新するコードが書けてしまう。
それに対し、クラスではフィールド(メンバー変数)にアクセスできるのはクラスのメソッド(メンバー関数)だけ。クラスはフィールドを管理する責務を持つ。別の言い方をすれば、特定のデータを扱う責務を持つのがクラス。責務外のデータにはアクセスしない。
だから、フィールドやメソッドをそのクラスに持たせるかどうか=クラスの責務に合致しているかどうかという判断基準はプログラミングの基礎になると思う。
(責務の考え方は、オブジェクト指向のクラスだけでなく、DBのテーブルとかコンポーネントの切り分け等にも応用できると思う)
SQL
リレーショナルデータベース(RDB)を操作するための言語。
自分は会社に入ってからSQLを覚えた。
大学で「データベース論」だったかな、そういった講義があったんだけど、当時はデータベースが何だか分かってなくて第3正規形とか意味不明だったんだけど、実際にRDBを扱うようになって、ようやくその意味が分かった^^;
DBを操作しようと思ったらDBが提供している独自言語を使った方が実行効率が良いってことはままあると思うけど、SQLが標準的すぎて、SQLが無いDBは使ってもらえない感がある^^;
Java
C++の次に流行った言語。オブジェクト指向を中心に据え、C++の欠点を克服しようとしたのだと思う。
Javaはいろいろ画期的だった。
コンパイルするとCPUが解釈できるバイナリーではなく中間のclassファイルを生成し、JavaVMがclassファイルを読んで実行する。
これにより、コンパイルする環境と実行する環境が同一でなくてもよくなった。
(C++だと、Linuxで動くアプリケーションをWindows上でコンパイルする方法なんて、考えたくない^^;)
しかしJavaVMはある意味インタープリターなので、実行速度が遅くなるという批判があった。
それに対し、JIT(Just In Time)コンパイラーを実現し、Javaは実行速度がかなり速い部類になった。(この成功を受けて、JITは他の言語でも採用されることになったのではないかと思う)
GC(ガーベッジコレクション)も画期的だった。
自分はリソースの管理をきっちり出来る(確保したメモリーを正しく解放できる)のが優れたプログラマーだと思っているが、やはり複雑なプログラムではリソースをちゃんと解放させるのは難しい。特にメモリーを確保してそれを関数の外に返す場合、どうすればきちんと解放できるのか、というのが…。
GCはそこを勝手にやってくれるので、プログラミングはすごく楽になった。
C++との兼ね合いで言うと、例外クラスが整備されたのも優れている。
C++のthrowは、整数でも何でもスローすることが出来たので、catchする側でそれに対応するのが大変だった。
Javaの例外は例外クラスで管理するデータが確立し、スタックトレースが出せるのもすごかった。
あと、リフレクションも驚きだった。
実行時にメソッド名を文字列で指定して呼び出せるなんてねぇ。
(よく考えたら、Lispでも実現されてた気はするけど^^;)
HTML
HTMLがプログラミング言語かと言うと議論があるようで、プログラミングっぽくは無いと思うけれど、言語ではあるよね?^^;
ウェブブラウザーが解釈して整形して画面に表示されるのに使われる。
表示されない属性もタグという形で一緒に管理するという文法は、分かりやすい。(閉じタグがくどいという話はあるが^^;)
ウェブブラウザーで表示される画面のソース(HTML)を見て、HTMLを勉強するということも昔はよくやった。
もっとも、今や人間が扱うのは他の記述方式に替わり、HTMLはプログラマーが直接書くのではなく生成されるのがほとんどかな。
ただ、自分は今でもHTMLエディターを使ってウェブページ作ってるよw
エディター上ではHTMLを意識せず書くけど、細かい調整はHTMLを直接いじる方が確実だったりする。
ホームページを提供するサービスはいくつもあったけど、けっこう閉鎖されて、インターネット上から過去の情報が消えたなんて話もあるみたいで…。
自分のウェブページは、インターネットプロバイダーにお金を払っている間は残るはずw
JavaScript
ウェブブラウザー上で動作するプログラムが書ける。
Javaを宣伝したいというマーケティングの都合でJavaScriptという名前になったみたいだけど、別物なので、今でもJavaとJavaScriptが混同されて混乱のもとになることがある^^;
ブラウザー上でJavaScriptを動かすとセキュリティーリスクがあると言われた時期があり、JavaScriptをオフにするのが推奨されていたこともあるくらいなんだけど。
GoogleがJavaScriptを駆使してGoogle MapやGmailといったサービスを作った衝撃で、JavaSciptは一気に復活した、と思っている。実際、ぐりぐり動くGoogle Mapは衝撃的だった!
最近はブラウザー上だけでなくサーバーサイドやローカルでもJavaScriptで動かせるようだけど、自分の知識は古いままだなぁ…。
TypeScript
TypeScriptは本で読んだだけなんだけど。
JavaScriptに型を持ち込んだ言語。(コンパイルするとJavaScriptを生成する)
自分は型のあるプログラミング言語が好きなので、JavaScriptを扱う機会があったら、TypeScriptを使いたい。
(プログラムはデータを扱うもので、データには必ず型がある。プログラミング言語によってそれがプログラム上に明示されるかどうかの違いはあるが、自分はコンパイラーに型をチェックして欲しい派。特に大規模なプログラムでは)
Scala
JavaVMは優秀だけど、Java言語のプログラムは冗長なところが多いよね(近年はいろいろ改善してきてるけど)…ということで、JavaVMで動くclassファイルを生成するJava以外の言語というものが生まれた。
有名なところでGroovy、Kotlin、そしてScala。
GroovyはGradleとして大変お世話になっております。
Kotlinは使ったことないんだけど、Androidでアプリケーションを作るのに使われているのだとか?(やっぱりキラーアプリがある言語はよく使われるよね)
Scalaは単純にJavaを便利にした構文もある(importの別名とか)けど、やはりオブジェクト指向プログラミングと関数プログラミングを融合させた点が大変素晴らしい。
Scalaの型はしっかりしていて、JavaだとList<String>とList<Integer>は関数の引数としてはどちらもListなのでオーバーロードできないんだけど、ScalaではSeq<String>とSeq<Int>は別物。
そういえば、JavaのintとIntegerがScalaではIntで統一されているのもいい。
それから、コレクションの統一感(継承関係)が良い。(ArrayとListがSeqを継承しているとか)
JavaでStream APIが導入されて便利になったけど、Scalaのコレクションの使いやすさにはやっぱり及ばないんだよねぇ。(JavaのStream APIは、なるほどJavaで導入するならこうなるかって感じで、特にFunctionalInterfaceとかcollectメソッドとかにすごく努力の跡が感じられるんだけど^^;)
Haskell
一度本格的に関数プログラミング言語を学んでおいた方がいいかと思って、ちょっとHaskellの勉強をしようかと思ったことがあったんだけど、関数呼び出しの引数が丸括弧で囲まれていないから関数呼び出しに見えず、即座に挫折しました。ごめんなさいorz
(C言語を学んで以来、一番長く使っている言語がJavaなので、脳がそういう関数呼び出し形式にすっかり染まってるんだよね…)
Python
Pythonの特徴は、インデントが決まっていること。
C言語やJavaだと、ブロックは波括弧で囲まれていればよく、しかしコーディング規約の方言によって、波括弧のどこで改行するかがまちまちだったりする…。
Pythonはインデントでブロックが決まるので、ソースコードの見た目も統一される。
インデントが強制されると不自由じゃないかなーと思ってたんだけど、実際コーディングしてみると、別に違和感は無かった。
少し気になった点は、PythonはJavaと同世代の言語の割にオブジェクト指向が中途半端な感じがする(長さを取得するのが関数なのかメソッドなのか統一されていない感じ)程度かなぁ。
あとはやはりコンパイルする言語じゃないので、例えばimort文が抜けてたら、Javaならコンパイルエラーになるんだけど、Pythonだと実行するまでエラーにならないのがちょっと…。
Javaのインターフェースに相当するものが無くて、特定のメソッドが定義されていたら特別な処理が出来るようになってる(ダックタイピング?)けど、その辺りはまさにプログラミング言語の考え方の違いだろうね。
Rust
Rustは所有権で有名な言語。
GC(ガーベッジコレクション)は無く、値が使用されなくなった時点でリソースを解放するのだが、それをコンパイル時点で判定する。
そのための概念が所有権で、これ自体はとても分かりやすいし超納得できる。
GCは実行に時間がかかることがあるし、リソースの解放がいつ行われるのか分からないという問題もある。所有権はこれを解決する。
しかし実際にRustでコーディングしてみると、所有権の考え方より「参照」で非常にハマった^^; 不変参照と可変参照の違いも甘く見ていた^^;
ChatGPTに質問したら意外と正しく答えてくれたのでなんとかプログラムできた感じ。AIが無かった時代にRustのプログラムを書いていた人たちは超すごいと思う。。
それから、C++やJavaのような例外機構が無い。Javaの例外はcatchブロックを作る必要があって、ブロックを作ると変数のスコープが影響を受けるので、コーディングしやすさを阻害する要因にもなる。
Rustは正常時の値とエラー時の値を返す構造体が用意されていて、それを扱いやすくする構文がある。
それから、あまり言及されることが無いように思うけれど、Rustは後発の言語なだけあって、エコシステムが大変素晴らしい。
最初のRustプロジェクト(ソースコードの雛形)作成もビルドも単体テストの実行もcargoコマンドひとつで出来る。
それどころか、依存ライブラリーの追加やソースコードの整形やドキュメンテーションコメントからのHTML生成まで全部cargoコマンドで出来る。
依存ライブラリーの公開方法(crates.io(JavaのMavenリポジトリー相当))も提供されているし、開発周りについて一通り揃っている感じだ。
cargo(≒rustコンパイラー)が対応している環境であれば(つまりWindowsでもLinuxでも)、同じコマンド・設定で実行バイナリーファイルが生成できる。
C言語から呼べる形式のファイル(WindowsのdllファイルやLinuxのsoファイル)も生成できるので、複数環境へ提供するプログラムを書くなら、C言語よりRustの方が便利だと思う。
というか、Rustって低水準なプログラミング言語のような気がする。高水準なプログラミング言語であるJavaなんかはプログラムは書きやすいけど環境ネイティブなバイナリーは生成できないし、目的次第だよね。
AIプロンプト
最近は、LLM(大規模言語モデル)(いわゆるAI)が発達してきて、自然な文章で質問して文章で回答を返してくれる。誤った答えを返すことがあるにせよ、これはこれで本当にすごい。
(MS-Excelのイルカ君、君は登場するのが早かったんや…)
LLMに指示してプログラムを生成することも出来るようになってきているらしい。まだ粗があるようだけど…。
もっとAIが発展すれば、確かにプログラム自体が不要になるかもしれないと思うよね。
例えば今でもClaudeは自然言語で質問すれば内部でselect文を生成してDBに問い合わせしてくれるから、こういうユーザーインターフェースが普及すれば、プログラマーがSQLを書く機会は減っていく(≒SQLが廃れる)だろう。HTMLを人が直接書く機会が減ったのと同じようなものかも。
そもそもSQLも自然言語(英語)に近い形で問い合わせたいという目的で決められた文法らしいし、その目的をLLMがようやく実現しつつあるということじゃないかな。
実際には、LLMは既存のプログラムを学習しているだろうから、既存の範囲内のもの(新しい組み合わせ)は生成できそうだが、世に公開されてないものやニッチなものは作れないような気がする。
(例えばLLMに「新しいDBMSを作って」と指示したとして、既存のDBMSより高性能で信頼性が高いDBMSのプログラムが生成できるか?)
まぁLLM以外のAIも研究されているだろうから、今後どうなるか分からないけど。
最後に
思ったより長文になってしまった^^;(書くのに4時間半くらいかかってるぞ…orz)
まぁ、プログラミング言語というものは、既存言語の欠点を改善するために新言語が生まれているわけで。そしていまだに究極のプログラミング言語が現れていないのは、何かしらのトレードオフがあるからだよね。
だから新しいプログラミング言語を使おうと思ったら、そのプログラミング言語の思想(何が改善されたのか)を勉強する必要があるっていうか、発想の転換をしてみる機会だと思うのがいいというか。郷に入っては郷に従えみたいな?
まぁそれでも思った通りのことが出来なくて「このくそ言語!」と思うこともあるけれど、上手く解決できたときに「なるほど、こりゃすげえ!」ってなれば嬉しいよねw
ちょっと話が逸れるけど、ゲームについて。
自分が子供の頃に8bitのゲーム機が出て、次に16bit機が出て、ポリゴンが出て3Dが綺麗になって…という流れを体感できたのはとても運が良かったと思っている。
今でも8bit時代のゲームをやることは出来るだろうけど、それが出た当時の熱狂は分からないよね。
プログラミング言語も同じで、プログラミング言語の進化を体験できる時代に生きているのは、とても運が良いことだとしみじみ思う。