Cleave は、コードの重複を最小限に抑えるための非常に便利なコンビネーターです。Abundant、Perfect、Deficient の数を分類したいとします。
USING: arrays assocs combinators formatting io kernel math
math.order math.primes.factors math.ranges sequences ;
IN: adp
CONSTANT: ADP { "deficient" "perfect" "abundant" }
: proper-divisors ( n -- seq )
dup zero? [ drop { } ] [ divisors dup length 1 - head ] if ;
: adp-classify ( n -- a/d/p )
dup proper-divisors sum <=>
{ +lt+ +eq+ +gt+ } ADP zip
H{ } assoc-clone-like at ;
: range>adp-classes ( n -- seq )
1 swap 1 <range> [ adp-classify ] map
ADP dup
[
[
[ = ] curry
[ count ] curry
] map
cleave 3array
] dip
swap zip H{ } assoc-clone-like ;
: print-adp-stats ( seq -- )
ADP [
[ dup [ swap at ] dip swap "%s: %s" sprintf ] curry
] map cleave
[ print ] tri@ ;
range>adp-classes
「実行時に計算された値にクリーブを適用できない」ため、コンパイルされません。
クリーブを使用できない場合は、基本的に次のことを行う必要があります。
[ [ [ "deficient" = ] count ]
[ [ "abundant" = ] count ]
[ [ "perfect" = ] count ]
tri
] dip
これは不自由で長く、キー文字列の配列がより長い場合、非常に醜く長くなります。また、キーの配列が実行時に生成される場合、切断せずに実行することは不可能です。
同様にprint-adp-stats
: なしcleave
では、このリテラルをソースに配置する必要があります。
{
[ "deficient" dup [ swap at ] dip swap "%s: %s" sprintf ]
[ "perfect" dup [ swap at ] dip swap "%s: %s" sprintf ]
[ "abundant" dup [ swap at ] dip swap "%s: %s" sprintf ]
}
きもい。
cleave
実行時の計算値を置き換えるコンビネータはありますか? 実行時に計算を許可しながら、他の方法で醜い重複を最小限に抑えることはできますか?