見出し画像

Retro-gaming and so on

C++は結構良い言語

プログラマは結構嘘を言う。
嘘、って言うのはこの場合、何かしらに対して発言した際に、それが「論理的な帰結」ではない、って事だ。
要は「根拠がない」。偉い誰それが言ってたから、とか皆そう言うから、とか背景は実はその程度のモノだったりするんだ。
このブログでも、いくつかそういった流言が嘘だ、と取り上げてきた。

  • 再帰は難しい -> 嘘。少なくとも「大学受験で入学した」学生にとっては難しくともなんともない。何故なら再帰は高校数学で習う漸化式の別名だから、だ。受験が終わったら押し入れに詰め込んだ数学の問題集の漸化式の問題を10題もプログラミングしてみれば形式にはあっという間に慣れるハズだが、教える方もバカなのか、「再帰は漸化式の事だ」と言わないらしい。従って大学を卒業しても「再帰は難しい」「再帰は神秘的」と言うような途方もない勘違いをした人間を量産している。
  • C言語はプログラミングの基礎 -> 大嘘。そもそも「基礎」ってのが一体何を指して言ってるんだかサッパリ分からない。言ってる本人も「何が基礎なのか」把握してないんだろう(※1)。ちなみに、何人かプログラマにサーヴェイしてみたんだけど、「C言語を学んでコンピュータの仕組みを理解しました!」なんつーヤツは一人もいなかった。事実は逆で、機械語やアセンブリ言語に明るい人間が「C言語を使いこなすのが上手い」。言い換えると、本当の「基礎」はマシンレベルでどっぷり浸かってる人が把握してる事であり、そういう人がC言語を理解しやすい、って事なんだけど、結果それは不可逆的なんだ。また、大学でコンパイラやインタプリタの作り方を学ぶせいで「C言語はプログラミングの基礎」って勘違いするのかもしれんが、コンパイラ/インタプリタの実装技術とC言語である必然性は全く関係がない。何ならPythonだろうとコンパイラ自体は実装可能だ・・・コンパイル作業が遅くてもな。そして「吐き出す実行形式の速さ」は直接そのコンパイラを「何で実装したのか」とは関係がないんだ(※2)。
前にも書いたけど、ポール・グレアムは偉大なハッカーだ。ただし、彼の発言の全部が全部「正しい」わけじゃない。彼もプログラマに良くある「流言」をそのまま繰り返したりする。
彼の最大のミスはマイクロソフトに対する攻撃だ。これは往年のアップルが流布した「嘘」に等しい。曰く「一回もマイクロソフトが作ったソフトウェアを使った事がない」。でも彼は「マイクロソフトのOS及びソフトウェア」が出来が悪いモノ、として攻撃するんだ。コッチ側は彼の発言を盲信するのではなく、使ったことがないメーカーのソフトの良し悪しの一体何が分かるんだ、とツッコむくらいの知性を持つべきだよな。真実はここには無く、ここにあるのは単なるバイアス、ってだけだ。

さて、ここに一つ「良く言われる流言」を付け足す事にした。いわゆる「Cはいい言語だけどC++はそうじゃない」と言った類の流言だ。事実は全然違う、って事を痛感してる。
前にも書いたけど、「C++嫌いのCハッカー」として有名なのが、Linuxを作ったリーナス・トーヴァルズだ。他にも、どういうわけか、「プログラミング言語を実装するプログラミング言語」としてCの選択例は多いけどC++の選択例は寡聞にして聞いた事がない。Javaの方が多いくらいだろう。C++を避ける根拠が良く分からん。嫌がらせなんじゃねぇの、ってほど使われてないんだ。

僕が好きなエッセイを書くスティーヴ・イエギ、って人がいる。この人もこんな事を書いている。うん、僕もホント、結構真に受けてたんだ。
ある意味、だからこそCにこだわって、もっとラクにプログラミング可能なんじゃねーの、ってぇんでGLibの記事なんかを書いてきた。しかしながら、結論から言うと、「Cの外部ライブラリであるGLibを使う」より圧倒的にC++標準ライブラリであるSTLの方が使いやすいんだ。明らかに使い勝手で比べるとGLibはSTLに及ばない。っつーか無理してGLibを使うくらいだったらC++を選んでSTLを使う方が素直にラクなんじゃないの?ってのが感想だ。

スティーヴ・イエギが書いてる事をまとめると、主要なポイントが2つあって、1つ目は「C++はオペレーティングシステムを書くには向かない」(※3)。それはそうなのかもしんない。OSはミニマルに実装されるべきであって、「機能が豊富な」C++で書けば実行形式が大きくなって不都合が生じる、って事はあり得るだろう。
ただし、「オペレーティングシステムを書くには向かない」がそのまま「アプリケーションを書くには向かない」と同値か、って訊かれればそれは違うだろう、って事は言えると思う。PythonでOSを書こう、とすれば「バカな事を考えるのは止めなさい」と言われるのは是かもしれんが、それがすなわち「Pythonでアプリケーションが書けない」を意味しないだろう。「適材適所」と言う意味ではC++は批判対象にならんのだ。
単にC++はアプリケーションを書くには充分な言語なんじゃないか、ってのは言えるとは思うんだ。
もう一つの批判は「C++は本質的にパースできない」と言う部分だろう。いや、これが本当に何を意味してるのか、ってのは正直言うと良く分かってないんだが、恐らくC++がマルチパラダイム言語だ、と言う事を批判してるんだろう。要はC++は手続き型言語であるC程単純じゃない、って事だ。「機能が豊富」だと言う事は機能によって構文が変わり得る、って事なんじゃないか。だから「パースできない」。
要は、一般的にC++は「オブジェクト指向版C」と捉えられてるけど、それは一面でしかない。実際は、もっと高機能な言語なんだ。だからスティーヴ・イエギは「すごい遊び場」だと表現している。一方で、C++での「良いコード」とは「ほとんどCのコードに、いくらかのC++の機能が、最低限だけうまく使われているような」コードの事だ、と提言してる。

なお、「Cのオブジェクト指向拡張」をターゲットにした言語は実は二種類ある。
この2つの言語は、言っちゃえば「オブジェクト指向」の捉え方が違い、C++はオブジェクト指向の祖、Simulaの影響をモロに受けているが、一方、Objective-Cの方は「オブジェクト指向」と言うアイディアを広めたSmalltalkに影響を受けていて、趣はかなり違う(※5)。
しかしながら、C++が1998年に国際標準機構(ISO)で標準仕様を制定された時点で、実はC++は単なるオブジェクト指向言語ではなくなっていた(※6)。
この時点でC++は「ジェネリックプログラミング」言語になってたんだ。

もう一回繰り返す。スティーヴ・イエギは「C++はパースできない」と言っていた。そしてC++は「すごい遊び場である」と。
C++は最初は「オブジェクト指向として拡張した」C言語として生まれた。ところが、国際標準規格が制定された時点では既に「オブジェクト指向言語」を逸脱していて、「ジェネリックプログラミング言語」なるものに変わっていた。
そしてその「ジェネリックプログラミング」の鍵を握ってるのがSTL(Standard Template Library)と名付けられたC++の標準ライブラリだ。
最初の方に掲げた通り、多くの著名なCハッカーはC++を無闇に嫌っている。一方、熱烈なC++ファンも存在する。しかし、僕が観察する限り、「熱烈なC++ファン」ってのは「C++のCの部分」とか「C++のオブジェクト指向の部分」を好んでるわけじゃない。そうじゃなくって彼らが愛してやまないのは、この、「仕様上、標準ライブラリとして添付された」STLのファンなんだ。
そう、C++って言語は、極端に言うと「2つの別々のプログラミング言語」が内包されてるような言語なんだ。一つは「オブジェクト指向拡張されたC言語部分」、そしてもう一方がSTLだ。STLはSTLで「まるで独立してるような」プログラミング言語部分になっている。
そしてそれが故にC++は「本質的にパースできない」くらい複雑になってるんだ。

実際、信じられないかもしんないけど、C++のSTLってのは「C++のC言語部分、あるいはオブジェクト指向部分」ってのを全く知らなくても使える(笑)。
いや、これマジな話(※7)。
僕がC++を初めて使ってみたのは数年前、教えて!gooのC++に関する質問があって、たまたまそれを目にした時、何故か「C++で書いてみっか」って思いついた時だった。
繰り返すが全くC++を使った事がなかったのに、だ。
ところが、それでも書けちゃったんだ。これには我ながらビックリした。ぶっちゃけLispの知識でC言語を書く、なんつーのは不可能なんだけど、Lispの知識でSTLは使える。これは衝撃的だったんだ。「え?」とか思った(笑)。
もちろんLispに比べて使いやすい、って事はないんだけど、「こうしたい」って思った事がリファレンスを調べる程度で実現可能だ、ってのにはマジで驚いたんだ。
さて、貴方はC言語は知ってるだろうか。「知らない」って人でも構わない。貴方がLispや他の関数型言語に関する知識があれば、「C言語は使えなくても」C++のSTLは使える可能性が高い。嘘って思うかもしんないけどそれが事実で、それが僕が経験した事だったんだ。

ちょっと前回紹介したコードの話をしよう。アレは元々、元ネタとしては「競技プログラミング」と言われるブツの問題だ。競技プログラミング、って事は対象言語はC/C++/Javaに限定される
「ウチの競技プログラミングはC/C++/Javaに限定してないです!」とか言う輩がいたとしてもハッキリ言ってそれは嘘だ。あらゆる言語に対応するような問題は存在しない。そして競技プログラミングはC/C++/Javaと言う「狭いサークル」の中でしか存在できないゲームなんだ。
と言うわけで、前回はRacket/Pythonでコードを書いたが本来はご法度なんだよ。当然、C/C++/Javaで書くべき問題なんだ。
ところが、だぜ。この「狭い縛り」の中で、C++は辛うじて「はみ出る事が出来る」んだ。
ちと見てみよう。例えば、前回見せたPythonコードは次のようなモノだ。



さて、同様のコードをC++で書くとする。どうなるか



分かるかな?完全に一対一対応とはイカんけど、ほぼPythonでのロジックを再現出来てるんだよ。本当だったら両者横に並べて見比べてみればもっと分かりやすいんだけど、かな〜り「同じ事を」やってるんだ。
もちろんC++は型宣言が面倒くさい、とかリストのスライスが再現出来ないんで、ベクタを新規作成して、古いベクタの部分的要素指定して代入する、とか「C++特有の」やり方をせなアカントコはある。あるんだけど、それでも「ロジックをほぼ完全に移植可能だ」ってのは驚きの性能だと思う。
そもそもPython版は「関数型プログラミング」っぽく書いている。言い換えると「関数型プログラミングっぽく書いてる」Pythonコードが読め、(ほぼ)一対一対応のC++コードを目で追えるなら、貴方はC++の基礎と思われている「C言語部分」と「オブジェクト指向部分」を知らなくても、STLならプログラミング可能だ、って事を示唆してるんだ。
そしてC + GLibでは上のC++のSTLで書いたコードを再現出来ない。もちろん、同じ結果を返すコードを書けない、って言ってるわけじゃない。しかし、Pythonでの関数型プログラミングのコードの構造はC++のSTLには持ってこれるが、C + GLibには持ってこれない、んだよ。何故ならGLibにはreduceがねぇからだ。そしてC言語にはラムダ式がない
そう、C++のSTLにはGLibには備わってないマッピング機能があり、reduceがあり、ラムダ式まであるんだ。ラムダ式がある、って事はGLibみたいにCallbacksと名付けられた関数ポインタ群のお世話にならんでエエ。
だから言ったろ?C + GLibをやるより、フツーに考えればC++のSTLを使った方が色々と簡単なんだ。圧倒的に苦しまなくて済む。

平たく言うと、STLとはまずは、GLibでも見た単方向連結リスト、双方向連結リスト、配列等の抽象データ型を備えている。この装備を考えてみても、C++はCよりOSを書くには向かないかもしれないが、一方、Pythonみたいな「フツーの言語に近い」と言う事が分かるハズだ。
そしてもう一つ備えてるのが言っちゃえば高階関数群。しかもGLibだと「定義されてるデータ型毎に特化した関数」が用意されてる程度なんだけど、STLのはSTLで定義されてるデータ型相手に、基本的にはたった一つの関数で対応出来る。

C言語、っつーか静的型付け言語の場合、データ型によって適用出来る関数が原則的に厳密に決まってる為、結果「なんらかの抽象データ型を作った」場合、それに特化した関数しか作れない。それがGLibに✗✗専用foreachがたくさんある理由なんだけど、一方C++は静的型付け言語にも関わらず、その辺を解決してるのが「ジェネリックプログラミング」と言うシステムなんだ。言っちゃえば「型」そのものも引数化しちゃって、そいつをソースコード上で使う際に「どの型なのか」指定する。そうすれば、静的型付け言語でありながら柔軟性が上昇する・・・結果、「何個もデータ毎にforeachを用意しなくても良くなる」わけ。
そしてC++では、その「ジェネリックプログラミング」をする際に使う機能を「テンプレート」と呼ぶ。結果、STLはその「テンプレートを利用した」標準ジェネリックプログラミング用ライブラリ、ってわけだ。
まぁ、型に付いては本音を言うと、「そんな面倒くさいシステムを作るくらいなら、最初から動的型付け言語を使えよ」とか思っちゃうんだが(笑)、それでも「関数の表現力」としてはフツーの静的型付け言語のブツに比べると圧倒的に自由度が高い。上でも見たが、STLにはreduce(に対応する関数)があるが、GLibにはない。GLibにない理由は、そもそも「返り値の型を決定しない関数は静的型付け言語では書けない」限界があるからで、「どんな型が返るか分からない」汎用的な関数reduceを設定出来ないから、だ(※8)。言い換えると、C++はそのテの問題を「ジェネリックプログラミング」で解決してる。
結果、STLでは「関数型プログラミング」が出来る。要は、「C言語そのものを知らん」でも、Lispプログラミング等を知っていればリファレンスマニュアルのサンプルを見ながら「見様見真似で」プログラミング出来ちまうんだよ。
こういう事を書くと「キチンとC++を深いトコまで理解して・・・」とか苦言を言うヤツが絶対現れるんだけど、関係ない。プロダクションコードを書かなあかん、ってならいざ知らず、「遊びでプログラミングする」なら別にC++の全体像を把握する必要もないし、あくまで「STLを使う」って事に限ってその機能を称賛してる、んだ。
また、「遊びで書けない」、あるいは「リファレンスマニュアルのサンプルを使って見様見真似で」コードを書けないようなプログラミング言語は「良い言語」じゃない。逆説的に、「C++の全体像を知らんでも」リファレンスマニュアルを見ながらコードをでっち上げられる、ってのがC++が良い言語、の証明ってことになる。これはC言語じゃあり得ない「柔軟性」だと言える。
結果、C++は「呼び水」を備えてる。「なんとなく洒落で使える」うちに、人はそのファンになり得るんだ。
いずれにせよ、皮肉にも、スティーヴ・イエギが言った

だから私がC++について言ったことが気に入らないなら、もっといい言語のエキスパートになることだ(私はLispをおすすめする)。そうすればあなたは私に反論する準備ができたことになる。しかしあなたはそうしないだろう。私はあなたを引っかけたのだ。そのときには、あなたはもうC++のことが好きではなくなっている。そして私が引っ かけて元好きだった言語を嫌いにさせたことに腹を立てるかもしれない。だからあなたはたぶん私が今言ったことは単に忘れてしまった方がいいのだ。

この部分は的を射てるが、同時に、「Lispを学んだ」事によりSTLの優秀さが際立ってる、って事が分かり、結果「C++が好きになってしまう」ってのは十二分にあり得るんだ(笑)。

さて、STLの高階関数の使い方の典型例をザックリと説明しよう。
件のコードだと、ここがSTLの高階関数を使用してる部分だ。

auto result = std::accumulate(B.begin(), B.end(), std::make_tuple(A, 0LL), foo);

accumulateと言うのがSTLで用意されてるreduceだ。
reduceに関してはこのブログでは、読んだ人が耳にタコが出来る程説明してるんで、ここでは詳細を省くが、いずれにせよ、単純にはリストを引数に取り、それに対して走査していくわけだが、STLにはそのリストを取る「方法」に特徴がある。
STLにはリストを含むコンテナ、と言う概念があって、そのコンテナがたくさんあるわけだが、引数にそれらを直接指定する事は出来ない。
代わりと言っちゃ何だが、その走査対象コンテナの始点(beginメソッド/メンバ関数)と終点(endメソッド/メンバ関数)を指定するようになってる。
これは個人的には最初見た時「嫌だな」と思ったもんだが(笑)、件のコード例で見ても分かると思うが、始点に+1したり、終点に-1したりすることも可能なんで実用上は問題ない。
なお、RacketのmapとかPythonのmapとかにあたるマッピング関数はどうなのか、と思うトコなんだけど、STLでmapを検索すると、連想配列の事になっちまうんだ(※9)。
単純にはSTLのマッピング関数はtransformになってて、この辺名前が「思ってもみなかった」ブツになってたりするんで気をつけよう。
例えばtransformの例示になってる次の例、



ってのはRacketで言うとこういうカンジだ。

(let ((v '(3 1 4)))
 (let ((result (map (lambda (x)
         (number->string (* x 2))) v)))
  (for-each (lambda (s)
       (displayln s)) result)))

Pythonだとこんなカンジだろうか。

#!/usr/bin/env python3

if __name__ == '__main__':
 v = [3, 1, 4]
 result = map(lambda x: str(x * 2), v)
 [print(s) for s in result]

圧倒的にRacketやPythonで書くコードの方が短い。
短いがC++のコードの意味は「追える」範疇だろう。
一方、STLのtransformはLispやPythonのmapと違って「返り値を目的とした」処理じゃない。別のコンテナ(この場合はresult)を作ってそれを破壊的変更をして結果を閉じ込める・・・それを行ってるのがback_inserterだ。
個人的には「破壊的変更」と言うのがなんともC臭くてアレだが(笑)、それでも「使える」のは間違いない。
少なくともGLibにはmapが無い。STLではmapreduceがあるだけ性能的にはGLibを遥かに上回ってるんだ。
そして、もっとも嬉しいのが、transformにコールバック関数として与えられているラムダ式だ。C++のラムダ式の書式はこうなっている。

[キャプチャリスト](パラメータリスト)  { 関数の本体 }

細かいトコはリファレンスを参照してもらいたいが、基本的にはこの形式、っつーかもっと小ちゃく

[](パラメータリスト)  { 関数の本体 }

でいい。
また、関数本体が{}で囲まれてる、と言う事は場合によってはこの部分は逐次処理を詰め込める、と言う事だ・・・結果、Pythonのラムダ式より遥かに強力だと言う事になる。
いずれにせよ、ラムダ式があるおかげでSTLの表現力は完全にC + GLibを凌駕している。GLibのように、Callbacksを探して適する関数ポインタを・・・なんつー苦労をする必要がない。
ラムダ式が使えると使えない、じゃ大違いなんだ。結果としてGLibのプログラミングの自由度なんざC++のSTLに及ばない。

上でも書いたけど、元々C++を使った理由は「教えて!goo」の回答を書く際に「あれ、C++で書いてみようか」と何となく気の迷いを起こし(笑)、コードが書けちゃったトコにある。しかし、僕はC++入門なる本やらサイトをいまだ一回も読んだことがないんだ。それでも書けちゃった、ってのがビックリなわけ。
あれから何度か洒落でC++のコードを書いた事がある程度、だ。でも、明らかにLispの知識だけ、でSTLは使える
しかし一方、最初の方にも書いたけど、あらゆるハッカーがC++を嫌っている。理由は良く分からんのだが、個人的にはずーっと「ハッカーが嫌っている以上、C++とは距離を置こう」って思ってて、C++に関して何か発言する、って事は避けてた。プログラマって同調圧力も凄いからな。ちょっと理系としては信じられない習性を備えてるんで、あまりその辺関わりたくなかったんだ。そんなんで「STLは使える」と思いながらC++に付いての明言は避けよう、とか思ってたわけ。
ところが、GLibの記事を書いてる際にどんどん違和感が大きくなってしまった。「アレ、これC++のSTLの方が遥かに使いやすくない?」と。それで今回、競技プログラミングの記事に関連して確信してしまった。C++は良い言語だ、と。
多分ここまで読んでくれた人はちと笑いながら疑問を呈するかもしんない。「Lispみたいに書けるからC++って良い言語、って根拠なの?」と。それに対してはこう答えておく。「"Lispみたいに書ける"以上に良い言語だ、と言うような客観的な根拠は存在しない」と。

なお、残念ながら「良いC++入門」って言える書籍は知らないんだ。人の口にのぼらない。
一番挙げられる書籍としてはC++の作者であるビャーネ・ストロヴストルップ(※10)自身が書いた次の本があるくらい、だろう。

 
当然個人的には全く読んだ事がないんでなんとも言えない。
ただ、C++の入門書ってのは多分、「オブジェクト指向版C言語」を説明する本が殆どで、STLに付いての解説書ってのはほぼ無いんじゃないか。扱っててもオマケ、のポジションだとか。
それじゃダメなんだよ。
上にも書いたけど、事実上、C++は2つの全く別の言語の混成体だ、って見た方がいい。つまり、STL及びテンプレートによるプログラミング入門、ってのが別に必要になるだろう。
しかし、幸いながらネット上では日本語・英語に関わらず「STL入門」を掲げているWebページが多い。これもGLib入門が日本語・英語に関わらずほぼ無い、と言うのとは大違いだ。
また、繰り返すが、C++リファレンスマニュアルのデキも大変良い。用例も豊富で、用例が全くなく、定義しか書かれてないGLibリファレンスマニュアルとは大違いだ。これだけ用例がしっかり書かれてるリファレンスマニュアルを備えてるだけ、でもC++は大変恵まれた環境を提供している。(Gaucheを除く)Scheme実装のリファレンスマニュアルの執筆者共に爪の垢を煎じて飲ませたいくらいだ。
あと、意外と、マイクロソフトのC++関連のドキュメントのデキが良い可能性がある。WindowsでVisual C++を利用する、と言う前提なら、まずはマイクロソフトのドキュメントでC++のプログラミング法を学ぶ、と言うのはかなり良い方策かもしんない(※11)。

いずれにせよ、STLがある限りC++は良い言語だ(※12)。これからはそういうスタンスで行こうと思ってる。
CはクソでもC++はそうじゃない(※13)。

※1: 繰り返すが、こんな馬鹿な妄言は1990年代前半までは存在しなかった。少なくとも、多くの大学で「1、2年次はPascal」、「3、4年次はC言語」を学び、今みたいに「C言語しか知らない」卒業生を作る、なんつー事は無かったんだ。昔の学生は最低でもバイリンガルだったんで、こんな馬鹿な事は言わなかったんだ。
Cが初級向けに下がってきたのはアメリカの大学の影響なんだろうけど、そもそもアメリカの大学ってのは日本で言うと「職業訓練校」のニュアンスが殆ど全て、なんだ。そして公立・私立を問わず、経営には寄付金が占める割合が高い。結果として起きたのは、90年代中頃の「C言語を使いこなせる人材がもっとたくさん欲しい」と言う「教育効果を無視した」スポンサーの要求だったんだ。結果、「教育効果を考えない」入門用言語がスポンサーの要求で二転三転する。「業界でJavaが使われる!」となれば「入門用言語にJavaを使え!」とかな(笑)。繰り返すけど、スポンサーは別に「教育効果」とか考えてないんだ(笑)。
そんな中で、マサチューセッツ工科大学なんかは、そのテのスポンサー側の要求を跳ね除けて、2000年代でも入門用言語としてSchemeを使い続ける、とか、「一般動向をまるで無視する」孤高の道を選択したに等しい。よっぽど「教育内容」に自信があった、って事だろう。世界最高の工科大学の名は伊達じゃないんだ。結果、多くのハッカーを生んでいる。果たして「教育効果」が本当にデカいのはCなのか、それともLispなのか。
なお、日本で有名なのは往年の慶應義塾大学で、そこではなんと、プログラミング言語はLispとアセンブリ言語の2つしか教えなかった、と言う逸話がある(笑)。「もっとも抽象度が高いプログラミング言語ともっとも抽象度の低いプログラミング言語の2つさえ知れば、間にあるヤツはどーにでもなるでしょ?」だそうだ(笑)。
そうだよな、「応用性がある事を教える」のが教育なら、教育とはそうあるべき、なんだよ。

※2: これは直感的な勘違いで良くあるケースだ。C言語でコンパイラ型言語処理系を実装し、「速くコンパイルする」コンパイラを書ける事は事実だが、吐き出す実行形式(と言うかアセンブリ言語でのソースコード)が速いか否か、ってのは「C言語を使った事」とはまるで関係がない。言っちゃえば「クッソ遅い」プログラミング言語で「速い実行形式」を生成するのは可能だ。

※3: しかし実際は、WindowsはC++で書かれている。

※4: Objective-Cの方は現行のMac OS Xで使われている言語だ。
なお、Mac OS XはMac OS 9までのMac OSとはまるで別物で、オリジンはスティーヴ・ジョブスの作ったNeXTと言うワークステーション用OSがルーツで、これもUNIX互換機だった。
その、NeXT用OSの開発言語になったのがObjective-Cだ。
ちなみに、Objective-Cは触ったカンジ、こっちはこっちでかなり厄介で、Smalltalkと同様に環境(ランタイム)と切り離せないような構造になってるっぽい。
「軽く触る」には向かない言語だと思う。

※5: 一番簡単にSmalltalkを試せるのがSqueakだが、「これってプログラミング言語なの?」ってビックリするだろう事請け合いだ。まるで仮想環境で「別のOSを起動している」ように見えるだろう。しかしその全部(開発環境を含めて)が「Smalltalkと言う言語の一部」なんだ。



結果、「Smalltalkでのプログラム」はSmalltalkの外へは持ち出せない(あるいは持ち出しづらい)。上にも書いたが、Objective-Cはそういう影響を受けている。

※6: 一方、Objective-Cには「標準言語仕様はない」。事実上Appleの為のAppleローカル言語だ。

※7: 厳密に言うと、もちろん、プログラムのエントリポイントはmain関数になってて、その返り値はint、スコープは{}で記述してプログラムが正常終了した場合は0を返す、って程度の「C言語のお約束」は既知の事実として、って事ではあるが。
しかしそれ以外は、includeするヘッダも違うし、入出力の記述も変わるし、とどっちにせよ殆どの部分は「C言語と同じではない」のがC++の現実でもある。

※8: void*型を返り値にする、ってやり方もありそうだが、「そういうユーティリティを用意していない」って事は多分技術的に色々とメンドくせぇんだろ(笑)。

※9: この辺、コンピュータ関連では、「同名異義」な単語が多くて辟易する。
ちなみに、これも本来ならもとこんぐさんの領域だが、一説によると、英語の総単語数は日本語のそれに比べると遥かに小さい、と言う話があって、結果、「何らかを説明する」単語を作ろうとすると、コンピュータサイエンス的に言うとコンフリクト、要は名前の衝突が頻繁に起こるらしい。
いや、逆に言うと日本語のコーパスがデカすぎる、って捉える事も出来て、日本語は大昔に中国語の漢語を貪欲に取り込み、現代でも英語、ドイツ語、フランス語等から気になった単語を受け入れ、日本語化し、更に独特のニュアンスを付け加える、と言った、MITのキッチンシンクアプローチもビックリ、ってとんでもない事をやってのけている。
言い換えると、積極的に外来語を取り入れる事が無い英語のコーパスが日本語に比べると小さい、ってのは当然なんだ。日本語だとmapと地図と数学で言う一次変換は全く違うニュアンスを持ってるが、英語は必ずしもそうではなく、全部mapで表す、と言うのはしょーがない背景がある。

※10: 舌を噛みそうな名前だが(笑)、要は元々英語圏の人ではなく、実はデンマークの人だ。
なお、オブジェクト指向の祖、Simulaと言う言語そのものがノルウェー製で、同じ北欧で元々「オブジェクト指向のアイディア」と言うのが大学間で広まってたんだろう。
このように、「プログラミング言語」は結構な割合でヨーロッパの影響が大きい。C言語の元となったB言語のそのまた親にあたるBCPLもイギリス・ケンブリッジ大学生まれの言語で、結果C言語もヨーロッパの血が入っている。
かつてC言語と人気を二分したPascalもヨーロッパ製(スイス生まれ)だし、Pythonもそうだ(オランダ生まれ)。
このように、プログラミング言語は、結構ヨーロッパの影響がデカいんだ。

※11: 事実上、C++はマイクロソフトベッタリのように「見える」のがハッカーの不興を買ってる可能性は高い。反面、根拠が薄いのにAppleが選んだObjective-Cなんかは持ち上げるんだよなぁ(笑)。
つまり、ぶっちゃけて言うと、これは「言語の性能の話」じゃなくってイデオロギーの話なんだ。マイクロソフトは「悪」だからC++は悪なんだけど、Appleは「善」だからObjective-Cは善だ、と(笑)。本当にそうか(笑)?
実際問題、歴史的に鑑みると、Appleの作った、あるいは推奨するような「プログラミング言語」なんざ失敗続きなんで、マトモな感覚だったら「選んじゃいけない」んだ。つまり、歴史的観点でもObjective-Cなんかを「良い」と評価する、なんつーのはマトモな判断力があったら「出来ない」ハズだ。
結果、なんか「言語の性能」と全く関係ないバイアスが論を形成してんだろ、と思わざるを得ない。
なお、CとC++は「一緒くた」として扱われやすいが、ユーザーを見ると「この2つは一緒にしちゃいけない」。何度も書いてるが「C言語を使ってる」ユーザーは、日本ではいまだANSI Cユーザーばっかで、「標準を知らない」いわばニセC言語使いばっかだ。
一方、C++ユーザーは「標準仕様を追っかける」。現行でもコンパイラの実装進捗にも拠るだろうが、最低でもC++17やC++20を理解してるユーザーの方が多いだろう。と言うのもマイクロソフトが標準仕様に準じたC++コンパイラへと常にアップデートしてるお陰だと言える。
いずれにせよ、マイクロソフトのお陰で、C++ユーザーのメンタリティは「自称」Cユーザーとは大違い、なんだ。

※12: 加えると、C++にはBoostと呼ばれるテンプレートの外部拡張ライブラリがあって、これも有名だ。そして「外部ライブラリ無しの極端にDIYな」C言語と違って、C++ユーザーは積極的にBoostと言う外部ライブラリを利用しているらしい。

 
※13: ちなみに、人生で唯一「プログラミング言語処理系を買った」のがなんとC/C++だった。1990年代前半だったが、Commodore Amiga用にSAS C/C++と言う商品を買ったのが唯一の経験だ。

そうそう、こんなカンジでデカいマニュアル二冊とフロッピーディスク数枚、と言った構成だった。

いや、当時、別に「プログラミングをやりたい!」とか思ってたわけじゃなくって、たまたま東京書籍から当時流行ってた「カオス理論」で作るグラフィックプログラミング集的な本が出てたんだよ。
本屋で立ち読みしてたんだけど、前書きには「C言語は移植性に優れた言語で・・・」とか良くあるフレーズが書いていたわけ(笑)。んで別に「グラフィックをプログラムする」くらいなら工夫も必要ないし、やってみっか、ってんでその本買ってみたのね。PC-9801用のTurbo C前提で書かれてたのに(笑)。そしてその時はTurbo Cが何指してるのか知らんかったんだよ(笑)。大体、教科書出版社から出した一般本なんだけど、™(トレードマーク)とか打ってなかったわけ。フツー、「商品名を記述する際」には通例で入ってんだけど、教科書出版社だからそういう「一般慣習」を知らんかったんとちゃうん?
そういうわけでAmiga用にSAS C/C++買ったはいいんだけど、プログラムを書いても当然動かない(笑)。「どこが移植性に優れてるねん!」とか言って激怒した、ってわけ(笑)。その時からC言語嫌いなんだよ(笑)。無駄金払わせやがって、みてぇな(笑)。そしてその時から「Cは移植性に優れて・・・」と言う文言は全く信用してない(笑)。 

注: 実際はCの「標準」の部分じゃなくってマシンに依存したグラフィックライブラリのせいだったんだけどな(笑)。でも当時は「知るかそんなの!」で、不幸な事にTurbo Cでもgraphic.hとか言うライブラリが追加されていて、Amiga用SAS C/C++でもそういうライブラリ名だったんだ。

いずれにせよ、多分もうANSI CあるいはISOのC90が制定された後の商品なんだけど、この時点では、なんだろ、C++ってCの拡張パッケージ扱いだったんだよな。「付録で付いてます!」みてぇな(笑)。そしてこの時点ではC++って「Cに比べて尖った拡張」ってニュアンスだったの。オブジェクト指向、なんつーのも良く分からんブツだったしな。
で、この後Javaが出るんだよ。1996年か。ある意味タイミング的にはWindows 95の登場とほぼ同じ時なの。この辺でMicrosoftのVisual C++が開発言語になってて、Windowsのアプリケーションもそれで書く、とか言う話になってきたんだけど、生憎この時点ではC++はまだ国際標準化してないんだ。だからC++と言うCに替わる尖った言語があるらしい -> Windows 95登場 -> アプリケーション作成はJavaで、的な流れがちと見えた後にC++の国際標準化がなされる、的なカンジだったのね。
個人的にはSAS C/C++では「オマケ扱い」だったわけだから(笑)、あ、そっかー、国際標準化したか〜、ちっちゃかったあの子も大きくなって〜、的なヘンな感慨はあるんだよな(笑)。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最近の「プログラミング」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事