Cleave a run-time computed value?

元气小坏坏 提交于 2019-12-07 11:19:27

问题


Cleave is a really useful combinator for minimising code duplication. Suppose I want to classify Abundant, Perfect, Deficient numbers:

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 does not compile because "cannot apply cleave to a run-time computed value".

If I can't use cleave, then I have to essentially do:

[ [ [ "deficient" = ] count ] 
  [ [ "abundant" = ] count ]
  [ [ "perfect" = ] count ]
  tri
] dip

Which is lame and longer, and would get really ugly and long if the array of key-strings was longer. Also, importantly, doing it without cleave is impossible if the array of keys is generated at run-time.

Similarly for print-adp-stats: without cleave I would have to have this literal lying around in my source:

{
    [ "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 ]
}

Gross.

Is there a combinator to replace cleave for run-time computed values? Can I minimise the ugly duplication some other way, while still allowing computation at run-time?


回答1:


cleave is likely not the right answer here. When Factor says cannot apply SOMETHING to a run-time computed value most often it means something can be written better. I think here you want to replace cleave with histogram:

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

--- Data stack:
H{ { "deficient" 33 } { "perfect" 30 } { "abundant" 37 } }


来源:https://stackoverflow.com/questions/37951947/cleave-a-run-time-computed-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!