時代遅れひとりFizzBuzz祭り ActiveBasic編

時代遅れひとり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型をバシバシ使っているのがマズイのかと疑ってしまったのだが*1DELL 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の各要素の参照先にある文字を書き換えるのは止めたほうがよいだろう。

ActiveBasicC言語C++Javaあたりの影響を受けていると言われているが、確かに配列まわりや代入演算子などは目に見えてC言語的だ。

文字列に関してもその傾向があるのだが、どこかちぐはぐな印象がある。文字列定数に関する情報が見つからなかったこともあるが、個人的にはChar型やByte型の配列の初期化で文字列定数をそのまま記述できない点が少しマイナスだと思う。

何より、mutableかimmutableか、プリミティブなデータ型かクラス的なものか、という違いはあるものの、最近は文字列専用の型を持つ言語が主流となりつつある*2。そんな中で「String型を捨てて、自前でメモリ管理しつつBytePtr型を使う」というActiveBasicは、目指す方向性がイマイチよく分からない。

*1:単なる被害妄想。

*2:動的言語でなくても、例えばObjective CamlやGoのような静的言語にも文字列用の型が用意されている訳で。特にGoはシステムプログラミングも視野に入れた言語だし……。