Objective-C 供養

szktty

SUZUKI Tetsuya

Posted on January 23, 2020

Objective-C 供養

※この記事は 2015年12月24日 に Qiita に投稿したものです。

世間はクリスマスモードだと言うのに、辛気臭いタイトルですみません。「勝手に殺すな」とか「お前は何様だ」などとなんだか怒られそうです。「喪失感で胸がいっぱい」だとか「 Objective-C はまだまだ使える言語です!」だとか、そういう感傷もありませんし、主張もしません。「いい言語だと思うし好きだけど、結局 Mac OS X や iOS のアプリケーション開発以外に活用(しようとトライしたけど)できないまま Swift が発表されたなー」と思っていて、なぜ活用しにくかったのかを整理してみようと考えました。ですので、「 Objective-C 栄光の歴史」を語ることはありません。体験してないし。知らないし。

それから、ここでは言語としての Objective-C を扱います。アップルのフレームワークや iOS アプリケーションの開発ツールの一部としての話ではないので、これを読んでも iOS アプリケーション開発の手助けにならないと思います。

バッドノウハウの終焉

Objective-C 2.0 以前

Objective-C 2.0 以前は、アップルのフレームワークを使ってプログラムを書くのに守るべき作法(イディオム)がありました。いくつか挙げてみましょう。

  • オブジェクトの生成: alloc -> init の連続したメッセージを送信する。
  • オブジェクトの初期化: init メソッドを実装し、その中で super に対して init メッセージを送信する。
  • メモリ管理: retain/release でカウントを増減させる。
  • オブジェクトの解放: dealloc メソッドを実装し、インスタンス変数に release メッセージを送信後、 super に dealloc メッセージを送信する。
  • インスタンス変数へのアクセス: getter/setter を実装する。
  • コレクション要素のイテレーション: Enumerator オブジェクトを介して行う。

これらの作法は、文法や言語仕様ではわかりません。ドキュメントを読む必要があります。べつだん不思議なことではなく、どんなライブラリにも順序立てて行わなければならない処理はあります。

アップルのフレームワークを除くと Objective-C の仕様は極めてシンプルで、ルートクラスの Object とその他一つか二つのクラスと、メッセージ送信機構程度です。アップルのフレームワークではこのルートクラス Object は使われておらず、オブジェクトの生成、解放処理からして同フレームワークで実装されています。それくらい素っ気ない代物ですから、同フレームワークを使うためには、まず上記の作法を知ることから始まります。

「 Objective-C はシンプルな言語です」との説明は間違っていないと思いますが、じゃあ iOS アプリケーションの開発を即座に始められるのかと言うと、大抵の人は難しいでしょう。(アップルのフレームワークである) Cocoa は「 NeXTSTEP から受け継いだ洗練されたフレームワークだ」とも称賛される反面で、必然的に上記のような作法を生みました。確かに作法を守るととても楽に開発が進むのですが、私は今となってはこれらの作法はバッドノウハウだと思います(これを広げちゃうと、ライブラリはすべてバッドノウハウになってしまいますけどね)。フレームワークの出来が悪いという意味ではありませんよ?

Reconstruction, not evolution

アップルは Mac OS 10.5 で、 Objective-C を 2.0 と呼ぶバージョンアップを行いました。それまでは Objective-C にろくにバージョンナンバーを付けてなかったのに 2.0 ブームに乗った節操のない会社ですが、その変更内容は進化というより、これまでのバッドノウハウの取り込みです。新しい仕様は GC くらいです。しかも iOS では使えないという中途半端な機能です。

Fast Enumeration は進化に見えなくもなさそうですけど、イテレーションのイディオムの最適化って進化に含めていいんでしょうか。それに、 NeXT もアップルもコンパイラを握ってきたベンダーです。 WebObjects という高価な商用製品もありましたし、高速にコレクション要素を列挙する必要性を痛感する機会も、導入する機会もいくらでもあったはずです。プロパティも Key-Value Coding という Foundation フレームワークの機構を利用した、インスタンス変数管理のノウハウの仕様化+αです。これらの変更は「 2007 年になるまで行われなかった」とも言えるのかもしれません。

プロパティと Fast Enumeration の導入で、 Objective-C のコードの見た目は少し変わりました。プロパティは getter/setter へのメッセージ送信をドット記法で代替でき、 Fast Enumeration は「イテレーター取得 -> while で回す」処理を文法として組み込みました。どちらもアップルのフレームワークの作法から発展した仕様であり、 Mac OS X/iOS アプリケーションの開発に特化した仕様変更だと言えると思います(ただし、この仕様はアップルのフレームワークから独立しています。任意のライブラリで利用可能です)。まあ、そもそもが自社製品以外の Objective-C コンパイラベンダーなんて気にかける必要がありませんし(そもそもない)、だいたい世界で一番 Objective-C を使っているのはこの会社です。

これらの仕様変更によって、 Smalltalk に由来するメッセージ送信メタファーがやや崩れました。それは当然で、一部のメッセージ送信を簡略化した文法にしたのが 2.0 ですから。しかし「崩れた」とか「逸脱した」とかいう表現は外部者の勝手な失望であって、アップルは「(一部の仕様において)メッセージ送信メタファーを『切り捨てた』=不要だと判断した」が実際です。ただ、だからといって Objective-C の空気ががらりと変わったということもなく、それだけを見れば些細な変更です。

Reconstruction, not evolution (again)

"Objective-C without C" と聞いて、「十年遅いんだよ」と思ったのは私だけでしょうか。まったく、自画自賛もいいとこです。こんにちは Swift です。

私は Objective-C を知って「これはいい言語だな」と思ったんですけど、その一方で「 Cocoa があればほとんど C に手を付けずに済むんだし、 Objective-C は捨てて、Mac OS X/iOS 専用でいいからネイティブコンパイルしてくれて高速に動くスクリプト言語を作ってくれればいいのに」とずっと思っていました(高速は無理でも Cocoa と親和性の高い "Objective-C without C" なスクリプト言語を作ろうとしたことはあります)。皮肉なことに、 Objective-C で実装されたライブラリが洗練されればされるほど、 Objective-C である必要性が薄れるらしいです。

さて、 Swift の特徴と言えばこんなところでしょうか。まあ Objective-C 互換にかなり引きずられてしまっている感はありますが、そこは膨大な資産を活用しなければならないので仕方がない面もあるのでしょう。

  • C の排除
  • 強い静的型付けと型推論
  • C/Objective-C の資産にアクセスできる
  • メモリ管理の自動化( GC ではない)
  • クロージャー

やはり最も大きな特徴は "Objective-C without C" との煽り文句の通り、 C を排除したことです。「これで(ゼロにはならないけど) C を書かなくて済む」ようになりました。でも、そういういかにもアクティブな姿勢に見せかけても、実際は「すでに C を書く必要がなくなっていた」のではないかと思います。 Mac OS X/iOS アプリケーションの API は C であっても C のスタイルとは似ても似つかないようなオブジェクト指向のライブラリで、大抵のアプリケーションは Mac OS X/iOS フレームワークの API で完結できる(外部の C ライブラリと連携する必要がない)と思います。もちろん高いパフォーマンスが要求されたり、 C のみで実装されたライブラリを使わざるを得ないならば C や C++ で実装しなければならない処理はあるでしょうけど、アプリケーション開発に関わるチームメンバー全員が Mac OS X/iOS フレームワークを一切使わない C のスペシャリストである必要はないでしょう。 C を使う理由が「 Objective-C より速い」なら尚更、 C に代わって Objective-C より速いネイティブコードを吐く言語があればいい話です。「だからそれが Swift だろ」と言われればその通りなんですが、でもそんなの今更気が付くことでもないだろ?と思います。もちろん、アップルにそこを解決するだけの技術力がなかったと言うのであれば無理な相談です。

もう一つの大きな特徴は、強い静的型付けと型推論です(型推論があってもかなり面倒そうですけど)。ああ、あとクロージャーですか。クロージャーについては後述します。

Objective-C の静的型付けはあまり強くありません。どんなオブジェクトでも、任意のオブジェクト型を示す id 型へのキャストが可能で、宣言された型はせいぜい目安にしかなりません。総称型もないので、コレクションの要素の型がわかりません。 nil に対してメッセージを送ってもエラーにならず、その処理が無視されます(コンパイラオプションでエラーにできることはできます)。まあ nil に関しては、これを利用してコード量を短縮するスタイルが主流でしたので、ダメだったと言い切れない面もあります。ありますが、他の言語で nil チェックに慣れた人にすれば余計な仕様でしょう。その声に応えたのか、 Swift では nil の可能性のある型をオプショナル型として、 nil の可能性のない型と区別します(ただ、オプショナル型の値に "nil" という名前を使ったことと、オプショナル型に関する演算子の多さは、「奥が深い症候群」を発症させる原因に見えなくもないです。事を面倒にしただけだと思います)。

一つ、どうでもいい疑問があります。 "Objective-C without C" ならば、シンプルに Objective-C の延長線上にある言語にしてもよかったのではないかと思います。開発コストも学習コストも下げられますし。この形になったのは、今後の開発を見据えてとか関数型言語やら型推論付きの強い型付けやらの流行に乗ってなどいくつも理由があるでしょうけど、ぶっちゃけ世間がオブジェクト指向言語に飽きたからなんじゃないかなと思わなくもないです。

なぜ Objective な C だったのか

Evolution, not revolution

Objective-C の登場は 1983 年、 Stepstone 社を設立した Brad J. Cox と Tom Love が開発しました。同社は Objective-C のコンパイラとライブラリを販売し、 1995 年に Objective-C に関するすべての権利を NeXT に売却します(売却後も NeXT からライセンスを得て、自社製品の販売は続けていたようです)。

当時はソフトウェア危機だとか何とかでオブジェクト指向プログラミングが登場し、 Cox はそれに注目しました。 Cox はオブジェクト指向プログラミングを "revolution" と言っています。しかし Cox は "revolution" の方法でソフトウェア開発上の問題を解決するよりも、既存の言語にオブジェクト指向プログラミングの手を加える「ハイブリッドな」方法に注目します。それなら既存の言語の力を維持しつつ、オブジェクト指向プログラミングも活用できると考えます。 Cox はこれを "evolution, not revolution" と言い表しています。

Cox 本では、次のオブジェクト指向プログラミング言語を比較しています。 Smalltalk-80, Ada, C++ です。 C++ に関しては、 C++ が C の言語仕様を拡張しているのに対し、 Objective-C は C を完全に残しつつ、遅延束縛を行うオブジェクト指向プログラミングを可能にしている、と冷静に比較しています。 Cox はハイブリッドな言語を考えていたので、言語仕様の拡張は方向性が異なりました。

至高の Smalltalk

Smalltalk-80, Ada, C++. これらの言語の中で、 Cox は特に Smalltalk-80 に注目します。 Smalltalk は個人の創造性を発揮させ、プログラマにとって最高のツールであり、ソフトウェア問題に対する最高の解決策だと考えたようです。ですが Smalltalk の選択には問題があると考えました。 Objecive-C の開発時、 Smalltalk は研究用にしか使われてなかった?ようで(商用の Smalltalk-80 の発売年は Objective-C と同じ)、 Smalltalk-80 の環境が Smalltalk の世界で閉じていることが問題だと考えました。

Smalltalk を使うとすれば、すでに他の言語で構築されているシステムとどう連携するのか? Cox の関心は、組織的なコンピューティングと個人的のコンピューティングを、プログラマの負担を最小にするブリッジでつなぐことにあり、最終的に Smalltalk の遅延束縛と C の早期束縛のハイブリッドを選択します。 C を選んだ理由は、 C なら低レベルな処理をカバーできることと、 C が普及し始めていたからとのことです。

こうして Cox らは C にクラス機構とメッセージ送信機構を追加した Objective-C を開発し、 Stepstone 社を設立してコンパイラ(というか C 言語へのトランスレーター)とライブラリの販売を始めます。ライブラリは Smalltalk のクラスライブラリが参考にされており、また、 Smalltalk のシステムブラウザを真似た Objective-C ブラウザも後々開発したようです。

導入されなかった「ブロック」

Smalltalk には、遅延束縛を支える要素の一つでもある「ブロック」があります。ブロックは Swift などでクロージャーと呼ばれているオブジェクトです(厳密に言うと Smalltalk-80 のブロックはクロージャーではないんですが、話が面倒になるので近いものだと思ってください)。 Cox はブロックの強力さを認めつつも採用しませんでした。 Cox は、 C のようにハードウェアスタックを前提とする言語では実装が難しいと判断したようです。「ごめんね、メッセージ送信式の文法に Smalltalk のブロックと同じ大括弧 [] を使っちゃったからできなかったの。てへ☆」みたいな文法上の理由ではありません。ただし、制限つきなら実装できなくもないと言っており、開発上の課題に挙げたものの、結局は実装されませんでした。

アップルは同様の機能を Mac OS X 10.6 で実装しましたが、メモリ管理が難しく、残念ながら使いやすいとは言えません。文法も C の関数ポインタを引きずっており、見た目が大変ややこしいです。 Swift で実装されたクロージャーは多少ましな文法になったものの、メモリ管理の面倒さはゼロにならないみたいですね。 GC と型推論なしではとても使っていられないのではないでしょうか。

Stepstone Objective-C

商用ライブラリ ICpak シリーズ

先に断っておきますと、今日に至るまで Objective-C の標準規格はありません。現在のアップルのコンパイラの実装はオープンソースとして公開されていても、それはオープンソースコミュニティ先導で Objective-C の開発が進んできたことを意味しません。 Objective-C の仕様は C にメッセージ送信機構といくばくかの文法を追加した程度で、ルートクラスも難なく用意できます。そのため、 Stepstone と NeXT の Objective-C の共通点は多くありません。ルートクラス Object は共通でも、まったく同じ内容ではありません。 NeXT の Objective-C を継承した現在のアップルの Objective-C の仕様には、 Objective-C という名前以外に Stepstone の跡形は見えないような気がします。

Stepstone は ICpak シリーズという商用ライブラリを販売していました。基礎的なクラスライブラリ (foundation) 、 GUI 、グラフ?の三つです。 Objective-C の将来性以上に誰も興味がないとは思いますが、このうちの Foundation ライブラリのクラス階層を挙げておきます。

Object
     Array
          IdArray
          IntArray
     Ctrn // Collection
          OrdCtrn // OrderedCollection
          Stack
          Set
              Dictionary
     BalNode // 二分木
         SortCtrn
     String
     Point
     Rectangle
     Assoc
     IPSequence // イテレーター
         Sequence

Array や Ctrn のクラス階層、 Dictionary オブジェクトと関係する Assoc クラスなど、 Smalltalk を意識したライブラリだったようです。オープンソースの Objective-C コンパイラ Portable Object Compiler 付属のライブラリが ICpak 互換らしいです。 POC は NeXT による権利買収以降の 1997 年にリリースされたようです。

ところで、「 Stepstore のライブラリはバグだらけだった。だから NeXT はライブラリを捨てて Foundation フレームワークを作った」と言っている方もいます。嘘か真かわかりませんけど、 Stepstone のライブラリが超優秀だったというエピソードを見たこともないのでどうなんでしょう。ちなみに ICpak ライブラリはソースコードで提供されていたそうです。

NeXT はなぜ Stepstone ライブラリを真似なかったのか

Stepstone Objective-C は、商用ライブラリを除けば Object クラスしかありません。コンパイラは C へのトランスレーターで、コンパイラのみの購入だとなかなかの貧弱さです。 NeXT は自社で GCC をベースにして Objective-C コンパイラを開発したので、 Stepstone のコンパイラは使っていなかったと思います。

初期の NeXT の基礎ライブラリはごくごくシンプルです。

Object
    List
    Storage
    HashTable
        StreamTable

これだけです。 GUI アプリケーションの開発に必要なコレクションクラスのみです。文字列処理には C 文字列を使い、イテレーターはありません。 NeXT はなぜ Stepstone のライブラリを真似なかったのか? 単に「真似すんな」というライセンス契約があっただけなのかもしれませんが、必要なクラスのみに留め、 Smalltalk 風味のライブラリにはしませんでした。なぜでしょうか?

そこは現在も残る洗練されたツールキットを開発した人たちのことです。そこにはきっと深い理由が...いえ、なかったかもしれません。 NeXT の人たちは遅延束縛に柔軟な開発の可能性を見出し、 OS 開発という分野に欠かせない C と融合した Objective-C のアドバンテージに惹かれた(と思う)のであって、 Smalltalk に惹かれたわけじゃなさそうです。そこに自分にとって最善のツールがあると思ったら、いちいちそのルーツまでたどって参考にしようなんて思わないでしょう。そのルーツから派生した目の前にあるツールが最善なんですから。「 Objective-C すごい」と思った人のうち、何人が Squeak や VisualWorks を試してみたのか。「 Swift すごい」と新規参入した人のうち、何人が今後大きな発展を遂げる可能性のない Objective-C のみで iOS アプリケーションを実装しようとするのか。ルーツは所詮(その人たちにとって)過去の遺産です。

とまあ偉そうに言い切りましたが、統一されたクラスライブラリは必要ないというだけだったのかもしれません。 NeXT の Objective-C は NeXT コンピューターでのみ動作すればよかったのですから。

話は変わって、先に挙げた「 NeXT はバグだらけの Stepstone ライブラリの代わりに Foundation ライブラリを作った」は真だったのでしょうか? 私、主に後半が気になります。

現在の Foundation フレームワークの前身である Foundation Kit のリリースは 1994 年、 Core Data の前身である Enterprise Objects Framework (以下 EOF )のリリースと同時です。というか、 Foundation Kit は EOF の一部でした。この時点で NeXT はまだ Stepstone から Objective-C の版権を買い取っていません。買収は翌年の 1995 年です。

Foundation Kit にはルートクラス NSObject が含まれていますが、前述の通り Foundation Kit は EOF の一部で、まだ NeXTSTEP の EOF 以外のクラスのルートクラスではありませんでした。つまり、 Foundation Kit が登場した時点では、 Object と NSObject という二つのルートクラスが混在しています。

初期の Foundation Kit に含まれていたクラス階層は以下です。 Cocoa フレームワークを使ったことがある人なら見覚えがあるはずです。

NSObject
    NSArray
        NSMutableArray
    NSDictionary
        NSMutableDictionary
    NSData
        NSMutableData
    NSValue
        NSNumber
    NSString
        NSMutableString
    NSCharacterSet
        NSMutableCharacterSet
    NSAutoreleasePool
    NSAssertionHandler
    NSEnumerator
    NSException
    NSNotification
    NSNotificationCenter
    NSScanner
    NSBundle
    NSDate
        NSCalendarDate
    NSTimeZone
        NSTimeZoneDetail

以上は文字列、コレクション、参照カウントによるメモリ管理、通知機構、日付と時刻に関するクラスです。現在の Foundation のうちの一部が含まれています。 Core Data を使い込んでいる人なら、このリストを見て何かに気付くかもしれません。そう、どのクラスも EOF/Core Data に欠かせないのです。だから Foundation Kit が EOF の一部としてリリースされたわけです。たぶん。

ただし、以前から文字列処理には C 文字列を使ってましたし、前述したようにコレクションクラスも(数えるほどですが)すでにありました。それらのクラスが Foundation Kit で NSObject のサブクラスとして再実装された理由は、「参照カウントでのメモリ管理」と「オブジェクト <-> データベースレコード間の変換処理のため」が大きいのではないかと思います。

Foundation Kit の目的はまだあって、そのうちの一つがクロスプラットフォームのサポートです。 EOF のリリースの前年、 1993 年に NeXTSTEP 3.2 がリリースされてから、 NeXT は Sun と OPENSTEP の共同開発を始めます(この延長線上に WebObjects があります)。仮に NeXT が Stepstone のライブラリを使っていたとして、それがバグだらけだったとしても、 Foundation Kit の最もな開発理由は製品戦略でしょう。まあ前述の方は、 Foundation Kit の開発動機が Stepstone ライブラリのバグだと思うほど当時困ったのかもしれません。

Objective-C ブラウザ

Stepstone は後になって、 Smalltalk のシステムブラウザを真似たツールを Objective-C 用に作ったようです。しかし、どうも Smalltalk ほどシステムに直結したツールではなくて、クラスとメソッドをリスト表示し、選択してソースコードを編集するくらいのツールだったようです。それってテキストエディタで代用できる程度のたいして有用でもないツールじゃないの? と思わなくもなかったです。 NeXT の人たちも同じ感想だったのか、 NeXTSTEP に同様のツールはありません。

WebObjects: 捨てられた Objective-C

NeXT は 1996 年に商用 Web アプリケーションサーバ/フレームワーク WebObjects の販売を開始しました。 WebObjects は Web アプリケーションフレームワークと、 Core Data の前身である OR マッピングフレームワーク(前述の EOF )で構成されます。どちらも NeXTSTEP のライブラリを使って実装され、また Objective-C の遅延束縛を活用しています。まあ実質は Objective-C が活躍したというより、 NeXTSTEP の資産があったからこそなんだと思いますが。

WebObjects アプリケーションの開発ツールに、 WebScript という専用のスクリプト言語がありました。簡易的な Objective-C 風の文法、または Java 風の文法を持つ、動的な言語です。使える場面は Web 層に限られますが、 Objective-C を知らなくてもアプリケーションを開発できるツールです。 WebScript をサポートするバージョンのリリースが 1996 年。 Python のバージョンが 1.3 、 Ruby のバージョンが 1.0 の頃です( Perl は 5.0 )。実行速度は遅かったらしいです。

WebScript がどう実装されていたのかはわかりません。遅さに我慢できるなら、 Objective-C のメタプログラミング機構を使えば実装は比較的容易だったと思います。ここばかりは Objective-C の動的な性質が有利に働いたのではないかと思います。

NeXT を買収したアップルは、 WebObjects のランタイムを Java で再実装します。このときアップルは Java 流に設計し直すような悠長な真似はせずに、 NeXSTEP のフレームワークを丸ごと Java で実装し直すというマッチョな戦略を採りました。 Objective-C の遅延束縛を利用する API は、 Java のリフレクションを使って実装されています。よくやるよなあと感心しますが、 2000 年に 699 ドルに値下げされるまでは 5 万ドル=当時の日本円で約 700 万円で販売(※サポート料金込み)されていた製品です。それだけの価値があったのだろうと思います。それに Java でほぼ問題なく再実装&運用ができたのなら、マーケティング的な理由も含めて、もう Objective-C である必要も、 C である必要もなくなっていたのだと思います。今では WebObjects も似たようなものだと思いますが、それはまた別の話ですね。

唯一のコンパイラベンダーは何を捨ててきたのか

Smalltalk 風の( Cox らが考える)実務的な開発環境を目指して誕生した Objective-C は、 NeXT とアップル時代で逆方向の開発が続きます。

時期 出来事 捨てたもの
1983 年 Stepstone Objective-C リリース
1988 年 NeXT Computer 発表、独自に Objective-C コンパイラを開発する
1995 年 NeXT が Objective-C に関する権利を買収 Stepstone のライブラリ(と Objective-C ブラウザ?)
1997 年 Apple が NeXT を買収
2001 年 WebObjects が Java で再実装される Objective-C
2007 年 Objective-C 2.0 リリース クラスのポージング(すげ替え)、一部のメッセージ送信メタファー
2014 年 Swift 発表 C 、遅延束縛、メッセージ送信メタファー

この中で WebObjects は毛色が異なるカテゴリですが、 Objective-C で実装されていた商用製品が Objective-C を捨てたことは重要なポイントだと思います。 Java で再実装された WebObjects は今でも iTunes Store を支えており(いつ取って替えられてもおかしくないと思いますが)、 Objective-C を捨ててもたいした問題はなかったように見受けられます。 Java プログラマが使え、 GC にメモリ管理を一任でき、運用面では Java EE アプリケーションサーバの恩恵を受けられる分、メリットの方が大きかったかもしれません。 Java で再実装した理由が十中八九マーケティング上の都合だっただろうにせよ、アップルはすでに一度、大金を投じて Objective-C を捨てているのです。

NeXTSTEP で Smalltalk 風のクラスライブラリとブラウザが切り捨てられ、 Objective-C 2.0 でクラスのポージング(すげ替え)が切り捨てられ、 Swift によって C が切り離され、さらにクラスベースのオブジェクト指向プログラミングとメッセージ送信も切り捨てられつつあります。こうして見ると Objective-C がたどった歴史は「『 Smalltalk らしきもの(遅延束縛)』と『 C らしきもの(低レベルな処理)』が次々と切り捨てられた歴史」と言えなくもなさそうで、もしかすると Smalltalk が敬遠される理由もこのあたりにあるのかもしれません。では、 Swift という形で残ったものは何か? 高レベルな型付けによる早期束縛です。

こう書いてみると Objective-C と Smalltalk の歴史に感傷的になっているようですが、私はどちらもあまり使う機会がなかったので、特に思い出はありません。まあ、思い出があろうとなかろうと、よりよいツールがあったらさっさと乗り換える性格ですので、「世の中って結局は顔ですよね?」と思うくらいです。

だから Objective-C はキモい

Objective-C と言えば、嫌われるのも好かれるのもメッセージ式の文法のせいでしょう。 Smalltalk のメッセージ式をそのまま取り入れたこの文法は、まったく異質の文化を取り入れたのですから、拒絶反応があっても不思議ではないと思います。

もっとも、遅延束縛を実現するだけなら C の文法の範囲内で表せます。レシーバとセレクタを引数としてディスパッチ関数を呼べばいいです。

reply = _msg(aReceiver, "aMessage", arg1, ...)

しかし、そうしなかった理由は Cox 曰く、この方法ではセレクタを文字列で比較するのでコストが高くつくからだそうです。そこでコンパイラが、コンパイル時にセレクタを適切なデータ SEL 型に変換します。と言っても、 Stepstone Objective-C の SEL 型は文字列 type char * ですが。ただしセレクタの内容が重複しないようにコンパイラが調節するので、ポインタの比較でディスパッチできるわけです。現在のアップルの実装でも同じです。一つ違うのは、こちらは typedef struct objc_selector *SEL と定義されており、文字列型にキャストできません。

それでも「 C++ のようなメソッド呼び出しの文法にしてくれればよかったのに」と思う方もいると思いますが、前述した通り Cox の目的は言語の拡張ではないため、効率的かつ既存の文法と衝突しない方法を選んだようです。ただしこの文法を選んだ理由は特に述べられておらず、遅延束縛を Smalltalk のメッセージ式で表す必然性はおそらくありません。 aReceiver::method(arg1, ...) とかでもよかったはずです。

ですが考えてもみますと、 Cox らはプログラマにとって理想的だと考えた Smalltalk の開発環境(の一部)を、外の世界に持って来ようとしました。例えそれが C の上に実装されるとしても、大事なのは持って来ようとした概念と敬意です。 Objective-C が開発されたのは 1983 年、 C++ が C with Classes から名称変更されたのも 1983 年、 Smalltalk が Smalltalk-80 として公開されたのも 1983 年です。 Ada は...Ada 83 が 1983 年に開発されましたが、オブジェクト指向は未導入です。元々 C を拡張しようとした C++ は少し事情が異なるにしても、新しい開発方法を模索している時代にわざわざ既存の言語の習慣に従う必要はないはずです。というか、既存の言語に縛られてどうすんだと思います。当時の(かつアメリカの)空気なんてわかりませんけど、今の時代の方が C 系や Algol 系の文法に頭が縛られてるのかもしれません。

おわりに

私は必ずしも「キモい」と思うことが悪だとは思いませんし、「 Objective-C はキモくないよ」と言うつもりもありません。キモがられる要因の一つ一つの合理的(に見える)理由を説いてみたところで、キモいと思う人にとってキモいものはキモいです。キモがられる側がキモがる側に必死にキモくないアピールをしても人生の無駄ですし、「キモけりゃ使うな」と言ったところで、わざわざキモい連中に言われなくたって世の中はキモい言語は使わない方向に流れます(だってキモいし)。その上で、「 Objective-C はキモい」の前に「だから」が付け加えられるようになったとき、 Objective-C はやっと死ぬことができるのかもしれないな、と思います。

参考

💖 💪 🙅 🚩
szktty
SUZUKI Tetsuya

Posted on January 23, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Objective-C 供養
objc Objective-C 供養

January 23, 2020