今回取り上げる「Seed7」はPascalやAdaに似たプログラミング言語です。インタプリタも用意されていますが、C言語に変換して実行ファイルを生成できます。安全性を重視した厳格な静的型付けや、ユーザーによる構文の定義が可能な拡張性の高さが特徴の言語です。今回はSeed7について紹介します。
Seed7について
Seed7は、ソフトウェア開発者のトーマス・メルテス(Thomas Mertes)氏によって設計された汎用プログラミング言語です。Windows/macOS/Linuxで動作するオープンソースの言語であり、GitHubやSourceForgeで公開されています。
Seed7のWebサイト(https://seed7.sourceforge.net/)には、親切なマニュアルがあり、デモとして、ゲームや実用ツールが掲載されています。ゲームは実際にWebサイト上で遊ぶこともできます。
-
Seed7のWebサイト
もともと、開発者が1989年に開発したコンパイラ「MASTER」とインタプリタ「HAL」を統合して、2005年にオープンソースの形態でSeed7が公開されました。
テンプレートやジェネリックス、演算子のオーバーロードなど、拡張性の高い機能が実装されています。ユニークなのは、ユーザーが新しい構文を定義できるようになっている点です。
インタプリタの「s7」に加えて、コンパイラの「s7c」が用意されています。s7cを使うと、Seed7のプログラムをC言語に変換したり実行ファイルを作成したりできます。
Seed7のインストール方法
Seed7はWindows/macOS/Linuxに対応しています。インストール方法はそれぞれ異なります。
【Windowsの場合】
Windowsであれば、オープンソースのプロジェクトをホストしているSourceForge( https://sourceforge.net/projects/seed7/files/bin/ )からインストーラーがダウンロードできます。ただし、最新のWindows版のバイナリは提供されていないので、比較的新しいバイナリファイル(seed7_05_20240812_win.exe)をダウンロードしましょう。
「最新版が提供されていないのはなぜ?」と思うかもしれませんが、インストーラーが最新のソースコードを取得して、自動的に最新版にビルドしてくれます。執筆時の最新バージョンは、2025-03-25でした。
画面の指示に従って、キーボードのキーを押していくとインストールされます。なお、最新版にアップデートする際に、画面がフリーズしたように見えるのですが、根気強くコンパイル完了を待ちましょう。「C:\seed7\bin」フォルダに続々と実行ファイルが作成されます。
【macOSの場合】
macOSの場合は、ソースコードを取得してきてビルドできます。ターミナルを起動して、以下のコマンドを実行しましょう。なお、XcodeとHomebrew( https://brew.sh/ja/ )を先にインストールしておく必要があります。
# リポジトリを取得
git clone https://github.com/ThomasMertes/seed7.git
# ビルド
cd seed7/src
cp mk_osxcl.mak makefile
make depend
make
# インストール
sudo make install
なお、上記の手順は簡易版で、GUIなど完全にライブラリをビルドしたい場合には、こちら(https://seed7.sourceforge.net/build.htm)にある「COMPILING UNDER MAC OS」を参考にして作業すると良いでしょう。
Seed7の簡単なプログラムを作ってみよう
それでは、簡単なSeed7のプログラムを作ってみましょう。Seed7のプログラムは、Pascalに似たところがあります。以下が、Seed7の最も簡単なプログラムです。
# 基本ライブラリを取り込む --- (*1)
$ include "seed7_05.s7i";
# メイン関数を定義 --- (*2)
const proc: main is func
begin
writeln("Hello, World!");
end func;
プログラムの(*1)では、基本ライブラリを取り込みます。基本ライブラリが「seed7_05.s7i」という名前なのに驚きますが、このライブラリの中で、基本構文や演算子の宣言などが含まれています。
(*2)ではメイン関数を定義します。そして、面白いことに、メイン関数は定数(const)文として定義します。Seed7では「const 型名: 定数名 is 値;」の書式で定数を定義します。
それで「const proc: main is func…」と書いてありますが「const proc: main」で、戻り値のない関数mainを定数として定義すると言う意味です。そして続く「is func begin … end」というのが関数の定義になります。「writeln(値)」で値を画面に出力します。
プログラムを実行してみましょう。上記のプログラムを「hello.sd7」という名前で保存します。そして、ターミナル(WindowsならPowerShell、macOSならターミナル.app)で下記のコマンドを実行しましょう。
s7 -q hello.sd7
すると、次の画面のように「Hello, World!」と表示されます。
なお、Seed7はプログラムをC言語に変換し、実行ファイルを生成することができます。
# コンパイル
s7c hello.sd7
# 実行 - Windowの場合
.\hello
# 実行 - macOSの場合
./hello
FizzBuzzのプログラムを作成してみよう
続いて、本連載で毎回作成しているFizzBuzz問題を解くプログラムも作ってみましょう。FizzBuzz問題とは次のような問題です。
1から100までの数を出力するプログラムを書いてください。ただし、3の倍数のときは数の代わりに「Fizz」と、5の倍数のときは「Buzz」と表示してください。3と5の倍数の時は「FizzBuzz」と表示してください。
Seed7でFizzBuzz問題を解くプログラムは次のようになります。見慣れないと、ちょっと何を書いているのか分からない部分があると思います。ただ、難しい訳ではないので、解説と合わせてゆっくり読み解いてみてください。
$ include "seed7_05.s7i";
# Fizz/Buzzを判定する関数を定義 --- (*1)
const func boolean: isFizz (in integer: n) is return (n mod 3) = 0;
const func boolean: isBuzz (in integer: n) is return (n mod 5) = 0;
# FizzBuzzを求める関数を定義 --- (*2)
const func string: getFizzBuzz(in integer: n) is func
result # 戻り値の定義 --- (*3)
var string: result is "";
local # ローカル変数の定義 --- (*4)
var boolean: fizz is FALSE;
var boolean: buzz is FALSE;
begin
# Fizz/Buzzを判定 --- (*5)
fizz := isFizz(n);
buzz := isBuzz(n);
# if文で一つずつFizz/Buzzを確認する --- (*6)
if fizz and buzz then
result := "FizzBuzz";
elsif fizz then
result := "Fizz";
elsif buzz then
result := "Buzz";
else
result := str(n); # Fizz/Buzz以外のとき文字列に変換 --- (*7)
end if;
end func;
# メイン関数を定義 --- (*8)
const proc: main is func
local # ローカル変数の定義
var integer: i is 1;
begin
# 1から100まで繰り返す --- (*9)
for i range 1 to 100 do
writeln(getFizzBuzz(i))
end for;
end func;
プログラムを確認しましょう。(*1)の部分では、Fizz/Buzzを判定する一行関数を定義しました。「const func 戻り値型: 関数名( in 引数型: 引き数名) is return 式」のように厳格な型定義が必要とは言え、このように一行で関数が書けるようになっています。
(*2)の関数getFizzBuzzではFizz/Buzzの文字列に変換する関数を定義します。複数行の関数を定義するには、「const func 戻り値: 関数名(in 引数型: 引き数名) is func … begin … end func;」のような書式で記述します。
(*3)に書いているように、関数の戻り値を何という名前の変数に代入するかresult句で指定するようになっています。ここでは、resultという変数に関数の戻り値を代入するように指定しました。
また、昔のC言語やPascalでは、関数内でローカル変数を利用する時、必ず、関数宣言の直後で変数をまとめて定義しなくてはなりませんでしたが、Seed7も同じです。(*2)の関数宣言の直後で、(*4)のようにlocal句を記述して、そこにローカル変数の定義を記述します。「var 型名: 変数名」のように記述します。
(*5)では、一行関数isFizz/isBuzzを使って、変数にfizzかbuzzかの判定を代入します。(*6)では、if文で一つずつ条件を確認して、FizzBuzz/Fizz/Buzz/数値を判定します。条件判定を行うには、基本的に「if 条件式 then ... else ... end if」と記述します。そして、連続でif文を記述する際は「elsif 条件式 then ...」のように記述します。
(*7)では関数strを利用して数値を文字列に変換します。
(*8)ではメイン関数を定義します。(*9)ではfor文を記述して1から100まで繰り返し、関数getFizzBuzzを呼び出します。
それでは、プログラムを実行してみましょう。上記のプログラムを「fizzbuzz.sd7」という名前で保存して、ターミナルで下記のコマンドを実行します。
s7 fizzbuzz.sd7
コマンドを実行すると、下記のようにFizzBuzzの結果が表示されます。
まとめ
以上、今回はSeed7を取り上げて、簡単なプログラムを紹介しました。実際にプログラムをいくつか書いてみて「型にとても厳格」という点が気になりました。C言語に変換したり、実行ファイルに変換できるのは素晴らしいのですが、型推論がないため、個人的には記述量が多くとても冗長に感じました。ただし、全ての型が明示されるので、安全で分かりやすいという主張もあります。
現在も活発に開発されており、親切なマニュアルもあります。既にメジャーな言語を習得しているなら、比較的短時間で習得できるでしょう。サンプルやデモもたくさん用意されており、ライブラリも一通り揃っています。Visual Studio Code用の拡張もあります。自作ツールなどの個人プロジェクトで活用してみるのはどうでしょうか。
自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2004年度未踏ユース スーパークリエータ認定、2010年 OSS貢献者章受賞。技術書も多く執筆している。直近では、「実践力をアップする Pythonによるアルゴリズムの教科書(マイナビ出版)」「シゴトがはかどる Python自動処理の教科書(マイナビ出版)」「すぐに使える!業務で実践できる! PythonによるAI・機械学習・深層学習アプリのつくり方 TensorFlow2対応(ソシム)」「マンガでざっくり学ぶPython(マイナビ出版)」など。