再帰では,基本的にどんどん成長方法も実行も常に同じ規則で続いていきます.
この事情は数値引数で繰り返しを作る場合も同じですね.
しかし,「第1回目の実行,あるいは第2回目の実行に限って何かをする/しない」というようなことも可能です.
今回はこの手筋を説明しましょう.
基本的な構文は次の形です:
a(X,Y):****a(**,A)第n回目の実行でYとして呼び出されるものをY[n]と書くことにすると,
a(**,B)
Y[1]=B, Y[2]=A, Y[3]=A, Y[4]=A, Y[5]=A,…となることが分かると思います.再帰の変数の更新規則の部分に
一番代表的な利用方法は,初項のみ不規則な成長速度を与えるという物です.例えば
a(X,Y):XXa(sssYX,ss)というコードを見てください.XがsssYずつ増えていくというコードですが,
a(r,)
b(X):XXb(sssssX)というコードを思いつく人がほとんどだと思いますが,この方法よりも
b(sssr)
a(X,Y):XXa(sYYX,ss)というような書き方も出来ますね.
a(r,s)
もちろん,実行部にYを混ぜても不規則な初項が楽しめます.
a(X,Y):XXXXYa(sX,l) a(sssr,r)などと書いてみると,最初だけ規則と外れた方向転換をする…という具合です.
「最初の2項だけ特別!」みたいなこともできます(あまり使ったことはないですが…).つまり
a(X,Y,Z):****a(**,Z,A)とすると,
a(X,B,C)
Y[1]=B, Y[2]=C, Y[3]=A, Y[4]=A, Y[5]=A,…となることが分かると思います.
他の方法と複合した例を見てみましょう.
a(X,Y):YYa(sX,XrXrX)この「Y=XrXrX」という変数の利用の仕方は,n倍関数の省略の講で
a(,srsl)
最後に,「最初の2項だけ特別!」を実現するちょっと変わった方法を紹介しましょう.
次のようなコードを考えます.
a(X,Y):****a(**,YY)今までのようにYの中身を全く新しくしてしまうのではなく,2倍関数を使っています.
a(,l)
Y[1]=l, Y[2]=ll, Y[3]=llll, Y[4]=llllllll,…とあくまでも「常に規則的に」変化します.しかし,Herbertにおいてはllllは何もしないことと同じなので
Y[1]=l, Y[2]=ll, Y[3]="", Y[4]="",…と第1項,第2項だけ特別な何かをやっているように見えることになります.
a(X,Y):****a(**,YYl)などとすれば
a(,)
Y[1]="", Y[2]=l, Y[3]=r, Y[4]=r,…とやはり特別な第1,2項が実現されます(「=r」というのは結果的に同じ経路になるという意味).