      { "n" integer } { "seq" sequence }
      { "n'" integer } { "seq'" sequence } }
 { $description "Part of the sequence protocol, this word translates the input index " { $snippet "n" } " into an index into the underlying storage returned by " { $link virtual-seq } "." } ;
+
+HELP: 2change-each
+{ $values
+     { "seq1" sequence } { "seq2" sequence } { "quot" quotation } }
+{ $description "Calls the quotation on subsequent pairs of objects from the two input sequences. The resulting computation replaces the element in the first sequence." }
+{ $examples { $example "USING: kernel math sequences prettyprint ;"
+    "{ 10 20 30 } dup { 60 70 80 } [ + ] 2change-each ."
+    "{ 70 90 110 }"
+} } ;
+
+HELP: 2map-reduce
+{ $values
+     { "seq1" sequence } { "seq2" sequence } { "map-quot" quotation } { "reduce-quot" quotation }
+     { "result" object } }
+{ $description "Unclips the first element of each sequence and calls " { $snippet "map-quot" } " on both objects. The result of this calculation is passed, along with the rest of both sequences, to " { $link 2reduce } ", with the computed object as the identity." }
+{ $examples { $example "USING: sequences prettyprint math ;"
+    "{ 10 30 50 } { 200 400 600 } [ + ] [ + ] 2map-reduce ."
+    "1290"
+} } ;
+
+HELP: 2pusher
+{ $values
+     { "quot" quotation }
+     { "quot" quotation } { "accum1" vector } { "accum2" vector } }
+{ $description "Creates two new vectors to accumultate values based on a predicate. The first vector accumulates values for which the predicate yields true; the second for false." } ;
+
+HELP: 2reverse-each
+{ $values
+     { "seq1" sequence } { "seq2" sequence } { "quot" quotation } }
+{ $description "Reverse the sequences using the " { $link <reversed> } " word and calls " { $link 2each } " on the reversed sequences." }
+{ $examples { $example "USING: sequences math prettyprint ;"
+    "{ 10 20 30 } { 1 2 3 } [ + . ] 2reverse-each"
+    "33\n22\n11"
+} } ;
+
+HELP: 2unclip-slice
+{ $values
+     { "seq1" sequence } { "seq2" sequence }
+     { "rest-slice1" sequence } { "rest-slice2" sequence } { "first1" object } { "first2" object } }
+{ $description "Unclips the first element of each sequence and leaves two slice elements and the two unclipped objects on the stack." }
+{ $examples { $example "USING: sequences prettyprint kernel arrays ;"
+    "{ 1 2 } { 3 4 } 2unclip-slice 4array [ . ] each"
+    "T{ slice { from 1 } { to 2 } { seq { 1 2 } } }\nT{ slice { from 1 } { to 2 } { seq { 3 4 } } }\n1\n3"
+} } ;
+
+HELP: accumulator
+{ $values
+     { "quot" quotation }
+     { "quot'" quotation } { "vec" vector } }
+{ $description "Creates a new quotation that pushes its result to a vector and outputs that vector on the stack." }
+{ $examples { $example "USING: sequences prettyprint kernel math ;"
+    "{ 1 2 } [ 30 + ] accumulator [ each ] dip ."
+    "V{ 31 32 }"
+} } ;
+
+HELP: binary-reduce
+{ $values
+     { "seq" sequence } { "start" integer } { "quot" quotation }
+     { "value" object } }
+{ $description "Like " { $link reduce } ", but splits the sequence in half recursively until each sequence is small enough, and calls the quotation on these smaller sequences. If the quotation computes values that depend on the size of their input, such as bignum arithmetic, then this algorithm can be more efficient than using " { $link reduce } "." }
+{ $examples "Computing factorial:"
+    { $example "USING: prettyprint sequences math ;"
+    "40 rest-slice 1 [ * ] binary-reduce ."
+    "20397882081197443358640281739902897356800000000" }
+} ;
+
+HELP: follow
+{ $values
+     { "obj" object } { "quot" quotation }
+     { "seq" sequence } }
+{ $description "Outputs a sequence containing the input object and all of the objects generated by successively feeding the result of the quotation called on the input object to the quotation recursuively. Objects yielded by the quotation are added to the output sequence until the quotation yields " { $link f } ", at which point the recursion terminates." }
+{ $examples "Get random numbers until zero is reached:"
+    { $unchecked-example
+    "USING: random sequences prettyprint math ;"
+    "100 [ random dup zero? [ drop f ] when ] follow ."
+    "{ 100 86 34 32 24 11 7 2 }"
+} } ;
+
+HELP: halves
+{ $values
+     { "seq" sequence }
+     { "first-slice" slice } { "second-slice" slice } }
+{ $description "Splits a sequence into two slices at the midpoint. If the sequence has an odd number of elements, the extra element is returned in the second slice." }
+{ $examples { $example "USING: arrays sequences prettyprint kernel ;"
+    "{ 1 2 3 4 5 } halves [ >array . ] bi@"
+    "{ 1 2 }\n{ 3 4 5 }"
+} } ;
+
+HELP: indices
+{ $values
+     { "obj" object } { "seq" sequence }
+     { "indices" sequence } }
+{ $description "Compares the input object to every element in the sequence and returns a vector containing the index of every position where the element was found." }
+{ $examples { $example "USING: sequences prettyprint ;"
+    "2 { 2 4 2 6 2 8 2 10 } indices ."
+    "V{ 0 2 4 6 }"
+} } ;
+
+HELP: insert-nth
+{ $values
+     { "elt" object } { "n" integer } { "seq" sequence }
+     { "seq'" sequence } }
+{ $description "Creates a new sequence where the " { $snippet "n" } "th index is set to the input object." }
+{ $examples { $example "USING: prettyprint sequences ;"
+    "40 3 { 10 20 30 50 } insert-nth ."
+    "{ 10 20 30 40 50 }"
+} } ;
+
+HELP: map-reduce
+{ $values
+     { "seq" sequence } { "map-quot" quotation } { "reduce-quot" quotation }
+     { "result" object } }
+{ $description "Unclips the first element of the sequence, calls " { $snippet "map-quot" } " on that element, and proceeds like a " { $link reduce } ", where the calculated element is the identity element and the rest of the sequence is the sequence to reduce." }
+{ $examples { $example "USING: sequences prettyprint math ;"
+    "{ 1 3 5 } [ sq ] [ + ] map-reduce ."
+    "35"
+} } ;
+
+HELP: new-like
+{ $values
+     { "len" integer } { "exemplar" "an exemplar sequence" } { "quot" quotation }
+     { "seq" sequence } }
+{ $description "Creates a new sequence of length " { $snippet "len" } " and calls the quotation with this sequence on the stack. The output of the quotation and the original exemplar are then passed to " { $link like } " so that the output sequence is the exemplar's type." } ;
+
+HELP: push-either
+{ $values
+     { "elt" object } { "quot" quotation } { "accum1" vector } { "accum2" vector } }
+{ $description "Pushes the input object onto one of the accumualators; the first if the quotation yields true, the second if false." } ;
+
+HELP: sequence-hashcode
+{ $values
+     { "n" integer } { "seq" sequence }
+     { "x" integer } }
+{ $description "Iterates over a sequence, computes a hashcode with " { $link hashcode* } " for each element, and combines them using " { $link sequence-hashcode-step } "." } ;
+
+HELP: sequence-hashcode-step
+{ $values
+     { "oldhash" integer } { "newpart" integer }
+     { "newhash" integer } }
+{ $description "An implementation word that computes a running hashcode of a sequence using some bit-twiddling. The resulting hashcode is always a fixnum." } ;
+
+HELP: short
+{ $values
+     { "seq" sequence } { "n" integer }
+     { "seq" sequence } { "n'" integer } }
+{ $description "Returns the input sequence and its length or " { $snippet "n" } ", whichever is less." }
+{ $examples { $example "USING: sequences kernel prettyprint ;"
+    "\"abcd\" 3 short [ . ] bi@"
+    "\"abcd\"\n3"
+} } ;
+
+HELP: shorten
+{ $values
+     { "n" integer } { "seq" sequence } }
+{ $description "Shortens a " { $link "growable" } " sequence to by " { $snippet "n" } " elements long." }
+{ $examples { $example "USING: sequences prettyprint kernel ;"
+    "V{ 1 2 3 4 5 } 3 over shorten ."
+    "V{ 1 2 3 }"
+} } ;
 
 ARTICLE: "sequences-unsafe" "Unsafe sequence operations"
 "The " { $link nth-unsafe } " and " { $link set-nth-unsafe } " sequence protocol bypasses bounds checks for increased performance."

HELP: reduce-index
{ $values
     { "seq" sequence } { "identity" object } { "quot" quotation } }
{ $description "Combines successive elements of the sequence and their indices using a binary operation, and outputs the final result. On the first iteration, the two inputs to the quotation are " { $snippet "identity" } ", the first element of the sequence, and its index, 0. On successive iterations, the first input is the result of the previous iteration, the second input is the corresponding element of the sequence, and the third is its index." }
{ $examples { $example "USING: sequences prettyprint math ;"
    "{ 10 50 90 } 0 [ + + ] reduce-index ."
    "153"

{ delete-nth remove delete } related-words

HELP: cut-slice
{ $values { "seq" sequence } { "n" "a non-negative integer" } { "before-slice" sequence } { "after-slice" "a slice" } }
{ $description "Outputs a pair of sequences, where " { $snippet "before" } " consists of the first " { $snippet "n" } " elements of " { $snippet "seq" } " and has the same type, while " { $snippet "after" } " is a slice of the remaining elements." }
{ $notes "Unlike " { $link cut } ", the run time of this word is proportional to the length of " { $snippet "before" } ", not " { $snippet "after" } ", so it is suitable for use in an iterative algorithm which cuts successive pieces off a sequence." } ;

