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でふるい落とされる、という現象だったらしい。なんというか勉強になりましたありがとう
追記:嘘書いてしまった。マイナスになる前にガードで縛られてるってば・・・