時代遅れひとりFizzBuzz祭り、今回はActiveBasic。前回のVBScriptとはBASIC繋がりで。実に安直だが、しかし真実だ。
ActiveBasicは、何故かHDDの中に入っている。別段ActiveBasicで何か作ったりする訳でもないのに、なぜ入っているのだろうか? 謎である。
とはいえ折角だからFizzBuzzを書いてみた。ちなみにActiveBasic 4.24.00だ。
#console #strict Function FizzBuzz(n As Integer) As String If n Mod 15 = 0 Then FizzBuzz = "FizzBuzz" ElseIf n Mod 3 = 0 Then FizzBuzz = "Fizz" ElseIf n Mod 5 = 0 Then FizzBuzz = "Buzz" Else FizzBuzz = Str$(n) End If End Function Dim i As Integer For i = 1 To 100 Print FizzBuzz(i) Next
普通にコマンドプロンプトで動くコードである。そしてこの時点では殆どVBScriptと同じだ。違いは変数が型付きで且つバリアント型的なものが無い所が違うぐらいだろうか?
「#console」ではなく「#prompt」でも動くはずだが、次のコードを「#prompt」でビルドしたところ、手元のDELL Inspiron 2200では何故か実行時に100%落ちた。
#console #strict Function FizzBuzz(n As Integer) As String Dim str As String str = "" If n Mod 3 = 0 Then str = "Fizz" End If If n Mod 5 = 0 Then str = str & "Buzz" End If If str = "" Then FizzBuzz = Str$(n) Else FizzBuzz = str End If End Function Dim i As Integer For i = 1 To 100 Print FizzBuzz(i) Next
一瞬、ヘルプファイルの記述に反してString型をバシバシ使っているのがマズイのかと疑ってしまったのだが*1、DELL Latitude E5400では落ちなかった。原因は不明だ。
同じBASIC繋がりだが、ActiveBasicにはVBScriptと比べて1つだけ利点がある。Dimステートメントで初期化ができる所だ。
#console #strict Function FizzBuzz(n As Integer) As String Dim str = "" As String If n Mod 3 = 0 Then str = "Fizz" If n Mod 5 = 0 Then str = str & "Buzz" If str = "" Then str = Str$(n) FizzBuzz = str End Function Dim i As Integer For i = 1 To 100 Print FizzBuzz(i) Next
変数strの宣言と初期化をまとめて記述している。この手の書き方はC言語系の言語ではよくあると思うのだが、VBScript辺りでは許されていない書き方だったりする。
初期化は配列でも可能だ。しかし次のコードでは思った通りに動作しなかった。
#console #strict Dim refTable[3] = ["", "Fizz", "Buzz", "FizzBuzz"] As String Function FizzBuzz(n As Integer) As String Dim fizz = 0 As Integer, buzz = 0 As Integer refTable[0] = Str$(n) If n Mod 3 = 0 Then fizz = 1 If n Mod 5 = 0 Then buzz = 2 FizzBuzz = refTable[fizz + buzz] End Function Dim i As Integer For i = 1 To 100 Print FizzBuzz(i) Next
ビルドは問題なく通るのだが、「Fizz」「Buzz」「FizzBuzz」が表示されない。
次のように、配列の各要素に明示的に代入するように書き換えれば問題なく動作する。
#console #strict Dim refTable[3] As String refTable[1] = "Fizz" refTable[2] = "Buzz" refTable[3] = "FizzBuzz" Function FizzBuzz(n As Integer) As String Dim idx = 0 As Integer refTable[0] = Str$(n) If n Mod 3 = 0 Then idx += 1 If n Mod 5 = 0 Then idx += 2 FizzBuzz = refTable[idx] End Function Dim i As Integer For i = 1 To 100 Print FizzBuzz(i) Next
とはいえ、これでは折角の初期化構文が台無しである。他の型の配列ではうまく初期化されるようなので、恐らくString型の場合にのみ発生する仕様ないしバグではないかと想像している。
実際の所、String型ではなくBytePtr型なら動作する。
#console #strict Dim refTable[2] = ["Fizz", "Buzz", "FizzBuzz"] As BytePtr Function FizzBuzz(n As Integer) As String Dim idx = -1 As Integer If n Mod 3 = 0 Then idx += 1 If n Mod 5 = 0 Then idx += 2 If idx < 0 Then FizzBuzz = Str$(n) Else FizzBuzz = MakeStr(refTable[idx]) End If End Function Dim i As Integer For i = 1 To 100 Print FizzBuzz(i) Next
付属のヘルプファイルも見てみたのだが、ActiveBasicにおける文字列定数の型や扱いについてよく分からなかった。が、多分refTableの各要素の参照先にある文字を書き換えるのは止めたほうがよいだろう。
ActiveBasicはC言語やC++、Javaあたりの影響を受けていると言われているが、確かに配列まわりや代入演算子などは目に見えてC言語的だ。
文字列に関してもその傾向があるのだが、どこかちぐはぐな印象がある。文字列定数に関する情報が見つからなかったこともあるが、個人的にはChar型やByte型の配列の初期化で文字列定数をそのまま記述できない点が少しマイナスだと思う。
何より、mutableかimmutableか、プリミティブなデータ型かクラス的なものか、という違いはあるものの、最近は文字列専用の型を持つ言語が主流となりつつある*2。そんな中で「String型を捨てて、自前でメモリ管理しつつBytePtr型を使う」というActiveBasicは、目指す方向性がイマイチよく分からない。
*1:単なる被害妄想。
*2:動的言語でなくても、例えばObjective CamlやGoのような静的言語にも文字列用の型が用意されている訳で。特にGoはシステムプログラミングも視野に入れた言語だし……。