+HELP: bi-curry
+{ $values { "x" object } { "p" { $quotation "( x -- ... )" } } { "q" { $quotation "( x -- ... )" } } { "p'" { $snippet "[ x p ]" } } { "q'" { $snippet "[ x q ]" } } }
+{ $description "Partially applies " { $snippet "p" } " and " { $snippet "q" } " to " { $snippet "x" } "." }
+{ $notes
+ "The following two lines are equivalent:"
+ { $code
+ "[ p ] [ q ] bi-curry [ call ] bi@"
+ "[ p ] [ q ] bi"
+ }
+ "Higher-arity variants of " { $link bi } " can be built from " { $link bi-curry } ":"
+ { $code
+ "[ p ] [ q ] bi-curry bi == [ p ] [ q ] 2bi"
+ "[ p ] [ q ] bi-curry bi-curry bi == [ p ] [ q ] 3bi"
+ }
+ "The combination " { $snippet "bi-curry bi*" } " cannot be expressed with the non-currying dataflow combinators alone; it is equivalent to a stack shuffle preceding " { $link 2bi* } ":"
+ { $code
+ "[ p ] [ q ] bi-curry bi*"
+ "[ swap ] keep [ p ] [ q ] 2bi*"
+ }
+ "To put it another way, " { $snippet "bi-curry bi*" } " handles the case where you have three values " { $snippet "a b c" } " on the stack, and you wish to apply " { $snippet "p" } " to " { $snippet "a c" } " and " { $snippet "q" } " to " { $snippet "b c" } "."
+} ;
+
+HELP: tri-curry
+{ $values
+ { "x" object }
+ { "p" { $quotation "( x -- ... )" } }
+ { "q" { $quotation "( x -- ... )" } }
+ { "r" { $quotation "( x -- ... )" } }
+ { "p'" { $snippet "[ x p ]" } }
+ { "q'" { $snippet "[ x q ]" } }
+ { "r'" { $snippet "[ x r ]" } }
+}
+{ $description "Partially applies " { $snippet "p" } ", " { $snippet "q" } " and " { $snippet "r" } " to " { $snippet "x" } "." }
+{ $notes
+ "The following two lines are equivalent:"
+ { $code
+ "[ p ] [ q ] [ r ] tri-curry [ call ] tri@"
+ "[ p ] [ q ] [ r ] tri"
+ }
+ "Higher-arity variants of " { $link tri } " can be built from " { $link tri-curry } ":"
+ { $code
+ "[ p ] [ q ] [ r ] tri-curry tri == [ p ] [ q ] [ r ] 2tri"
+ "[ p ] [ q ] [ r ] tri-curry tri-curry bi == [ p ] [ q ] [ r ] 3tri"
+ }
+ "The combination " { $snippet "tri-curry tri*" } " cannot be expressed with the non-currying dataflow combinators alone; it handles the case where you have four values " { $snippet "a b c d" } " on the stack, and you wish to apply " { $snippet "p" } " to " { $snippet "a d" } ", " { $snippet "q" } " to " { $snippet "b d" } " and " { $snippet "r" } " to " { $snippet "c d" } "." } ;
+
+HELP: bi-curry*
+{ $values { "x" object } { "y" object } { "p" { $quotation "( x -- ... )" } } { "q" { $quotation "( y -- ... )" } } { "p'" { $snippet "[ x p ]" } } { "q'" { $snippet "[ y q ]" } } }
+{ $description "Partially applies " { $snippet "p" } " to " { $snippet "x" } ", and " { $snippet "q" } " to " { $snippet "y" } "." }
+{ $notes
+ "The following two lines are equivalent:"
+ { $code
+ "[ p ] [ q ] bi-curry* [ call ] bi@"
+ "[ p ] [ q ] bi*"
+ }
+ "The combination " { $snippet "bi-curry* bi" } " is equivalent to a stack shuffle preceding " { $link 2bi* } ":"
+ { $code
+ "[ p ] [ q ] bi-curry* bi"
+ "[ over ] dip [ p ] [ q ] 2bi*"
+ }
+ "In other words, " { $snippet "bi-curry* bi" } " handles the case where you have the three values " { $snippet "a b c" } " on the stack, and you wish to apply " { $snippet "p" } " to " { $snippet "a b" } " and " { $snippet "q" } " to " { $snippet "a c" } "."
+ $nl
+ "The combination " { $snippet "bi-curry* bi*" } " is equivalent to a stack shuffle preceding " { $link 2bi* } ":"
+ { $code
+ "[ p ] [ q ] bi-curry* bi*"
+ "[ swap ] dip [ p ] [ q ] 2bi*"
+ }
+ "In other words, " { $snippet "bi-curry* bi*" } " handles the case where you have the four values " { $snippet "a b c d" } " on the stack, and you wish to apply " { $snippet "p" } " to " { $snippet "a c" } " and " { $snippet "q" } " to " { $snippet "b d" } "."
+
+} ;
+
+HELP: tri-curry*
+{ $values
+ { "x" object }
+ { "y" object }
+ { "z" object }
+ { "p" { $quotation "( x -- ... )" } }
+ { "q" { $quotation "( y -- ... )" } }
+ { "r" { $quotation "( z -- ... )" } }
+ { "p'" { $snippet "[ x p ]" } }
+ { "q'" { $snippet "[ y q ]" } }
+ { "r'" { $snippet "[ z r ]" } }
+}
+{ $description "Partially applies " { $snippet "p" } " to " { $snippet "x" } ", " { $snippet "q" } " to " { $snippet "y" } " and " { $snippet "r" } " to " { $snippet "z" } "." }
+{ $notes
+ "The following two lines are equivalent:"
+ { $code
+ "[ p ] [ q ] [ r ] tri-curry* [ call ] tri@"
+ "[ p ] [ q ] [ r ] tri*"
+ }
+ "The combination " { $snippet "tri-curry* tri" } " is equivalent to a stack shuffle preceding " { $link 2tri* } ":"
+ { $code
+ "[ p ] [ q ] [ r ] tri-curry* tri"
+ "[ [ over ] dip over ] dip [ p ] [ q ] [ r ] 2tri*"
+ }
+} ;
+
+HELP: bi-curry@
+{ $values { "x" object } { "y" object } { "q" { $quotation "( obj -- ... )" } } { "p'" { $snippet "[ x q ]" } } { "q'" { $snippet "[ y q ]" } } }
+{ $description "Partially applies " { $snippet "q" } " to " { $snippet "x" } " and " { $snippet "y" } "." }
+{ $notes
+ "The following two lines are equivalent:"
+ { $code
+ "[ q ] bi-curry@"
+ "[ q ] [ q ] bi-curry*"
+ }
+} ;
+
+HELP: tri-curry@
+{ $values
+ { "x" object }
+ { "y" object }
+ { "z" object }
+ { "q" { $quotation "( obj -- ... )" } }
+ { "p'" { $snippet "[ x q ]" } }
+ { "q'" { $snippet "[ y q ]" } }
+ { "r'" { $snippet "[ z q ]" } }
+}
+{ $description "Partially applies " { $snippet "q" } " to " { $snippet "x" } ", " { $snippet "y" } " and " { $snippet "z" } "." }
+{ $notes
+ "The following two lines are equivalent:"
+ { $code
+ "[ q ] tri-curry@"
+ "[ q ] [ q ] [ q ] tri-curry*"
+ }
+} ;
+