Simula

概要

オスロのノルウェー計算センターのクリステン・ニガードとオルヨハン・ダールが1962年から1967年にかけて、Simula の元となる Simula I と Simula67 を ALGOL 60 の拡張として設計/実装した。Simula は当初シミュレーションに用いられたが、のちに汎用言語となった。名前「Simula」は「シミュレーション言語」を意味する英語「simulation language」と「簡潔な汎用言語」を意味する英語「simple universal language」の二つに由来する。
主に北欧圏で使用されたこと、言語的な未成熟さもあって広く普及することはなかったが、後続言語に与えた影響は大きい。特にSmalltalk は Simula のオブジェクト概念を一般化したものだと言うことができる。C++ もまた、当初はC言語に Simula のクラスなどの仕組みを追加したものであった。
開発の動機は、ある制限下におかれたモデル群の全体の挙動をどう記述するか、というものである。気体の分子運動を例にとると、システム全体を考えてその中の項として分子を扱うよりも、一つの一つの気体分子をモデル化し、それぞれの相互作用の結果をシステムとして捉える方が自然で取り扱いやすい。その為には小さなモデル、関連する法則、それらを一度に複数取り扱う能力が必要となる。こうして属性を備えたオブジェクト概念と、それに従属するメソッド概念が生まれたのである。
Simula 67 ではオブジェクト、 クラス、サブクラス、継承、動的束縛（仮想関数）、コルーチン、 ディスクリートイベントシミュレーション、ガベージコレクションの機能をもち、オブジェクト指向プログラミングの基本概念はすべてここで発案されているといえる。
Simula はプログラミングパラダイムとして最初のオブジェクト指向言語であると考えられる。その名前が示すように Simula はシミュレーションを行うために設計され、その必要性から今日のオブジェクト指向言語で使われる多くの機能のためのフレームワークを提供した。なお、Simula 当時「オブジェクト指向」という言葉はまだない。この用語はアラン・ケイが Simula の概念として70年代ごろに使い出したのが始まりといわれている。従ってその意味では Simula が世界最初のオブジェクト指向言語であり、Simula は「オブジェクト指向として再認識が可能な最古の言語」ということができる。
VLSI設計、プロセス、プロトコル、アルゴリズムといったシミュレーションや、組版、コンピュータグラフィックス、教育といったアプリケーションソフトに Simula は利用された。Simula 形式のオブジェクトは C++、Java、C# で再実装されており、Simula の影響を受けていることが知られている。C++ の開発者であるビャーネ・ストロヴストルップはBCPLのような機械語を出力し高速に動作する低レベル言語に Simula が提供する開発効率を高める機能を導入するため、C++ 開発時に Simula 67 の影響を大きく受けていることを認めている。

最小のプログラム

空のファイルはソースコードのサイズを基準とした場合で最も小さな Simula のプログラムである。これは1つのダミーのステートメントのみで構成される。
しかしながら合理的に考えれば最小のプログラムは空のブロックとして表現される。
BeginEnd ;
これは起動してすぐに終了するプログラムである。Simula ではプログラム自身が値を返す return文 を持たない。

古典的 Hello World

Simulaで記述された Hello world の例である。Simula は大文字と小文字を厳密に区別する。
BeginOutText ("Hello World!") ;
Outimage ;
End ;

典型的サブクラスと仮想関数

クラス、サブクラス、仮想関数を用いた現実的な例を以下に示す。
BeginClass Glyph ;
   Virtual: Procedure print Is Procedure print ;
   Begin
   End ;

   Glyph Class Char (c) ;
      Character c ;
      Begin
      Procedure print ;
      OutChar(c) ;
      End ;

   Glyph Class Line (elements) ;
      Ref (Glyph) Array elements ;
      Begin
      Procedure print ;
         Begin
         Integer i ;
         For i:= 1 Step 1 Until UpperBound (elements, 1) Do
            elements (i) .print ;
         OutImage ;
         End ;
      End ;

   Ref (Glyph) rg ;
   Ref (Glyph) Array rgs (1 : 4) ;

   ! Main program;
   rgs (1):- New Char ('A') ;
   rgs (2):- New Char ('b') ;
   rgs (3):- New Char ('b') ;
   rgs (4):- New Char ('a') ;
   rg:- New Line (rgs) ;
   rg.print ;
End ;
上記の例には1つの親クラス（Glyph）と2つのサブクラス（Char、Line）があり、1つの仮想関数と2つの実装がある。メインプログラムから実行を開始する。Simula は純粋仮想関数を持つクラスをインスタンス化できるため抽象基底クラスの概念が無い。これは上記の例にある全てのクラスがインスタンス化できるということである。しかしながら純粋仮想関数を呼び出すとランタイムライブラリエラーを引き起こす。

名前呼び

Simula は名前呼び（call by name、評価戦略を参照）をサポートしているため Jensen's Device（en:Jensen's Device）を容易に実装できる。デフォルトはALGOLと異なり値呼び（call by value）であるため、Jensen's Deviceを実装する際には、名前呼びであることを明示する必要がある。
単純な例として総和関数の実装例を以下に示す。
Real Procedure Sigma (l, m, n, u) ;
   Name l, u ;
   Integer l, m, n ;
   Real u ;
   Begin
   Real s ;
   l:= m ;
   While l <= n Do
      Begin
      s := s + u ;
      l := l + 1 ;
      End ;
   Sigma := s ;
   End ;
上記のコードは値（l）と式（u）を制御するために名前呼びを用いている。これにより式で使用する値を制御できる。Simula の標準規格は for 文にある種の制約があるため上記の例では while 文を使用している。
以下の式は次のように実装できる。
Z:= Sigma (i, 1, 100, 1 / (i + a) ** 2) ;

シミュレーション

Simula にはディスクリートイベントシミュレーションを行うためのシミュレーションパッケージが含まれている。このシミュレーションパッケージはSimulaのオブジェクト指向とコルーチンのコンセプトに基づいている。
下記の例で Sam、Sally、Andy は服を買おうとしている。彼らは1つの試着室を共有しなければならない。3人は正規分布によりランダムに約12分間店内を探索し、同様に試着室を約3分間占有する。以下は彼らが試着室をどのように使うのかをシミュレーションするものである。
Simulation
   Begin
   Class FittingRoom ;
      Begin
      Ref (Head) door ;
      Boolean inUse ;
      Procedure request ;
         Begin
         If inUse Then
             Begin
             Wait (door) ;
             door.First.Out ;
             End ;
         inUse := True ;
         End ;
      Procedure leave ;
         Begin
         inUse := False ;
         Activate door.First ;
         End ;
      door:- New Head ;
      End ;
  
   Procedure report (message) ;
      Text message ;
      Begin
      OutFix (Time, 2, 0) ;
      OutText (": " & message) ;
      OutImage ;
      End;

   Process Class Person (pname) ;
      Text pname ;
      Begin
      While True Do
         Begin
         Hold (Normal (12, 4, u)) ;
         report  (pname & " is requesting the fitting room") ;
         fittingroom1.request ;
         report (pname & " has entered the fitting room") ;
         Hold (Normal (3, 1, u)) ;
         fittingroom1.leave ;
         report (pname & " has left the fitting room") ;
         End ;
      End ;

   Integer u ;
   Ref (FittingRoom) fittingRoom1 ;

   fittingRoom1 :- New FittingRoom ;
   Activate New Person ("Sam") ;
   Activate New Person ("Sally") ;
   Activate New Person ("Andy") ;
   Hold (100) ;
   End;
メインブロックが Simulation でプレフィックスされることによりシミュレーションを実行できる。シミュレーションパッケージはどこのブロックからでも自由に利用でき、シミュレーションしているものそれ自体をシミュレーションするときにはシミュレーションを再帰的にネストできる。
試着室オブジェクトはキュー（door）により試着室にアクセスできる。誰かが使用中の試着室を使おうとしたときはこのキュー（Wait (door)）で待たなければならない。誰かが試着室を出るとき、列の先頭にいる者がキューからリリース（Activate door.first）されてドアキューから削除（door.First.Out）される。
Person は Process のサブクラスでありその動作は hold（店内を探索する時間と試着室で過ごす時間）を用いて記述され、試着室に出入りするために試着室オブジェクト内でメソッドを呼び出す。
メインプログラムは全てのオブジェクトを生成し、全ての Person オブジェクトをイベントキューに投入するためにアクティベートする。メインプログラムはシミュレーション時間で100分間待ってからプログラムを終了する。