Вычислить вычисленное значение во время выполнения?

Cleave - действительно полезный комбинатор для минимизации дублирования кода. Предположим, я хочу классифицировать чисел: обильные, совершенные, дефектные:

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 не компилируется, потому что "не может применить cleave к вычисляемому значению во время выполнения".

Если я не могу использовать cleave, тогда я должен сделать:

[ [ [ "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 для вычисляемых во время выполнения значений? Могу ли я минимизировать уродливое дублирование каким-либо другим способом, но при этом разрешить вычисления во время выполнения?

1 ответ

Решение

cleave скорее всего, не правильный ответ здесь. Когда Фактор не может применить SOMETHING к вычисляемому значению во время выполнения, чаще всего это означает, что что-то может быть написано лучше. Я думаю, что здесь вы хотите заменить cleave с гистограммой:

IN: scratchpad 100 [ { "abundant" "deficient" "perfect" } random ] replicate 
    histogram

--- Data stack:
H{ { "deficient" 33 } { "perfect" 30 } { "abundant" 37 } }
Другие вопросы по тегам