PrologでふつうにFizzBuzz

またFizzBuzz問題の話です。昨日はなるべく短く書こうってことだったけど今度は普通に書いてみます。と言ってもPrologで何が普通かなんでよく知らないので適当です。そして処理系はSWI-Polog。
とりあえず述語fizzbuzzを定義。

fizzbuzz(N, 'FizzBuzz') :- N mod 15 =:= 0, !.
fizzbuzz(N, 'Fizz') :- N mod 3 =:= 0, !.
fizzbuzz(N, 'Buzz') :- N mod 5 =:= 0, !.
fizzbuzz(N, N).

あとは、例えば1行ずつ出力するならこんなかんじ。

?- between(1,100, N), fizzbuzz(N, X), writeln(X), fail.

リストがほしいときはfindallを使うのかな。

?- findall(X, (between(1,100,N), fizzbuzz(N, X)), L).

もしくはこうか。

?- numlist(1, 100, Ns), maplist(fizzbuzz, Ns, L).

剰余を使わないでやるにはどうしようかと思ったけど、循環リストで書いてみた。

fizzbuzz_list(N, L) :-
	Fs = ['', '', 'Fizz' |Fs],
	Bs = ['', '', '', '', 'Buzz' |Bs],
	fizzbuzz_sub(0, N, Fs, Bs, L).
fizzbuzz_sub(N, N, _, _, []) :- !.
fizzbuzz_sub(I, N, [F|Fs], [B|Bs], [X|Xs]) :-
	I1 is I + 1,
	atom_concat(F, B, S),
	(S == '' -> X = I1 ; X = S),
	fizzbuzz_sub(I1, N, Fs, Bs, Xs).

ってPrologで循環リストって使っていいんだっけ?