lists:seqの実装とか

@Masahitoさんのつぶやき、

を見てなんだか気になって、試してみる。

1> lists:seq(5,4).
[]
2> lists:seq(6,4).
** exception error: no function clause matching lists:seq(6,4)

へええ、しかし単純にException errorじゃなくて no function clause というてはるので、これはガード条件ではじかれて該当しないパターンね、とわかる。おそらくそういう条件があるんだろう、とチャッと試してみた。

seq(F, T) when F =< T -> [F|seq(F+1, T)];
seq(F, T) when F =:= T+1 -> [].
2> t:seq(5,4).
[]
3> t:seq(6,4).
** exception error: no function clause matching t:seq(6,4)

まあそうだよなあ。とか。一応本物のlists:seq()は増分もとるので拡張。

sequ(F, T) -> sequ(F,T,1).
sequ(F, T, INC) when F =< T -> [F|sequ(F+INC, T, INC)];
sequ(F, T, INC) when F =< T+INC -> [].

まあおkっぽい。

のだけれども、なんだか気になってしまってソースを読んでみてびっくり。
なんと! (簡単のため、2引数のみ)

seq(First, Last)
    when is_integer(First), is_integer(Last), First-1 =< Last ->
    seq_loop(Last-First+1, Last, []).

seq_loop(N, X, L) when N >= 4 ->
     seq_loop(N-4, X-4, [X-3,X-2,X-1,X|L]);
seq_loop(N, X, L) when N >= 2 ->
     seq_loop(N-2, X-2, [X-1,X|L]);
seq_loop(1, X, L) ->
     [X|L];
seq_loop(0, _, L) ->
     L.

末尾再起&アキュムレート方式だった! しかも4倍、2倍での一気に連続のホップステップ高速化されている! なんというPragmatic。すごいなあ。
というわけで、結局件の現象はこの3行目、Last - First + 1 が指定条件ではマイナスになってしまうため no clauseになる二行目のFirst-1 =< Lastでふるい落とされる、という現象だったらしい。なんというか勉強になりましたありがとう

追記:嘘書いてしまった。マイナスになる前にガードで縛られてるってば・・・