{ $values { "2map-reduce-quots" sequence } }
{ $description "A version of " { $link 2map-reduce } " that takes a sequence of " { $snippet "{ 2map-quot 2reduce-quot }" } " pairs, returning the " { $link 2map-reduce } " result for each pair." } ;
+HELP: smart-loop
+{ $values { "quot" { $quotation ( ..a -- ..b ? ) } } }
+{ $description "A version of " { $link loop } " that runs until the " { $snippet "quot" } " returns " { $link f } " and leaves the result of the quotation on the stack." } ;
+
ARTICLE: "combinators.smart" "Smart combinators"
"A " { $emphasis "smart combinator" } " is a macro which reflects on the stack effect of an input quotation. The " { $vocab-link "combinators.smart" } " vocabulary implements a few simple smart combinators which look at the static stack effects of input quotations and generate code which produces or consumes the relevant number of stack values." $nl
"Take all input values from a sequence:"
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays assocs combinators.smart kernel locals
-math sequences stack-checker tools.test ;
+math random sequences stack-checker tools.test ;
IN: combinators.smart.tests
: test-bi ( -- 9 11 )
{ { 1 2 3 4 } 5 6 } [ [ 1 2 3 4 5 6 ] 2 output>array-n ] unit-test
{ { } 5 6 } [ [ 5 6 ] 2 output>array-n ] unit-test
{ { 1 2 } 3 4 5 6 } [ [ 1 2 3 4 5 6 ] 4 output>array-n ] unit-test
+
+{ t } [ [ 10 random dup even? ] smart-loop odd? ] unit-test
+{ t } [ 10 [ random dup even? ] smart-loop odd? ] unit-test
[ @ _ [ cleave-curry ] [ cleave-curry ] bi _ spread* ]
1 2each-from
] ;
+
+:: smart-loop ( ..a quot: ( ..a -- ..b ? ) -- ..b )
+ quot inputs/outputs :> ( #inputs #outputs )
+ [ quot preserving dup ]
+ [ #outputs ndrop ] while
+ [ #inputs ndrop ] #outputs ndip drop ; inline