1 USING: help.markup help.syntax quotations kernel ;
\r
5 { $description "Fry specifier. Inserts a literal value into the fried quotation." } ;
\r
8 { $description "Fry specifier. Splices a quotation into the fried quotation." } ;
\r
11 { $values { "quot" quotation } { "quot'" quotation } }
\r
12 { $description "Outputs a quotation that when called, fries " { $snippet "quot" } " by taking values from the stack and substituting them in." }
\r
13 { $notes "This word is used to implement " { $link POSTPONE: '[ } "; the following two lines are equivalent:"
\r
14 { $code "[ X ] fry call" "'[ X ]" }
\r
18 { $syntax "'[ code... ]" }
\r
19 { $description "Literal fried quotation. Expands into code which takes values from the stack and substitutes them in place of the fry specifiers " { $link _ } " and " { $link @ } "." }
\r
20 { $examples "See " { $link "fry.examples" } "." } ;
\r
22 HELP: >r/r>-in-fry-error
\r
23 { $error-description "Thrown by " { $link POSTPONE: '[ } " if the fried quotation contains calls to retain stack manipulation primitives." } ;
\r
25 ARTICLE: "fry.examples" "Examples of fried quotations"
\r
26 "The easiest way to understand fried quotations is to look at some examples."
\r
28 "If a quotation does not contain any fry specifiers, then " { $link POSTPONE: '[ } " behaves just like " { $link POSTPONE: [ } ":"
\r
29 { $code "{ 10 20 30 } '[ . ] each" }
\r
30 "Occurrences of " { $link _ } " on the left map directly to " { $link curry } ". That is, the following three lines are equivalent:"
\r
32 "{ 10 20 30 } 5 '[ _ + ] map"
\r
33 "{ 10 20 30 } 5 [ + ] curry map"
\r
34 "{ 10 20 30 } [ 5 + ] map"
\r
36 "Occurrences of " { $link _ } " in the middle of a quotation map to more complex quotation composition patterns. The following three lines are equivalent:"
\r
38 "{ 10 20 30 } 5 '[ 3 _ / ] map"
\r
39 "{ 10 20 30 } 5 [ 3 ] swap [ / ] curry compose map"
\r
40 "{ 10 20 30 } [ 3 5 / ] map"
\r
42 "Occurrences of " { $link @ } " are simply syntax sugar for " { $snippet "_ call" } ". The following four lines are equivalent:"
\r
44 "{ 10 20 30 } [ sq ] '[ @ . ] each"
\r
45 "{ 10 20 30 } [ sq ] [ call . ] curry each"
\r
46 "{ 10 20 30 } [ sq ] [ . ] compose each"
\r
47 "{ 10 20 30 } [ sq . ] each"
\r
49 "The " { $link _ } " and " { $link @ } " specifiers may be freely mixed, and the result is considerably more concise and readable than the version using " { $link curry } " and " { $link compose } " directly:"
\r
51 "{ 8 13 14 27 } [ even? ] 5 '[ @ dup _ ? ] map"
\r
52 "{ 8 13 14 27 } [ even? ] 5 [ dup ] swap [ ? ] curry compose compose map"
\r
53 "{ 8 13 14 27 } [ even? dup 5 ? ] map"
\r
55 "The following is a no-op:"
\r
57 "Here are some built-in combinators rewritten in terms of fried quotations:"
\r
59 { { $link literalize } { $snippet ": literalize '[ _ ] ;" } }
\r
60 { { $link slip } { $snippet ": slip '[ @ _ ] call ;" } }
\r
61 { { $link curry } { $snippet ": curry '[ _ @ ] ;" } }
\r
62 { { $link compose } { $snippet ": compose '[ @ @ ] ;" } }
\r
63 { { $link bi@ } { $snippet ": bi@ tuck '[ _ @ _ @ ] call ;" } }
\r
66 ARTICLE: "fry.philosophy" "Fried quotation philosophy"
\r
67 "Fried quotations generalize quotation-building words such as " { $link curry } " and " { $link compose } ". They can clean up code with lots of currying and composition, particularly when quotations are nested:"
\r
69 "'[ [ _ key? ] all? ] filter"
\r
70 "[ [ key? ] curry all? ] curry filter"
\r
72 "There is a mapping from fried quotations to lexical closures as defined in the " { $vocab-link "locals" } " vocabulary. Namely, a fried quotation is equivalent to a ``let'' form where each local binding is only used once, and bindings are used in the same order in which they are defined. The following two lines are equivalent:"
\r
75 "[let | a [ ] b [ ] | [ 3 a + 4 b / ] ]"
\r
78 ARTICLE: "fry" "Fried quotations"
\r
79 "The " { $vocab-link "fry" } " vocabulary implements " { $emphasis "fried quotation" } ". Conceptually, fried quotations are quotations with ``holes'' (more formally, " { $emphasis "fry specifiers" } "), and the holes are filled in when the fried quotation is pushed on the stack."
\r
81 "Fried quotations are started by a special parsing word:"
\r
82 { $subsection POSTPONE: '[ }
\r
83 "There are two types of fry specifiers; the first can hold a value, and the second ``splices'' a quotation, as if it were inserted without surrounding brackets:"
\r
86 "The holes are filled in with the top of stack going in the rightmost hole, the second item on the stack going in the second hole from the right, and so on."
\r
87 { $subsection "fry.examples" }
\r
88 { $subsection "fry.philosophy" }
\r
89 "Fry is implemented as a parsing word which reads a quotation and scans for occurrences of " { $link _ } " and " { $link @ } "; these words are not actually executed, and doing so raises an error (this can happen if they're accidentally used outside of a fry)."
\r
91 "Fried quotations can also be constructed without using a parsing word; this is useful when meta-programming:"
\r
93 "Fried quotations are an abstraction on top of the " { $link "compositional-combinators" } "; their use is encouraged over the combinators, because often the fry form is shorter and clearer than the combinator form." ;
\r