<commit_before>! Copyright (C) 2009 <NAME>.
! See http://factorcode.org/license.txt for BSD license.
USING: classes.tuple help.markup help.syntax kernel math
quotations sequences stack-checker ;
IN: combinators.smart

HELP: input<sequence
{ $values
     { "quot" quotation }
     { "newquot" quotation }
}
{ $description "Infers the number of inputs, " { $snippet "n" } ", to " { $snippet "quot" } " and calls the " { $snippet "quot" } " with the first " { $snippet "n" } " values from a sequence." }
{ $examples
    { $example
        "USING: combinators.smart math prettyprint ;"
        "{ 1 2 3 } [ + + ] input<sequence ."
        "6"
    }
} ;

HELP: output>array
{ $values
     { "quot" quotation }
     { "newquot" quotation }
}
{ $description "Infers the number or outputs from the quotation and constructs an array from those outputs." }
{ $examples
    { $example
        "USING: combinators combinators.smart math prettyprint ;
9 [
    { [ 1 - ] [ 1 + ] [ sq ] } cleave
] output>array ."
    "{ 8 10 81 }"
    }
} ;

HELP: output>sequence
{ $values
     { "quot" quotation } { "exemplar" "an exemplar" }
     { "newquot" quotation }
}
{ $description "Infers the number of outputs from the quotation and constructs a new sequence from those objects of the same type as the exemplar." }
{ $examples
    { $example
        "USING: combinators.smart kernel math prettyprint ;"
        "4 [ [ 1 + ] [ 2 + ] [ 3 + ] tri ] V{ } output>sequence ."
        "V{ 5 6 7 }"
    }
} ;

HELP: reduce-outputs
{ $values
     { "quot" quotation } { "operation" quotation }
     { "newquot" quotation }
}
{ $description "Infers the number of outputs from " { $snippet "quot" } " and reduces them using " { $snippet "operation" } ". The identity for the " { $link reduce } " operation is the first output." }
{ $examples
    { $example
        "USING: combinators.smart kernel math prettyprint ;"
        "3 [ [ 4 * ] [ 4 / ] [ 4 - ] tri ] [ * ] reduce-outputs ."
        "-9"
    }
} ;

HELP: sum-outputs
{ $values
     { "quot" quotation }
     { "n" integer }
}
{ $description "Infers the number of outputs from " { $snippet "quot" } " and returns their sum." }
{ $examples
    { $example
        "USING: combinators.smart kernel math prettyprint ;"
        "10 [ [ 1 - ] [ 1 + ] bi ] sum-outputs ."
        "20"
    }
} ;

HELP: append-outputs
{ $values
     { "quot" quotation }
     { "seq" sequence }
}
{ $description "Infers the number of outputs from " { $snippet "quot" } " and returns a sequence of the outputs appended." }
{ $examples
    { $example
        "USING: combinators.smart prettyprint ;"
        "[ { 1 2 } { \"A\" \"b\" } ] append-outputs ."
        "{ 1 2 \"A\" \"b\" }"
    }
} ;

HELP: append-outputs-as
{ $values
     { "quot" quotation } { "exemplar" sequence }
     { "seq" sequence }
}
{ $description "Infers the number of outputs from " { $snippet "quot" } " and returns a sequence of type " { $snippet "exemplar" } " of the outputs appended." }
{ $examples
    { $example
        "USING: combinators.smart prettyprint ;"
        "[ { 1 2 } { \"A\" \"b\" } ] V{ } append-outputs-as ."
        "V{ 1 2 \"A\" \"b\" }"
    }
} ;

{ append-outputs append-outputs-as } related-words

HELP: drop-outputs
{ $values { "quot" quotation } }
{ $description "Calls a quotation and drops any values it leaves on the stack." } ;

HELP: keep-inputs
{ $values { "quot" quotation } }
{ $description "Calls a quotation and preserves any values it takes off the stack." } ;

{ drop-outputs keep-inputs } related-words

HELP: dropping
{ $values
    { "quot" quotation }
    { "quot" quotation }
}
{ $description "Outputs a quotation that, when called, will have the effect of dropping the number of inputs to the original quotation." }
{ $examples
    { $example
        """USING: combinators.smart math prettyprint ;
[ + + ] dropping ."""
"""[ 3 ndrop ]"""
    }
} ;

HELP: input<sequence-unsafe
{ $values
    { "quot" quotation }
    { "quot" quotation }
}
{ $description "An unsafe version of " { $link input<sequence-unsafe } "." } ;

HELP: map-reduce-outputs
{ $values
    { "quot" quotation } { "mapper" quotation } { "reducer" quotation }
    { "quot" quotation }
}
{ $description "Infers the number of outputs from " { $snippet "quot" } " and, treating those outputs as a sequence, calls " { $link map-reduce } " on them." }
{ $examples
    { $example
"""USING: math combinators.smart prettyprint ;
[ 1 2 3 ] [ sq ] [ + ] map-reduce-outputs ."""
"14"
    }
} ;

HELP: nullary
{ $values
    { "quot" quotation }
    { "quot" quotation }
}
{ $description "Infers the number of inputs to a quotation and drops them from the stack." }
{ $examples
    { $code
        """USING: combinators.smart kernel math ;
1 2 [ + ] nullary"""
    }
} ;

HELP: preserving
{ $values
    { "quot" quotation }
    { "quot" quotation }
}
{ $description "Calls a quotation and leaves any consumed inputs on the stack beneath the quotation's outputs." }
{ $examples
    { $example
        """USING: combinators.smart kernel math prettyprint ;
1 2 [ + ] preserving [ . ] tri@"""
"""1
2
3"""
    }
} ;

HELP: smart-apply
{ $values
    { "quot" quotation } { "n" integer }
    { "quot" quotation }
}
{ $description "Applies a quotation to the datastack " { $snippet "n" } " times, starting lower on the stack and working up in increments of the number of inferred inputs to the quotation." }
{ $examples
    { $example
        """USING: combinators.smart prettyprint math kernel ;
1 2 3 4 [ + ] 2 smart-apply [ . ] bi@"""
"""3
7"""
    }
} ;

HELP: smart-if
{ $values
    { "pred" quotation } { "true" quotation } { "false" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link if } " that takes three quotations, where the first quotation is a predicate that preserves any inputs it consumes." } ;

HELP: smart-if*
{ $values
    { "pred" quotation } { "true" quotation } { "false" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link if } " that takes three quotations, where the first quotation is a predicate that preserves any inputs it consumes, the second is the " { $snippet "true" } " branch, and the third is the " { $snippet "false" } " branch. If the " { $snippet "true" }  " branch is taken, the values are left on the stack and the quotation is called. If the " { $snippet "false" } " branch is taken, the number of inputs inferred from predicate quotation is dropped and the quotation is called." } ;

HELP: smart-unless
{ $values
    { "pred" quotation } { "false" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link unless } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "false" } " branch." } ;

HELP: smart-unless*
{ $values
    { "pred" quotation } { "false" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link unless } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "false" } " branch. If the " { $snippet "true" }  " branch is taken, the values are left on the stack. If the " { $snippet "false" } " branch is taken, the number of inputs inferred from predicate quotation is dropped and the quotation is called." } ;

HELP: smart-when
{ $values
    { "pred" quotation } { "true" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link when } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "true" } " branch." } ;

HELP: smart-when*
{ $values
    { "pred" quotation } { "true" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link when } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "true" } " branch. If the " { $snippet "true" }  " branch is taken, the values are left on the stack and the quotation is called. If the " { $snippet "false" } " branch is taken, the number of inputs inferred from predicate quotation is dropped." } ;

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:"
{ $subsections
    input<sequence
    input<sequence-unsafe
}
"Store all output values to a sequence:"
{ $subsections
    output>sequence
    output>array
}
"Reducing the set of output values:"
{ $subsections
    reduce-outputs
    map-reduce-outputs
}
"Applying a quotation to groups of elements on the stack:"
{ $subsections smart-apply }
"Summing output values:"
{ $subsections sum-outputs }
"Concatenating output values:"
{ $subsections
    append-outputs
    append-outputs-as
}
"Drop the outputs after calling a quotation:"
{ $subsections drop-outputs }
"Cause a quotation to act as a no-op and drop the inputs:"
{ $subsection nullary }
"Preserve the inputs below or above the outputs of the quotation:"
{ $subsections preserving keep-inputs }
"Versions of if that infer how many inputs to keep from the predicate quotation:"
{ $subsections smart-if smart-when smart-unless }
"Versions of if* that infer how many inputs to keep from the predicate quotation:"
{ $subsections smart-if* smart-when* smart-unless* }
"New smart combinators can be created by defining " { $link "macros" } " which call " { $link infer } "." ;

ABOUT: "combinators.smart"
<commit_msg>smart-docs output>array typo fix<commit_after>! Copyright (C) 2009 <NAME>.
! See http://factorcode.org/license.txt for BSD license.
USING: classes.tuple help.markup help.syntax kernel math
quotations sequences stack-checker ;
IN: combinators.smart

HELP: input<sequence
{ $values
     { "quot" quotation }
     { "newquot" quotation }
}
{ $description "Infers the number of inputs, " { $snippet "n" } ", to " { $snippet "quot" } " and calls the " { $snippet "quot" } " with the first " { $snippet "n" } " values from a sequence." }
{ $examples
    { $example
        "USING: combinators.smart math prettyprint ;"
        "{ 1 2 3 } [ + + ] input<sequence ."
        "6"
    }
} ;

HELP: output>array
{ $values
     { "quot" quotation }
     { "newquot" quotation }
}
{ $description "Infers the number of outputs from the quotation and constructs an array from those outputs." }
{ $examples
    { $example
        "USING: combinators combinators.smart math prettyprint ;
9 [
    { [ 1 - ] [ 1 + ] [ sq ] } cleave
] output>array ."
    "{ 8 10 81 }"
    }
} ;

HELP: output>sequence
{ $values
     { "quot" quotation } { "exemplar" "an exemplar" }
     { "newquot" quotation }
}
{ $description "Infers the number of outputs from the quotation and constructs a new sequence from those objects of the same type as the exemplar." }
{ $examples
    { $example
        "USING: combinators.smart kernel math prettyprint ;"
        "4 [ [ 1 + ] [ 2 + ] [ 3 + ] tri ] V{ } output>sequence ."
        "V{ 5 6 7 }"
    }
} ;

HELP: reduce-outputs
{ $values
     { "quot" quotation } { "operation" quotation }
     { "newquot" quotation }
}
{ $description "Infers the number of outputs from " { $snippet "quot" } " and reduces them using " { $snippet "operation" } ". The identity for the " { $link reduce } " operation is the first output." }
{ $examples
    { $example
        "USING: combinators.smart kernel math prettyprint ;"
        "3 [ [ 4 * ] [ 4 / ] [ 4 - ] tri ] [ * ] reduce-outputs ."
        "-9"
    }
} ;

HELP: sum-outputs
{ $values
     { "quot" quotation }
     { "n" integer }
}
{ $description "Infers the number of outputs from " { $snippet "quot" } " and returns their sum." }
{ $examples
    { $example
        "USING: combinators.smart kernel math prettyprint ;"
        "10 [ [ 1 - ] [ 1 + ] bi ] sum-outputs ."
        "20"
    }
} ;

HELP: append-outputs
{ $values
     { "quot" quotation }
     { "seq" sequence }
}
{ $description "Infers the number of outputs from " { $snippet "quot" } " and returns a sequence of the outputs appended." }
{ $examples
    { $example
        "USING: combinators.smart prettyprint ;"
        "[ { 1 2 } { \"A\" \"b\" } ] append-outputs ."
        "{ 1 2 \"A\" \"b\" }"
    }
} ;

HELP: append-outputs-as
{ $values
     { "quot" quotation } { "exemplar" sequence }
     { "seq" sequence }
}
{ $description "Infers the number of outputs from " { $snippet "quot" } " and returns a sequence of type " { $snippet "exemplar" } " of the outputs appended." }
{ $examples
    { $example
        "USING: combinators.smart prettyprint ;"
        "[ { 1 2 } { \"A\" \"b\" } ] V{ } append-outputs-as ."
        "V{ 1 2 \"A\" \"b\" }"
    }
} ;

{ append-outputs append-outputs-as } related-words

HELP: drop-outputs
{ $values { "quot" quotation } }
{ $description "Calls a quotation and drops any values it leaves on the stack." } ;

HELP: keep-inputs
{ $values { "quot" quotation } }
{ $description "Calls a quotation and preserves any values it takes off the stack." } ;

{ drop-outputs keep-inputs } related-words

HELP: dropping
{ $values
    { "quot" quotation }
    { "quot" quotation }
}
{ $description "Outputs a quotation that, when called, will have the effect of dropping the number of inputs to the original quotation." }
{ $examples
    { $example
        """USING: combinators.smart math prettyprint ;
[ + + ] dropping ."""
"""[ 3 ndrop ]"""
    }
} ;

HELP: input<sequence-unsafe
{ $values
    { "quot" quotation }
    { "quot" quotation }
}
{ $description "An unsafe version of " { $link input<sequence-unsafe } "." } ;

HELP: map-reduce-outputs
{ $values
    { "quot" quotation } { "mapper" quotation } { "reducer" quotation }
    { "quot" quotation }
}
{ $description "Infers the number of outputs from " { $snippet "quot" } " and, treating those outputs as a sequence, calls " { $link map-reduce } " on them." }
{ $examples
    { $example
"""USING: math combinators.smart prettyprint ;
[ 1 2 3 ] [ sq ] [ + ] map-reduce-outputs ."""
"14"
    }
} ;

HELP: nullary
{ $values
    { "quot" quotation }
    { "quot" quotation }
}
{ $description "Infers the number of inputs to a quotation and drops them from the stack." }
{ $examples
    { $code
        """USING: combinators.smart kernel math ;
1 2 [ + ] nullary"""
    }
} ;

HELP: preserving
{ $values
    { "quot" quotation }
    { "quot" quotation }
}
{ $description "Calls a quotation and leaves any consumed inputs on the stack beneath the quotation's outputs." }
{ $examples
    { $example
        """USING: combinators.smart kernel math prettyprint ;
1 2 [ + ] preserving [ . ] tri@"""
"""1
2
3"""
    }
} ;

HELP: smart-apply
{ $values
    { "quot" quotation } { "n" integer }
    { "quot" quotation }
}
{ $description "Applies a quotation to the datastack " { $snippet "n" } " times, starting lower on the stack and working up in increments of the number of inferred inputs to the quotation." }
{ $examples
    { $example
        """USING: combinators.smart prettyprint math kernel ;
1 2 3 4 [ + ] 2 smart-apply [ . ] bi@"""
"""3
7"""
    }
} ;

HELP: smart-if
{ $values
    { "pred" quotation } { "true" quotation } { "false" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link if } " that takes three quotations, where the first quotation is a predicate that preserves any inputs it consumes." } ;

HELP: smart-if*
{ $values
    { "pred" quotation } { "true" quotation } { "false" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link if } " that takes three quotations, where the first quotation is a predicate that preserves any inputs it consumes, the second is the " { $snippet "true" } " branch, and the third is the " { $snippet "false" } " branch. If the " { $snippet "true" }  " branch is taken, the values are left on the stack and the quotation is called. If the " { $snippet "false" } " branch is taken, the number of inputs inferred from predicate quotation is dropped and the quotation is called." } ;

HELP: smart-unless
{ $values
    { "pred" quotation } { "false" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link unless } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "false" } " branch." } ;

HELP: smart-unless*
{ $values
    { "pred" quotation } { "false" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link unless } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "false" } " branch. If the " { $snippet "true" }  " branch is taken, the values are left on the stack. If the " { $snippet "false" } " branch is taken, the number of inputs inferred from predicate quotation is dropped and the quotation is called." } ;

HELP: smart-when
{ $values
    { "pred" quotation } { "true" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link when } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "true" } " branch." } ;

HELP: smart-when*
{ $values
    { "pred" quotation } { "true" quotation }
    { "quot" quotation }
}
{ $description "A version of " { $link when } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "true" } " branch. If the " { $snippet "true" }  " branch is taken, the values are left on the stack and the quotation is called. If the " { $snippet "false" } " branch is taken, the number of inputs inferred from predicate quotation is dropped." } ;

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:"
{ $subsections
    input<sequence
    input<sequence-unsafe
}
"Store all output values to a sequence:"
{ $subsections
    output>sequence
    output>array
}
"Reducing the set of output values:"
{ $subsections
    reduce-outputs
    map-reduce-outputs
}
"Applying a quotation to groups of elements on the stack:"
{ $subsections smart-apply }
"Summing output values:"
{ $subsections sum-outputs }
"Concatenating output values:"
{ $subsections
    append-outputs
    append-outputs-as
}
"Drop the outputs after calling a quotation:"
{ $subsections drop-outputs }
"Cause a quotation to act as a no-op and drop the inputs:"
{ $subsection nullary }
"Preserve the inputs below or above the outputs of the quotation:"
{ $subsections preserving keep-inputs }
"Versions of if that infer how many inputs to keep from the predicate quotation:"
{ $subsections smart-if smart-when smart-unless }
"Versions of if* that infer how many inputs to keep from the predicate quotation:"
{ $subsections smart-if* smart-when* smart-unless* }
"New smart combinators can be created by defining " { $link "macros" } " which call " { $link infer } "." ;

ABOUT: "combinators.smart"

{'fraction_non_alphanumeric': 0.12767478678310606, 'fraction_numerical': 0.006332669424442061, 'mean_word_length': 3.167269631836561, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1873977', 'n_tokens_mistral': 6247, 'n_tokens_neox': 5866, 'n_words': 2267}