]> gitweb.factorcode.org Git - factor.git/commitdiff
Documentation improvements
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Tue, 17 Feb 2009 10:57:02 +0000 (04:57 -0600)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Tue, 17 Feb 2009 10:57:02 +0000 (04:57 -0600)
core/kernel/kernel-docs.factor
core/make/make-docs.factor

index da79a928ad571a7582c972f8aaba621b26f57eaa..c83dbfbc21119b205544e06c28ac65aff8c349c1 100644 (file)
@@ -447,7 +447,7 @@ HELP: 2tri@
 
 HELP: bi-curry
 { $values { "x" object } { "p" { $quotation "( x -- ... )" } } { "q" { $quotation "( x -- ... )" } } { "p'" { $snippet "[ x p ]" } } { "q'" { $snippet "[ x q ]" } } }
-{ $description "Curries " { $snippet "x" } " onto " { $snippet "p" } " and " { $snippet "q" } "." }
+{ $description "Partially applies " { $snippet "p" } " and " { $snippet "q" } " to " { $snippet "x" } "." }
 { $notes
   "The following two lines are equivalent:"
   { $code
@@ -477,7 +477,7 @@ HELP: tri-curry
   { "q'" { $snippet "[ x q ]" } }
   { "r'" { $snippet "[ x r ]" } }
 }
-{ $description "Curries " { $snippet "x" } " onto " { $snippet "p" } ", " { $snippet "q" } " and " { $snippet "q" } "." }
+{ $description "Partially applies " { $snippet "p" } ", " { $snippet "q" } " and " { $snippet "r" } " to " { $snippet "x" } "." }
 { $notes
   "The following two lines are equivalent:"
   { $code
@@ -493,7 +493,7 @@ HELP: tri-curry
 
 HELP: bi-curry*
 { $values { "x" object } { "y" object } { "p" { $quotation "( x -- ... )" } } { "q" { $quotation "( y -- ... )" } } { "p'" { $snippet "[ x p ]" } } { "q'" { $snippet "[ y q ]" } } }
-{ $description "Curries " { $snippet "x" } " onto " { $snippet "p" } ", and " { $snippet "y" } " onto " { $snippet "q" } "." }
+{ $description "Partially applies " { $snippet "p" } " to " { $snippet "x" } ", and " { $snippet "q" } " to " { $snippet "y" } "." }
 { $notes
   "The following two lines are equivalent:"
   { $code
@@ -519,14 +519,58 @@ HELP: bi-curry*
 HELP: tri-curry*
 { $values
   { "x" object }
+  { "y" object }
+  { "z" object }
   { "p" { $quotation "( x -- ... )" } }
-  { "q" { $quotation "( x -- ... )" } }
-  { "r" { $quotation "( x -- ... )" } }
+  { "q" { $quotation "( y -- ... )" } }
+  { "r" { $quotation "( z -- ... )" } }
   { "p'" { $snippet "[ x p ]" } }
-  { "q'" { $snippet "[ x q ]" } }
-  { "r'" { $snippet "[ x r ]" } }
+  { "q'" { $snippet "[ y q ]" } }
+  { "r'" { $snippet "[ z r ]" } }
 }
-{ $description "Curries " { $snippet "x" } " onto " { $snippet "p" } ", " { $snippet "q" } " and " { $snippet "q" } "." } ;
+{ $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*"
+  }
+} ;
 
 HELP: if
 { $values { "?" "a generalized boolean" } { "true" quotation } { "false" quotation } }
@@ -945,17 +989,49 @@ ARTICLE: "curried-dataflow" "Curried dataflow combinators"
 { $subsection tri-curry@ }
 { $see-also "dataflow-combinators" } ;
 
+ARTICLE: "compositional-examples" "Examples of compositional combinator usage"
+"Consider printing the same message ten times:"
+{ $code ": print-10 ( -- ) 10 [ \"Hello, world.\" print ] times ;" }
+"if we wanted to abstract out the message into a parameter, we could keep it on the stack between iterations:"
+{ $code ": print-10 ( message -- ) 10 [ dup print ] times drop ;" }
+"However, keeping loop-invariant values on the stack doesn't always work out nicely. For example, a word to subtract a value from each element of a sequence:"
+{ $code ": subtract-n ( seq n -- seq' ) swap [ over - ] map nip ;" }
+"Three shuffle words are required to pass the value around. Instead, the loop-invariant value can be partially applied to a quotation using " { $link curry } ", yielding a new quotation that is passed to " { $link map } ":"
+{ $example
+  "USING: kernel math prettyprint sequences ;"
+  ": subtract-n ( seq n -- seq' ) [ - ] curry map ;"
+  "{ 10 20 30 } 5 subtract-n ."
+  "{ 5 15 25 }"
+}
+"Now consider the word that is dual to the one above; instead of subtracting " { $snippet "n" } " from each stack element, it subtracts each element from " { $snippet "n" } "."
+$nl
+"One way to write this is with a pair of " { $link swap } "s:"
+{ $code ": n-subtract ( n seq -- seq' ) swap [ swap - ] curry map ;" }
+"Since this pattern comes up often, " { $link with } " encapsulates it:"
+{ $example
+  "USING: kernel math prettyprint sequences ;"
+  ": n-subtract ( n seq -- seq' ) [ - ] with map ;"
+  "30 { 10 20 30 } n-subtract ."
+  "{ 20 10 0 }"
+}
+{ $see-also "fry.examples" } ;
+
 ARTICLE: "compositional-combinators" "Compositional combinators"
-"Quotations can be composed using efficient quotation-specific operations:"
+"Certain combinators transform quotations to produce a new quotation."
+{ $subsection "compositional-examples" }
+"Fundamental operations:"
 { $subsection curry }
+{ $subsection compose }
+"Derived operations:"
 { $subsection 2curry }
 { $subsection 3curry }
 { $subsection with }
-{ $subsection compose }
 { $subsection prepose }
+"These operations run in constant time, and in many cases are optimized out altogether by the " { $link "compiler" } ". " { $link "fry" } " are an abstraction built on top of these operations, and code that uses this abstraction is often clearer than direct calls to the below words."
+$nl
 "Curried dataflow combinators can be used to build more complex dataflow by combining cleave, spread and apply patterns in various ways."
 { $subsection "curried-dataflow" }
-"Quotations also implement the sequence protocol, and can be manipulated with sequence words; see " { $link "quotations" } "." ;
+"Quotations also implement the sequence protocol, and can be manipulated with sequence words; see " { $link "quotations" } ". However, such runtime quotation manipulation will not be optimized by the optimizing compiler." ;
 
 ARTICLE: "implementing-combinators" "Implementing combinators"
 "The following pair of words invoke words and quotations reflectively:"
index 269f4fb26bbf4c18a384a4a81c2f84b3052f2202..9c309e2f5e7118a8164d23bbed66557723b184c1 100644 (file)
@@ -2,14 +2,57 @@ IN: make
 USING: help.markup help.syntax quotations sequences math.parser
 kernel ;
 
+ARTICLE: "make-philosophy" "Make philosophy"
+{ $heading "When to use make" }
+"Make is useful for complex sequence construction which is hard to express with sequence combinators and various combinations of utility words."
+$nl
+"For example, this example uses " { $link make } " and reads better than a version using utility words:"
+{ $code "[ [ left>> , ] [ \"+\" % center>> % \"-\" % ] [ right , ] tri ] { } make" }
+"compare the above to"
+{ $code "[ center>> \"+\" \"-\" surround ] [ left>> prefix ] [ right suffix ] tri" }
+"The first one has a similar shape to the eventual output array. The second one has an arbitrary structure and uses three different utilities. Furthermore, the second version also constructs two redundant intermediate sequences, and for longer sequences, this extra copying will outweigh any overhead " { $link make } " has due to its use of a dynamic variable to store the sequence being built."
+$nl
+"On the other hand, using " { $link make } " instead of a single call to " { $link surround } " is overkill. The below headings summarize the most important cases where other idioms are more appropriate than " { $link make } "."
+{ $heading "Make versus combinators" }
+"Sometimes, usages of " { $link make } " are better expressed with " { $link "sequences-combinators" } ". For example, instead of calling a combinator with a quotation which executes " { $link , } " exactly once on each iteration, oftena combinator encapsulating that specific idiom exists and can be used."
+$nl
+"For example,"
+{ $code "[ [ 42 * , ] each ] { } make" }
+"is equivalent to"
+{ $code "[ 42 * ] map" }
+"and"
+{ $code "[ [ reverse % ] each ] \"\" make" }
+"is equivalent to"
+{ $code "[ [ reverse ] map concat" }
+{ $heading "Utilities for simple make patterns" }
+"Sometimes, an existing word already implements a specific " { $link make } " usage. For example, " { $link suffix } " is equivalent to the following, with the added caveat that the below example always outputs an array:"
+{ $code "[ , % ] { } make" }
+"The existing utility words can in some cases express intent better than an arbitrary-looking string or " { $link , } " and " { $link % } "."
+{ $heading "Constructing quotations" }
+"Simple quotation construction can often be accomplished using " { $link "fry" } " and " { $link "compositional-combinators" } "."
+$nl
+"For example,"
+{ $code "[ 2 , , \ + , ] [ ] make" }
+"is better expressed as"
+{ $code "'[ 2 _ + ]" } ;
+
 ARTICLE: "namespaces-make" "Making sequences with variables"
 "The " { $vocab-link "make" } " vocabulary implements a facility for constructing sequences by holding an accumulator sequence in a variable. Storing the accumulator sequence in a variable rather than the stack may allow code to be written with less stack manipulation."
+$nl
+"Sequence construction is wrapped in a combinator:"
 { $subsection make }
+"Inside the quotation passed to " { $link make } ", several words accumulate values:"
 { $subsection , }
 { $subsection % }
 { $subsection # }
-"The accumulator sequence can be accessed directly:"
-{ $subsection building } ;
+"The accumulator sequence can be accessed directly from inside a " { $link make } ":"
+{ $subsection building }
+{ $example
+  "USING: make math.parser io ;"
+  "[ \"Language #\" % CHAR: \s , 5 # ] \"\" make print"
+  "Language #5"
+}
+{ $subsection "make-philosophy" } ;
 
 ABOUT: "namespaces-make"
 
@@ -27,4 +70,4 @@ HELP: ,
 
 HELP: %
 { $values { "seq" sequence } }
-{ $description "Appends a sequence to the end of the sequence being constructed by " { $link make } "." } ;
+{ $description "Appends a sequence to the end of the sequence being constructed by " { $link make } "." } ;
\ No newline at end of file