From: Slava Pestov Date: Mon, 6 Apr 2009 08:00:46 +0000 (-0500) Subject: Documentation updates X-Git-Tag: 0.94~2165^2~29 X-Git-Url: https://gitweb.factorcode.org/gitweb.cgi?p=factor.git;a=commitdiff_plain;h=99b8400e56e23584db5544e3b3cb64357721ec31 Documentation updates --- diff --git a/basis/alien/syntax/tags.txt b/basis/alien/syntax/tags.txt new file mode 100644 index 0000000000..f4274299b1 --- /dev/null +++ b/basis/alien/syntax/tags.txt @@ -0,0 +1 @@ +extensions diff --git a/basis/combinators/short-circuit/smart/tags.txt b/basis/combinators/short-circuit/smart/tags.txt new file mode 100644 index 0000000000..f4274299b1 --- /dev/null +++ b/basis/combinators/short-circuit/smart/tags.txt @@ -0,0 +1 @@ +extensions diff --git a/basis/combinators/short-circuit/tags.txt b/basis/combinators/short-circuit/tags.txt new file mode 100644 index 0000000000..f4274299b1 --- /dev/null +++ b/basis/combinators/short-circuit/tags.txt @@ -0,0 +1 @@ +extensions diff --git a/basis/combinators/smart/smart-docs.factor b/basis/combinators/smart/smart-docs.factor index 75f83c1a55..679b587759 100644 --- a/basis/combinators/smart/smart-docs.factor +++ b/basis/combinators/smart/smart-docs.factor @@ -108,17 +108,19 @@ HELP: append-outputs-as ARTICLE: "combinators.smart" "Smart combinators" -"The " { $vocab-link "combinators.smart" } " vocabulary implements " { $emphasis "smart combinators" } ". A smart combinator is one whose behavior depends on the static stack effect of an input quotation." $nl -"Smart inputs from a sequence:" +"The macros in the " { $vocab-link "combinators.smart" } " vocabulary look at the static stack effects of input quotations and generate code which produces or consumes the relevant number of stack values." $nl +"Call a quotation and discard all output values:" +{ $subsection drop-outputs } +"Take all input values from a sequence:" { $subsection inputsequence } { $subsection output>array } -"Reducing the output of a quotation:" +"Reducing the set of output values:" { $subsection reduce-outputs } -"Summing the output of a quotation:" +"Summing output values:" { $subsection sum-outputs } -"Appending the results of a quotation:" +"Concatenating output values:" { $subsection append-outputs } { $subsection append-outputs-as } ; diff --git a/basis/combinators/smart/tags.txt b/basis/combinators/smart/tags.txt new file mode 100644 index 0000000000..f4274299b1 --- /dev/null +++ b/basis/combinators/smart/tags.txt @@ -0,0 +1 @@ +extensions diff --git a/basis/help/cookbook/cookbook.factor b/basis/help/cookbook/cookbook.factor index 2cc19f87dd..867f373209 100644 --- a/basis/help/cookbook/cookbook.factor +++ b/basis/help/cookbook/cookbook.factor @@ -117,7 +117,7 @@ $nl } { $references { "Since quotations are objects, they can be constructed and taken apart at will. You can write code that writes code. Arrays are just one of the various types of sequences, and the sequence operations such as " { $link each } " and " { $link map } " operate on all types of sequences. There are many more sequence iteration operations than the ones above, too." } - "dataflow" + "combinators" "sequences" } ; diff --git a/basis/help/handbook/handbook.factor b/basis/help/handbook/handbook.factor index ed2a14a2f2..b2a0e56c0a 100644 --- a/basis/help/handbook/handbook.factor +++ b/basis/help/handbook/handbook.factor @@ -5,7 +5,7 @@ math system strings sbufs vectors byte-arrays quotations io.streams.byte-array classes.builtin parser lexer classes.predicate classes.union classes.intersection classes.singleton classes.tuple help.vocabs math.parser -accessors ; +accessors definitions ; IN: help.handbook ARTICLE: "conventions" "Conventions" @@ -49,7 +49,7 @@ $nl { "associative mapping" { "an object whose class implements the " { $link "assocs-protocol" } } } { "boolean" { { $link t } " or " { $link f } } } { "class" { "a set of objects identified by a " { $emphasis "class word" } " together with a discriminating predicate. See " { $link "classes" } } } - { "definition specifier" { "a " { $link word } ", " { $link method-spec } ", " { $link link } ", vocabulary specifier, or any other object whose class implements the " { $link "definition-protocol" } } } + { "definition specifier" { "an instance of " { $link definition } " which implements the " { $link "definition-protocol" } } } { "generalized boolean" { "an object interpreted as a boolean; a value of " { $link f } " denotes false and anything else denotes true" } } { "generic word" { "a word whose behavior depends can be specialized on the class of one of its inputs. See " { $link "generic" } } } { "method" { "a specialized behavior of a generic word on a class. See " { $link "generic" } } } @@ -70,7 +70,7 @@ ARTICLE: "tail-call-opt" "Tail-call optimization" $nl "Tail-call optimization allows iterative algorithms to be implemented in an efficient manner using recursion, without the need for any kind of primitive looping construct in the language. However, in practice, most iteration is performed via combinators such as " { $link while } ", " { $link each } ", " { $link map } ", " { $link assoc-each } ", and so on. The definitions of these combinators do bottom-out in recursive words, however." ; -ARTICLE: "evaluator" "Evaluation semantics" +ARTICLE: "evaluator" "Stack machine model" { $link "quotations" } " are evaluated sequentially from beginning to end. When the end is reached, the quotation returns to its caller. As each object in the quotation is evaluated in turn, an action is taken based on its type:" { $list { "a " { $link word } " - the word's definition quotation is called. See " { $link "words" } } @@ -84,12 +84,13 @@ ARTICLE: "objects" "Objects" "An " { $emphasis "object" } " is any datum which may be identified. All values are objects in Factor. Each object carries type information, and types are checked at runtime; Factor is dynamically typed." { $subsection "equality" } { $subsection "math.order" } -{ $subsection "destructors" } { $subsection "classes" } { $subsection "tuples" } { $subsection "generic" } -{ $subsection "slots" } -{ $subsection "mirrors" } ; +"Advanced features:" +{ $subsection "delegate" } +{ $subsection "mirrors" } +{ $subsection "slots" } ; ARTICLE: "numbers" "Numbers" { $subsection "arithmetic" } @@ -118,9 +119,9 @@ ARTICLE: "collections" "Collections" "Fixed-length sequences:" { $subsection "arrays" } { $subsection "quotations" } -"Fixed-length specialized sequences:" { $subsection "strings" } { $subsection "byte-arrays" } +{ $subsection "specialized-arrays" } "Resizable sequences:" { $subsection "vectors" } { $subsection "byte-vectors" } @@ -128,7 +129,8 @@ ARTICLE: "collections" "Collections" { $subsection "growable" } { $heading "Associative mappings" } { $subsection "assocs" } -{ $subsection "namespaces" } +{ $subsection "linked-assocs" } +{ $subsection "biassocs" } { $subsection "refs" } "Implementations:" { $subsection "hashtables" } @@ -140,26 +142,29 @@ ARTICLE: "collections" "Collections" { $subsection "dlists" } { $subsection "search-deques" } { $heading "Other collections" } -{ $subsection "boxes" } +{ $subsection "lists" } +{ $subsection "disjoint-sets" } +{ $subsection "interval-maps" } { $subsection "heaps" } +{ $subsection "boxes" } { $subsection "graphs" } { $subsection "buffers" } "There are also many other vocabularies tagged " { $link T{ vocab-tag { name "collections" } } } " in the library." ; -USING: io.encodings.utf8 io.encodings.utf16 io.encodings.binary io.encodings.ascii io.files ; +USING: io.encodings.utf8 io.encodings.binary io.files ; ARTICLE: "encodings-introduction" "An introduction to encodings" "In order to express text in terms of binary, some sort of encoding has to be used. In a modern context, this is understood as a two-way mapping between Unicode code points (characters) and some amount of binary. Since English isn't the only language in the world, ASCII is not sufficient as a mapping from binary to Unicode; it can't even express em-dashes or curly quotes. Unicode was designed as a universal character set that could potentially represent everything." $nl "Not all encodings can represent all Unicode code points, but Unicode can represent basically everything that exists in modern encodings. Some encodings are language-specific, and some can represent everything in Unicode. Though the world is moving toward Unicode and UTF-8, the reality today is that there are several encodings which must be taken into account." $nl -"Factor uses a system of encoding descriptors to denote encodings. Encoding descriptors are objects which describe encodings. Examples are " { $link utf8 } ", " { $link ascii } " and " { $link binary } ". Encoding descriptors can be passed around independently. Each encoding descriptor has some method for constructing an encoded or decoded stream, and the resulting stream has an encoding descriptor stored which has methods for reading or writing characters." $nl +"Factor uses a system of encoding descriptors to denote encodings. Encoding descriptors are objects which describe encodings. Examples are " { $link utf8 } " and " { $link binary } ". Encoding descriptors can be passed around independently. Each encoding descriptor has some method for constructing an encoded or decoded stream, and the resulting stream has an encoding descriptor stored which has methods for reading or writing characters." $nl "Constructors for streams which deal with bytes usually take an encoding as an explicit parameter. For example, to open a text file for reading whose contents are in UTF-8, use the following" { $code "\"file.txt\" utf8 " } "If there is an error in the encoded stream, a replacement character (0xFFFD) will be inserted. To throw an exception upon error, use a strict encoding as follows" { $code "\"file.txt\" utf8 strict " } "In a similar way, encodings can be specified when opening a file for writing." -{ $code "\"file.txt\" ascii " } +{ $code "USE: io.encodings.ascii" "\"file.txt\" ascii " } "An encoding is also needed for some words that don't return streams, such as " { $link file-contents } ", for example" -{ $code "\"file.txt\" utf16 file-contents" } +{ $code "USE: io.encodings.utf16" "\"file.txt\" utf16 file-contents" } "Encoding descriptors are also used by " { $link "io.streams.byte-array" } " and taken by combinators like " { $link with-file-writer } " and " { $link with-byte-reader } " which deal with streams. It is " { $emphasis "not" } " used with " { $link "io.streams.string" } " because these deal with abstract text." $nl "When the " { $link binary } " encoding is used, a " { $link byte-array } " is expected for writing and returned for reading, since the stream deals with bytes. All other encodings deal with strings, since they are used to represent text." ; @@ -239,40 +244,57 @@ ARTICLE: "class-index" "Class index" { $heading "Predicate classes" } { $index [ classes [ predicate-class? ] filter ] } ; -ARTICLE: "program-org" "Program organization" -{ $subsection "definitions" } -{ $subsection "vocabularies" } -{ $subsection "parser" } -{ $subsection "vocabs.loader" } -{ $subsection "source-files" } ; - USING: help.cookbook help.tutorial ; ARTICLE: "handbook-language-reference" "Language reference" +"Fundamentals:" { $subsection "conventions" } { $subsection "syntax" } -{ $subsection "dataflow" } -{ $subsection "objects" } -{ $subsection "program-org" } +{ $subsection "effects" } +"Data types:" +{ $subsection "booleans" } { $subsection "numbers" } { $subsection "collections" } -{ $subsection "io" } +"Evaluation semantics:" +{ $subsection "evaluator" } +{ $subsection "words" } +{ $subsection "shuffle-words" } +{ $subsection "combinators" } +{ $subsection "errors" } +{ $subsection "continuations" } +"Named values:" +{ $subsection "locals" } +{ $subsection "namespaces" } +{ $subsection "namespaces-global" } +{ $subsection "values" } +"Abstractions:" +{ $subsection "objects" } +{ $subsection "destructors" } +{ $subsection "macros" } +{ $subsection "fry" } +"Program organization:" +{ $subsection "vocabs.loader" } "Vocabularies tagged " { $link T{ vocab-tag { name "extensions" } } } " implement various additional language abstractions." ; ARTICLE: "handbook-environment-reference" "Environment reference" +"Parse time and compile time:" +{ $subsection "parser" } +{ $subsection "definitions" } +{ $subsection "vocabularies" } +{ $subsection "source-files" } +{ $subsection "compiler" } +"Tools:" { $subsection "prettyprint" } { $subsection "tools" } -{ $subsection "cli" } -{ $subsection "rc-files" } { $subsection "help" } { $subsection "inference" } -{ $subsection "compiler" } -{ $subsection "system" } { $subsection "images" } -{ $subsection "alien" } +"VM:" +{ $subsection "cli" } +{ $subsection "rc-files" } { $subsection "init" } -{ $subsection "layouts" } -{ $see-also "program-org" } ; +{ $subsection "system" } +{ $subsection "layouts" } ; ARTICLE: "handbook-library-reference" "Library reference" "This index only includes articles from loaded vocabularies. To explore more vocabularies, see " { $link "vocab-index" } "." @@ -282,9 +304,14 @@ ARTICLE: "handbook" "Factor handbook" "Learn the language:" { $subsection "cookbook" } { $subsection "first-program" } +"Reference material:" { $subsection "handbook-language-reference" } { $subsection "handbook-environment-reference" } +{ $subsection "io" } { $subsection "ui" } +{ $subsection "ui-tools" } +{ $subsection "unicode" } +{ $subsection "alien" } { $subsection "handbook-library-reference" } "Explore loaded libraries:" { $subsection "article-index" } diff --git a/basis/help/home/home-docs.factor b/basis/help/home/home-docs.factor index 6608a6e9c0..e6db2d3b9c 100644 --- a/basis/help/home/home-docs.factor +++ b/basis/help/home/home-docs.factor @@ -8,7 +8,6 @@ ARTICLE: "help.home" "Factor documentation" { $link "handbook" } { $link "vocab-index" } { $link "ui-tools" } - { $link "handbook-library-reference" } } { $heading "Recently visited" } { $table diff --git a/basis/help/syntax/tags.txt b/basis/help/syntax/tags.txt new file mode 100644 index 0000000000..f4274299b1 --- /dev/null +++ b/basis/help/syntax/tags.txt @@ -0,0 +1 @@ +extensions diff --git a/basis/interpolate/tags.txt b/basis/interpolate/tags.txt new file mode 100644 index 0000000000..f4274299b1 --- /dev/null +++ b/basis/interpolate/tags.txt @@ -0,0 +1 @@ +extensions diff --git a/basis/locals/locals-docs.factor b/basis/locals/locals-docs.factor index 18dabed4b0..b1f0b6ca17 100644 --- a/basis/locals/locals-docs.factor +++ b/basis/locals/locals-docs.factor @@ -112,7 +112,15 @@ HELP: MEMO:: { $description "Defines a memoized word with named inputs; it reads stack values into bindings from left to right, then executes the body with those bindings in lexical scope." } ; { POSTPONE: MEMO: POSTPONE: MEMO:: } related-words + +HELP: M:: +{ $syntax "M:: class generic ( bindings... -- outputs... ) body... ;" } +{ $description "Defines a method with named inputs; it reads stack values into bindings from left to right, then executes the body with those bindings in lexical scope." } +{ $notes "The output names do not affect the word's behavior, however the compiler attempts to check the stack effect as with other definitions." } ; + +{ POSTPONE: M: POSTPONE: M:: } related-words + ARTICLE: "locals-literals" "Locals in literals" "Certain data type literals are permitted to contain free variables. Any such literals are written into code which constructs an instance of the type with the free variable values spliced in. Conceptually, this is similar to the transformation applied to quotations containing free variables." $nl @@ -237,13 +245,14 @@ $nl } "The reason is that locals are rewritten into stack code at parse time, whereas macro expansion is performed later during compile time. To circumvent this problem, the " { $vocab-link "macros.expander" } " vocabulary is used to rewrite simple macro usages prior to local transformation, however "{ $vocab-link "macros.expander" } " does not deal with more complicated cases where the literal inputs to the macro do not immediately precede the macro call in the source." ; -ARTICLE: "locals" "Local variables and lexical closures" +ARTICLE: "locals" "Lexical variables and closures" "The " { $vocab-link "locals" } " vocabulary implements lexical scope with full closures, both downward and upward. Mutable bindings are supported, including assignment to bindings in outer scope." $nl "Compile-time transformation is used to compile local variables to efficient code; prettyprinter extensions are defined so that " { $link see } " can display original word definitions with local variables and not the closure-converted concatenative code which results." $nl "Applicative word definitions where the inputs are named local variables:" { $subsection POSTPONE: :: } +{ $subsection POSTPONE: M:: } { $subsection POSTPONE: MEMO:: } { $subsection POSTPONE: MACRO:: } "Lexical binding forms:" diff --git a/basis/math/ranges/ranges-docs.factor b/basis/math/ranges/ranges-docs.factor index 8987def80b..e35adb10e5 100644 --- a/basis/math/ranges/ranges-docs.factor +++ b/basis/math/ranges/ranges-docs.factor @@ -2,7 +2,7 @@ USING: help.syntax help.markup arrays sequences ; IN: math.ranges -ARTICLE: "ranges" "Ranges" +ARTICLE: "math.ranges" "Numeric ranges" "A " { $emphasis "range" } " is a virtual sequence with real number elements " "ranging from " { $emphasis "a" } " to " { $emphasis "b" } " by " { $emphasis "step" } ". Ascending as well as descending ranges are supported." $nl @@ -24,4 +24,4 @@ $nl { $code "100 1 [a,b] product" } "A range can be converted into a concrete sequence using a word such as " { $link >array } ". In most cases this is unnecessary since ranges implement the sequence protocol already. It is necessary if a mutable sequence is needed, for use with words such as " { $link set-nth } " or " { $link change-each } "." ; -ABOUT: "ranges" \ No newline at end of file +ABOUT: "math.ranges" \ No newline at end of file diff --git a/basis/peg/ebnf/tags.txt b/basis/peg/ebnf/tags.txt index 5af5dba748..1ccdafb2bb 100644 --- a/basis/peg/ebnf/tags.txt +++ b/basis/peg/ebnf/tags.txt @@ -1,2 +1,3 @@ +extensions text parsing diff --git a/basis/ui/tools/tools-docs.factor b/basis/ui/tools/tools-docs.factor index 93f45591a5..52cd77d726 100644 --- a/basis/ui/tools/tools-docs.factor +++ b/basis/ui/tools/tools-docs.factor @@ -55,7 +55,7 @@ $nl ARTICLE: "ui-tools" "UI developer tools" "The " { $vocab-link "ui.tools" } " vocabulary hierarchy implements a collection of simple developer tools." -$nl +{ $subsection "starting-ui-tools" } "To take full advantage of the UI tools, you should be using a supported text editor. See " { $link "editor" } "." $nl "Common functionality:" @@ -66,7 +66,7 @@ $nl { $subsection "ui-listener" } { $subsection "ui-browser" } { $subsection "ui-inspector" } -{ $subsection "ui-profiler" } +{ $subsection "ui.tools.profiler" } { $subsection "ui-walker" } { $subsection "ui.tools.deploy" } "Platform-specific features:" diff --git a/basis/unicode/unicode-docs.factor b/basis/unicode/unicode-docs.factor index 9450b49f0b..56432585c0 100644 --- a/basis/unicode/unicode-docs.factor +++ b/basis/unicode/unicode-docs.factor @@ -1,7 +1,7 @@ USING: help.markup help.syntax strings ; IN: unicode -ARTICLE: "unicode" "Unicode" +ARTICLE: "unicode" "Unicode support" "The " { $vocab-link "unicode" } " vocabulary and its sub-vocabularies implement support for the Unicode 5.1 character set." $nl "The Unicode character set contains most of the world's writing systems. Unicode is intended as a replacement for, and is a superset of, such legacy character sets as ASCII, Latin1, MacRoman, and so on. Unicode characters are called " { $emphasis "code points" } "; Factor's " { $link "strings" } " are sequences of code points." diff --git a/basis/values/values-docs.factor b/basis/values/values-docs.factor index df38869fbf..7c96f19ac9 100644 --- a/basis/values/values-docs.factor +++ b/basis/values/values-docs.factor @@ -2,7 +2,7 @@ USING: help.markup help.syntax ; IN: values ARTICLE: "values" "Global values" -"Usually, dynamically scoped variables are sufficient for holding data which is not literal. But occasionally, for global information that's calculated just once, it's useful to use the word mechanism instead, and set the word to the appropriate value just once. The " { $vocab-link "values" } " vocabulary implements " { $emphasis "values" } ", which abstract over this concept. To create a new word as a value, use the following syntax:" +"Usually, dynamically-scoped variables subsume global variables and are sufficient for holding global data. But occasionally, for global information that's calculated just once and must be accessed more rapidly than a dynamic variable lookup can provide, it's useful to use the word mechanism instead, and set a word to the appropriate value just once. The " { $vocab-link "values" } " vocabulary implements " { $emphasis "values" } ", which abstract over this concept. To create a new word as a value, use the following syntax:" { $subsection POSTPONE: VALUE: } "To get the value, just call the word. The following words manipulate values:" { $subsection get-value } diff --git a/basis/xml/syntax/tags.txt b/basis/xml/syntax/tags.txt index 71c0ff7282..4f4a20b1cb 100644 --- a/basis/xml/syntax/tags.txt +++ b/basis/xml/syntax/tags.txt @@ -1 +1,2 @@ +extensions syntax diff --git a/core/combinators/combinators-docs.factor b/core/combinators/combinators-docs.factor index cc502140ad..9c96fe34c9 100644 --- a/core/combinators/combinators-docs.factor +++ b/core/combinators/combinators-docs.factor @@ -4,46 +4,313 @@ math assocs sequences sequences.private combinators.private effects words ; IN: combinators +ARTICLE: "cleave-shuffle-equivalence" "Expressing shuffle words with cleave combinators" +"Cleave combinators are defined in terms of shuffle words, and mappings from certain shuffle idioms to cleave combinators are discussed in the documentation for " { $link bi } ", " { $link 2bi } ", " { $link 3bi } ", " { $link tri } ", " { $link 2tri } " and " { $link 3tri } "." +$nl +"Certain shuffle words can also be expressed in terms of the cleave combinators. Internalizing such identities can help with understanding and writing code using cleave combinators:" +{ $code + ": keep [ ] bi ;" + ": 2keep [ ] 2bi ;" + ": 3keep [ ] 3bi ;" + "" + ": dup [ ] [ ] bi ;" + ": 2dup [ ] [ ] 2bi ;" + ": 3dup [ ] [ ] 3bi ;" + "" + ": tuck [ nip ] [ ] 2bi ;" + ": swap [ nip ] [ drop ] 2bi ;" + "" + ": over [ ] [ drop ] 2bi ;" + ": pick [ ] [ 2drop ] 3bi ;" + ": 2over [ ] [ drop ] 3bi ;" +} ; + +ARTICLE: "cleave-combinators" "Cleave combinators" +"The cleave combinators apply multiple quotations to a single value." +$nl +"Two quotations:" +{ $subsection bi } +{ $subsection 2bi } +{ $subsection 3bi } +"Three quotations:" +{ $subsection tri } +{ $subsection 2tri } +{ $subsection 3tri } +"An array of quotations:" +{ $subsection cleave } +{ $subsection 2cleave } +{ $subsection 3cleave } +"Technically, the cleave combinators are redundant because they can be simulated using shuffle words and other combinators, and in addition, they do not reduce token counts by much, if at all. However, they can make code more readable by expressing intention and exploiting any inherent symmetry. For example, a piece of code which performs three operations on the top of the stack can be written in one of two ways:" +{ $code + "! First alternative; uses keep" + "[ 1 + ] keep" + "[ 1 - ] keep" + "2 *" + "! Second alternative: uses tri" + "[ 1 + ]" + "[ 1 - ]" + "[ 2 * ] tri" +} +"The latter is more aesthetically pleasing than the former." +{ $subsection "cleave-shuffle-equivalence" } ; + +ARTICLE: "spread-shuffle-equivalence" "Expressing shuffle words with spread combinators" +"Spread combinators are defined in terms of shuffle words, and mappings from certain shuffle idioms to spread combinators are discussed in the documentation for " { $link bi* } ", " { $link 2bi* } ", " { $link tri* } ", and " { $link 2tri* } "." +$nl +"Certain shuffle words can also be expressed in terms of the spread combinators. Internalizing such identities can help with understanding and writing code using spread combinators:" +{ $code + ": dip [ ] bi* ;" + ": 2dip [ ] [ ] tri* ;" + "" + ": slip [ call ] [ ] bi* ;" + ": 2slip [ call ] [ ] [ ] tri* ;" + "" + ": nip [ drop ] [ ] bi* ;" + ": 2nip [ drop ] [ drop ] [ ] tri* ;" + "" + ": rot" + " [ [ drop ] [ ] [ drop ] tri* ]" + " [ [ drop ] [ drop ] [ ] tri* ]" + " [ [ ] [ drop ] [ drop ] tri* ]" + " 3tri ;" + "" + ": -rot" + " [ [ drop ] [ drop ] [ ] tri* ]" + " [ [ ] [ drop ] [ drop ] tri* ]" + " [ [ drop ] [ ] [ drop ] tri* ]" + " 3tri ;" + "" + ": spin" + " [ [ drop ] [ drop ] [ ] tri* ]" + " [ [ drop ] [ ] [ drop ] tri* ]" + " [ [ ] [ drop ] [ drop ] tri* ]" + " 3tri ;" +} ; + +ARTICLE: "spread-combinators" "Spread combinators" +"The spread combinators apply multiple quotations to multiple values. The " { $snippet "*" } " suffix signifies spreading." +$nl +"Two quotations:" +{ $subsection bi* } +{ $subsection 2bi* } +"Three quotations:" +{ $subsection tri* } +{ $subsection 2tri* } +"An array of quotations:" +{ $subsection spread } +"Technically, the spread combinators are redundant because they can be simulated using shuffle words and other combinators, and in addition, they do not reduce token counts by much, if at all. However, they can make code more readable by expressing intention and exploiting any inherent symmetry. For example, a piece of code which performs three operations on three related values can be written in one of two ways:" +{ $code + "! First alternative; uses dip" + "[ [ 1 + ] dip 1 - ] dip 2 *" + "! Second alternative: uses tri*" + "[ 1 + ] [ 1 - ] [ 2 * ] tri*" +} +"A generalization of the above combinators to any number of quotations can be found in " { $link "combinators" } "." +{ $subsection "spread-shuffle-equivalence" } ; + +ARTICLE: "apply-combinators" "Apply combinators" +"The apply combinators apply a single quotation to multiple values. The " { $snippet "@" } " suffix signifies application." +$nl +"Two quotations:" +{ $subsection bi@ } +{ $subsection 2bi@ } +"Three quotations:" +{ $subsection tri@ } +{ $subsection 2tri@ } +"A pair of utility words built from " { $link bi@ } ":" +{ $subsection both? } +{ $subsection either? } ; + +ARTICLE: "slip-keep-combinators" "Retain stack combinators" +"Sometimes an additional storage area is needed to hold objects. The " { $emphasis "retain stack" } " is an auxilliary stack for this purpose. Objects can be moved between the data and retain stacks using a set of combinators." +$nl +"The dip combinators invoke the quotation at the top of the stack, hiding the values underneath:" +{ $subsection dip } +{ $subsection 2dip } +{ $subsection 3dip } +{ $subsection 4dip } +"The slip combinators invoke a quotation further down on the stack. They are most useful for implementing other combinators:" +{ $subsection slip } +{ $subsection 2slip } +{ $subsection 3slip } +"The keep combinators invoke a quotation which takes a number of values off the stack, and then they restore those values:" +{ $subsection keep } +{ $subsection 2keep } +{ $subsection 3keep } ; + +ARTICLE: "curried-dataflow" "Curried dataflow combinators" +"Curried cleave combinators:" +{ $subsection bi-curry } +{ $subsection tri-curry } +"Curried spread combinators:" +{ $subsection bi-curry* } +{ $subsection tri-curry* } +"Curried apply combinators:" +{ $subsection bi-curry@ } +{ $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" +"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 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" } ". However, such runtime quotation manipulation will not be optimized by the optimizing compiler." ; + +ARTICLE: "booleans" "Booleans" +"In Factor, any object that is not " { $link f } " has a true value, and " { $link f } " has a false value. The " { $link t } " object is the canonical true value." +{ $subsection f } +{ $subsection t } +"There are some logical operations on booleans:" +{ $subsection >boolean } +{ $subsection not } +{ $subsection and } +{ $subsection or } +{ $subsection xor } +"Boolean values are most frequently used for " { $link "conditionals" } "." +{ $heading "The f object and f class" } +"The " { $link f } " object is the unique instance of the " { $link f } " class; the two are distinct objects. The latter is also a parsing word which adds the " { $link f } " object to the parse tree at parse time. To refer to the class itself you must use " { $link POSTPONE: POSTPONE: } " or " { $link POSTPONE: \ } " to prevent the parsing word from executing." +$nl +"Here is the " { $link f } " object:" +{ $example "f ." "f" } +"Here is the " { $link f } " class:" +{ $example "\\ f ." "POSTPONE: f" } +"They are not equal:" +{ $example "f \\ f = ." "f" } +"Here is an array containing the " { $link f } " object:" +{ $example "{ f } ." "{ f }" } +"Here is an array containing the " { $link f } " class:" +{ $example "{ POSTPONE: f } ." "{ POSTPONE: f }" } +"The " { $link f } " object is an instance of the " { $link f } " class:" +{ $example "USE: classes" "f class ." "POSTPONE: f" } +"The " { $link f } " class is an instance of " { $link word } ":" +{ $example "USE: classes" "\\ f class ." "word" } +"On the other hand, " { $link t } " is just a word, and there is no class which it is a unique instance of." +{ $example "t \\ t eq? ." "t" } +"Many words which search collections confuse the case of no element being present with an element being found equal to " { $link f } ". If this distinction is imporant, there is usually an alternative word which can be used; for example, compare " { $link at } " with " { $link at* } "." ; + +ARTICLE: "conditionals-boolean-equivalence" "Expressing conditionals with boolean logic" +"Certain simple conditional forms can be expressed in a simpler manner using boolean logic." +$nl +"The following two lines are equivalent:" +{ $code "[ drop f ] unless" "swap and" } +"The following two lines are equivalent:" +{ $code "[ ] [ ] ?if" "swap or" } +"The following two lines are equivalent, where " { $snippet "L" } " is a literal:" +{ $code "[ L ] unless*" "L or" } ; + +ARTICLE: "conditionals" "Conditional combinators" +"The basic conditionals:" +{ $subsection if } +{ $subsection when } +{ $subsection unless } +"Forms abstracting a common stack shuffle pattern:" +{ $subsection if* } +{ $subsection when* } +{ $subsection unless* } +"Another form abstracting a common stack shuffle pattern:" +{ $subsection ?if } +"Sometimes instead of branching, you just need to pick one of two values:" +{ $subsection ? } +"Two combinators which abstract out nested chains of " { $link if } ":" +{ $subsection cond } +{ $subsection case } +{ $subsection "conditionals-boolean-equivalence" } +{ $see-also "booleans" "bitwise-arithmetic" both? either? } ; + +ARTICLE: "dataflow-combinators" "Data flow combinators" +"Data flow combinators pass values between quotations:" +{ $subsection "slip-keep-combinators" } +{ $subsection "cleave-combinators" } +{ $subsection "spread-combinators" } +{ $subsection "apply-combinators" } +{ $see-also "curried-dataflow" } ; + ARTICLE: "combinators-quot" "Quotation construction utilities" "Some words for creating quotations which can be useful for implementing method combinations and compiler transforms:" { $subsection cond>quot } { $subsection case>quot } { $subsection alist>quot } ; -ARTICLE: "call" "Calling code with known stack effects" -"Arbitrary quotations and words can be called from code accepted by the optimizing compiler. This is done by specifying the stack effect of the quotation literally. It is checked at runtime that the stack effect is accurate." +ARTICLE: "call" "Fundamental combinators" +"The most basic combinators are those that take either a quotation or word, and invoke it immediately. There are two sets of combinators; they differe in whether or not the stack effect of the expected code is declared." $nl -"Quotations:" -{ $subsection POSTPONE: call( } +"The simplest combinators do not take an effect declaration:" +{ $subsection call } +{ $subsection execute } +"These combinators only get optimized by the compiler if the quotation or word parameter is a literal; otherwise a compiler warning will result. Definitions of combinators which require literal parameters must be followed by the " { $link POSTPONE: inline } " declaration. For example:" +{ $code + ": keep ( x quot -- x )" + " over [ call ] dip ; inline" +} +"See " { $link "declarations" } " and " { $link "compiler-errors" } " for details." +$nl +"The other set of combinators allow arbitrary quotations and words to be called from optimized code. This is done by specifying the stack effect of the quotation literally. It is checked at runtime that the stack effect is accurate." { $subsection call-effect } -"Words:" -{ $subsection POSTPONE: execute( } { $subsection execute-effect } -"Unsafe calls:" +"A simple layer of syntax sugar is defined on top:" +{ $subsection POSTPONE: call( } +{ $subsection POSTPONE: execute( } +"Unsafe calls declare an effect statically without any runtime checking:" { $subsection call-effect-unsafe } -{ $subsection execute-effect-unsafe } ; +{ $subsection execute-effect-unsafe } +{ $see-also "effects" "inference" } ; -ARTICLE: "combinators" "Additional combinators" -"The " { $vocab-link "combinators" } " vocabulary provides a few useful combinators." +ARTICLE: "combinators" "Combinators" +"A central concept in Factor is that of a " { $emphasis "combinator" } ", which is a word taking code as input." +{ $subsection "call" } +{ $subsection "dataflow-combinators" } +{ $subsection "conditionals" } +{ $subsection "looping-combinators" } +{ $subsection "compositional-combinators" } +{ $subsection "combinators.short-circuit" } +{ $subsection "combinators.smart" } +"More combinators are defined for working on data structures, such as " { $link "sequences-combinators" } " and " { $link "assocs-combinators" } "." $nl -"Generalization of " { $link bi } " and " { $link tri } ":" -{ $subsection cleave } -"Generalization of " { $link 2bi } " and " { $link 2tri } ":" -{ $subsection 2cleave } -"Generalization of " { $link 3bi } " and " { $link 3tri } ":" -{ $subsection 3cleave } -"Generalization of " { $link bi* } " and " { $link tri* } ":" -{ $subsection spread } -"Two combinators which abstract out nested chains of " { $link if } ":" -{ $subsection cond } -{ $subsection case } -"The " { $vocab-link "combinators" } " also provides some less frequently-used features." +"The " { $vocab-link "combinators" } " provides some less frequently-used features." $nl "A combinator which can help with implementing methods on " { $link hashcode* } ":" { $subsection recursive-hashcode } -{ $subsection "call" } { $subsection "combinators-quot" } -{ $see-also "quotations" "dataflow" } ; +"Advanced topics:" +{ $see-also "quotations" } ; ABOUT: "combinators" diff --git a/core/definitions/definitions-docs.factor b/core/definitions/definitions-docs.factor index b53ab28cbc..9d49cf62c6 100644 --- a/core/definitions/definitions-docs.factor +++ b/core/definitions/definitions-docs.factor @@ -56,11 +56,24 @@ $nl { $subsection redefine-error } ; ARTICLE: "definitions" "Definitions" -"A " { $emphasis "definition" } " is an artifact read from a source file. This includes words, methods, help articles, and path names (which represent the source file at that location). Words for working with definitions are found in the " { $vocab-link "definitions" } " vocabulary." +"A " { $emphasis "definition" } " is an artifact read from a source file. Words for working with definitions are found in the " { $vocab-link "definitions" } " vocabulary." +$nl +"Definitions are defined using parsing words. Examples of definitions together with their defining parsing words are words (" { $link POSTPONE: : } "), methods (" { $link POSTPONE: M: } "), and vocabularies (" { $link POSTPONE: IN: } ")." +$nl +"All definitions share some common traits:" +{ $list + "There is a word to list all definitions of a given type" + "There is a parsing word for creating new definitions" + "There is an ordinary word which is the runtime equivalent of the parsing word, for introspection" + "Instances of the definition may be introspected and modified with the definition protocol" +} +"For every source file loaded into the system, a list of definitions is maintained. Pathname objects implement the definition protocol, acting over the definitions their source files contain. See " { $link "source-files" } " for details." { $subsection "definition-protocol" } { $subsection "definition-crossref" } { $subsection "definition-checking" } { $subsection "compilation-units" } +"A parsing word to remove definitions:" +{ $subsection POSTPONE: FORGET: } { $see-also "see" "parser" "source-files" "words" "generic" "help-impl" } ; ABOUT: "definitions" diff --git a/core/effects/effects-docs.factor b/core/effects/effects-docs.factor index b209dcf259..20709ca807 100644 --- a/core/effects/effects-docs.factor +++ b/core/effects/effects-docs.factor @@ -1,4 +1,4 @@ -USING: help.markup help.syntax math strings words kernel ; +USING: help.markup help.syntax math strings words kernel combinators ; IN: effects ARTICLE: "effect-declaration" "Stack effect declaration" @@ -29,14 +29,11 @@ $nl "The stack effect inferencer verifies stack effect comments to ensure the correct number of inputs and outputs is listed. Value names are ignored; only their number matters. An error is thrown if a word's declared stack effect does not match its inferred stack effect. See " { $link "inference" } "." ; ARTICLE: "effects" "Stack effects" -"A " { $emphasis "stack effect declaration" } ", for example " { $snippet "( x y -- z )" } " denotes that an operation takes two inputs, with " { $snippet "y" } " at the top of the stack, and returns one output." +"A " { $emphasis "stack effect declaration" } ", for example " { $snippet "( x y -- z )" } " denotes that an operation takes two inputs, with " { $snippet "y" } " at the top of the stack, and returns one output. Stack effects are first-class, and words for working with them are found in the " { $vocab-link "effects" } " vocabulary." $nl -"Stack effects of words can be declared." +"Stack effects of words must be declared, and the " { $link "compiler" } " checks that these declarations are correct. Invalid declarations are reported as " { $link "compiler-errors" } ". The " { $link "inference" } " tool can be used to check stack effects interactively." { $subsection "effect-declaration" } -"Stack effects are first-class, and words for working with them are found in the " { $vocab-link "effects" } " vocabulary." -{ $subsection effect } -{ $subsection effect? } -"There is a literal syntax for stack objects. It is most often used with " { $link define-declared } "." +"There is a literal syntax for stack objects. It is most often used with " { $link define-declared } ", " { $link call-effect } " and " { $link execute-effect } "." { $subsection POSTPONE: (( } "Getting a word's declared stack effect:" { $subsection stack-effect } @@ -45,7 +42,9 @@ $nl "Comparing effects:" { $subsection effect-height } { $subsection effect<= } -{ $see-also "inference" } ; +"The class of stack effects:" +{ $subsection effect } +{ $subsection effect? } ; ABOUT: "effects" diff --git a/core/generic/generic-docs.factor b/core/generic/generic-docs.factor index 06a8fa87a3..7017ef8a08 100644 --- a/core/generic/generic-docs.factor +++ b/core/generic/generic-docs.factor @@ -45,8 +45,8 @@ $nl { $subsection make-generic } "Low-level method constructor:" { $subsection } -"A " { $emphasis "method specifier" } " refers to a method and implements the " { $link "definition-protocol" } ":" -{ $subsection method-spec } +"Methods may be pushed on the stack with a literal syntax:" +{ $subsection POSTPONE: M\ } { $see-also "see" } ; ARTICLE: "method-combination" "Custom method combination" @@ -98,8 +98,8 @@ $nl "Generic words must declare their stack effect in order to compile. See " { $link "effect-declaration" } "." { $subsection "method-order" } { $subsection "call-next-method" } -{ $subsection "generic-introspection" } { $subsection "method-combination" } +{ $subsection "generic-introspection" } "Generic words specialize behavior based on the class of an object; sometimes behavior needs to be specialized on the object's " { $emphasis "structure" } "; this is known as " { $emphasis "pattern matching" } " and is implemented in the " { $vocab-link "match" } " vocabulary." ; ABOUT: "generic" @@ -119,9 +119,10 @@ HELP: define-generic { $description "Defines a generic word. A method combination is an object which responds to the " { $link perform-combination } " generic word." } { $contract "The method combination quotation is called each time the generic word has to be updated (for example, when a method is added), and thus must be side-effect free." } ; -HELP: method-spec -{ $class-description "The class of method specifiers, which are two-element arrays consisting of a class word followed by a generic word." } -{ $examples { $code "{ fixnum + }" "{ editor draw-gadget* }" } } ; +HELP: M\ +{ $syntax "M\\ class generic" } +{ $class-description "Pushes a method on the stack." } +{ $examples { $code "M\\ fixnum + see" } { $code "USING: ui.gadgets ui.gadgets.editors ;" "M\\ editor draw-gadget* edit" } } ; HELP: method-body { $class-description "The class of method bodies, which are words with special word properties set." } ; diff --git a/core/generic/generic-tests.factor b/core/generic/generic-tests.factor index aadc44833f..151c2f52fa 100755 --- a/core/generic/generic-tests.factor +++ b/core/generic/generic-tests.factor @@ -105,9 +105,6 @@ M: shit big-generic-test "shit" ; [ float ] [ \ real \ float math-class-max ] unit-test [ fixnum ] [ \ fixnum \ null math-class-max ] unit-test -[ t ] [ { hashtable equal? } method-spec? ] unit-test -[ f ] [ { word = } method-spec? ] unit-test - ! Regression TUPLE: first-one ; TUPLE: second-one ; diff --git a/core/generic/math/math-docs.factor b/core/generic/math/math-docs.factor index 4323f91bc3..60fa745339 100644 --- a/core/generic/math/math-docs.factor +++ b/core/generic/math/math-docs.factor @@ -15,7 +15,7 @@ HELP: no-math-method HELP: math-method { $values { "word" generic } { "class1" class } { "class2" class } { "quot" quotation } } { $description "Generates a definition for " { $snippet "word" } " when the two inputs are instances of " { $snippet "class1" } " and " { $snippet "class2" } ", respectively." } -{ $examples { $example "USING: generic.math math prettyprint ;" "\\ + fixnum float math-method ." "[ { fixnum float } declare [ >float ] dip float=>+ ]" } } ; +{ $examples { $example "USING: generic.math math prettyprint ;" "\\ + fixnum float math-method ." "[ { fixnum float } declare [ >float ] dip M\\ float + ]" } } ; HELP: math-class { $class-description "The class of subtypes of " { $link number } " which are not " { $link null } "." } ; diff --git a/core/kernel/kernel-docs.factor b/core/kernel/kernel-docs.factor index c178573a0a..36d04f1437 100644 --- a/core/kernel/kernel-docs.factor +++ b/core/kernel/kernel-docs.factor @@ -841,260 +841,6 @@ $nl { $subsection roll } { $subsection -roll } ; -ARTICLE: "cleave-shuffle-equivalence" "Expressing shuffle words with cleave combinators" -"Cleave combinators are defined in terms of shuffle words, and mappings from certain shuffle idioms to cleave combinators are discussed in the documentation for " { $link bi } ", " { $link 2bi } ", " { $link 3bi } ", " { $link tri } ", " { $link 2tri } " and " { $link 3tri } "." -$nl -"Certain shuffle words can also be expressed in terms of the cleave combinators. Internalizing such identities can help with understanding and writing code using cleave combinators:" -{ $code - ": keep [ ] bi ;" - ": 2keep [ ] 2bi ;" - ": 3keep [ ] 3bi ;" - "" - ": dup [ ] [ ] bi ;" - ": 2dup [ ] [ ] 2bi ;" - ": 3dup [ ] [ ] 3bi ;" - "" - ": tuck [ nip ] [ ] 2bi ;" - ": swap [ nip ] [ drop ] 2bi ;" - "" - ": over [ ] [ drop ] 2bi ;" - ": pick [ ] [ 2drop ] 3bi ;" - ": 2over [ ] [ drop ] 3bi ;" -} ; - -ARTICLE: "cleave-combinators" "Cleave combinators" -"The cleave combinators apply multiple quotations to a single value." -$nl -"Two quotations:" -{ $subsection bi } -{ $subsection 2bi } -{ $subsection 3bi } -"Three quotations:" -{ $subsection tri } -{ $subsection 2tri } -{ $subsection 3tri } -"Technically, the cleave combinators are redundant because they can be simulated using shuffle words and other combinators, and in addition, they do not reduce token counts by much, if at all. However, they can make code more readable by expressing intention and exploiting any inherent symmetry. For example, a piece of code which performs three operations on the top of the stack can be written in one of two ways:" -{ $code - "! First alternative; uses keep" - "[ 1 + ] keep" - "[ 1 - ] keep" - "2 *" - "! Second alternative: uses tri" - "[ 1 + ]" - "[ 1 - ]" - "[ 2 * ] tri" -} -"The latter is more aesthetically pleasing than the former." -$nl -"A generalization of the above combinators to any number of quotations can be found in " { $link "combinators" } "." -{ $subsection "cleave-shuffle-equivalence" } ; - -ARTICLE: "spread-shuffle-equivalence" "Expressing shuffle words with spread combinators" -"Spread combinators are defined in terms of shuffle words, and mappings from certain shuffle idioms to spread combinators are discussed in the documentation for " { $link bi* } ", " { $link 2bi* } ", " { $link tri* } ", and " { $link 2tri* } "." -$nl -"Certain shuffle words can also be expressed in terms of the spread combinators. Internalizing such identities can help with understanding and writing code using spread combinators:" -{ $code - ": dip [ ] bi* ;" - ": 2dip [ ] [ ] tri* ;" - "" - ": slip [ call ] [ ] bi* ;" - ": 2slip [ call ] [ ] [ ] tri* ;" - "" - ": nip [ drop ] [ ] bi* ;" - ": 2nip [ drop ] [ drop ] [ ] tri* ;" - "" - ": rot" - " [ [ drop ] [ ] [ drop ] tri* ]" - " [ [ drop ] [ drop ] [ ] tri* ]" - " [ [ ] [ drop ] [ drop ] tri* ]" - " 3tri ;" - "" - ": -rot" - " [ [ drop ] [ drop ] [ ] tri* ]" - " [ [ ] [ drop ] [ drop ] tri* ]" - " [ [ drop ] [ ] [ drop ] tri* ]" - " 3tri ;" - "" - ": spin" - " [ [ drop ] [ drop ] [ ] tri* ]" - " [ [ drop ] [ ] [ drop ] tri* ]" - " [ [ ] [ drop ] [ drop ] tri* ]" - " 3tri ;" -} ; - -ARTICLE: "spread-combinators" "Spread combinators" -"The spread combinators apply multiple quotations to multiple values. The " { $snippet "*" } " suffix signifies spreading." -$nl -"Two quotations:" -{ $subsection bi* } -{ $subsection 2bi* } -"Three quotations:" -{ $subsection tri* } -{ $subsection 2tri* } -"Technically, the spread combinators are redundant because they can be simulated using shuffle words and other combinators, and in addition, they do not reduce token counts by much, if at all. However, they can make code more readable by expressing intention and exploiting any inherent symmetry. For example, a piece of code which performs three operations on three related values can be written in one of two ways:" -{ $code - "! First alternative; uses dip" - "[ [ 1 + ] dip 1 - ] dip 2 *" - "! Second alternative: uses tri*" - "[ 1 + ] [ 1 - ] [ 2 * ] tri*" -} -"A generalization of the above combinators to any number of quotations can be found in " { $link "combinators" } "." -{ $subsection "spread-shuffle-equivalence" } ; - -ARTICLE: "apply-combinators" "Apply combinators" -"The apply combinators apply a single quotation to multiple values. The " { $snippet "@" } " suffix signifies application." -$nl -"Two quotations:" -{ $subsection bi@ } -{ $subsection 2bi@ } -"Three quotations:" -{ $subsection tri@ } -{ $subsection 2tri@ } -"A pair of utility words built from " { $link bi@ } ":" -{ $subsection both? } -{ $subsection either? } ; - -ARTICLE: "slip-keep-combinators" "Retain stack combinators" -"Sometimes an additional storage area is needed to hold objects. The " { $emphasis "retain stack" } " is an auxilliary stack for this purpose. Objects can be moved between the data and retain stacks using a set of combinators." -$nl -"The dip combinators invoke the quotation at the top of the stack, hiding the values underneath:" -{ $subsection dip } -{ $subsection 2dip } -{ $subsection 3dip } -{ $subsection 4dip } -"The slip combinators invoke a quotation further down on the stack. They are most useful for implementing other combinators:" -{ $subsection slip } -{ $subsection 2slip } -{ $subsection 3slip } -"The keep combinators invoke a quotation which takes a number of values off the stack, and then they restore those values:" -{ $subsection keep } -{ $subsection 2keep } -{ $subsection 3keep } ; - -ARTICLE: "curried-dataflow" "Curried dataflow combinators" -"Curried cleave combinators:" -{ $subsection bi-curry } -{ $subsection tri-curry } -"Curried spread combinators:" -{ $subsection bi-curry* } -{ $subsection tri-curry* } -"Curried apply combinators:" -{ $subsection bi-curry@ } -{ $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" -"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 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" } ". 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:" -{ $subsection call } -{ $subsection execute } -"These words are used to implement combinators. Note that combinator definitions must be followed by the " { $link POSTPONE: inline } " declaration in order to compile in the optimizing compiler; for example:" -{ $code - ": keep ( x quot -- x )" - " over [ call ] dip ; inline" -} -"Word inlining is documented in " { $link "declarations" } "." ; - -ARTICLE: "booleans" "Booleans" -"In Factor, any object that is not " { $link f } " has a true value, and " { $link f } " has a false value. The " { $link t } " object is the canonical true value." -{ $subsection f } -{ $subsection t } -"The " { $link f } " object is the unique instance of the " { $link f } " class; the two are distinct objects. The latter is also a parsing word which adds the " { $link f } " object to the parse tree at parse time. To refer to the class itself you must use " { $link POSTPONE: POSTPONE: } " or " { $link POSTPONE: \ } " to prevent the parsing word from executing." -$nl -"Here is the " { $link f } " object:" -{ $example "f ." "f" } -"Here is the " { $link f } " class:" -{ $example "\\ f ." "POSTPONE: f" } -"They are not equal:" -{ $example "f \\ f = ." "f" } -"Here is an array containing the " { $link f } " object:" -{ $example "{ f } ." "{ f }" } -"Here is an array containing the " { $link f } " class:" -{ $example "{ POSTPONE: f } ." "{ POSTPONE: f }" } -"The " { $link f } " object is an instance of the " { $link f } " class:" -{ $example "USE: classes" "f class ." "POSTPONE: f" } -"The " { $link f } " class is an instance of " { $link word } ":" -{ $example "USE: classes" "\\ f class ." "word" } -"On the other hand, " { $link t } " is just a word, and there is no class which it is a unique instance of." -{ $example "t \\ t eq? ." "t" } -"Many words which search collections confuse the case of no element being present with an element being found equal to " { $link f } ". If this distinction is imporant, there is usually an alternative word which can be used; for example, compare " { $link at } " with " { $link at* } "." ; - -ARTICLE: "conditionals-boolean-equivalence" "Expressing conditionals with boolean logic" -"Certain simple conditional forms can be expressed in a simpler manner using boolean logic." -$nl -"The following two lines are equivalent:" -{ $code "[ drop f ] unless" "swap and" } -"The following two lines are equivalent:" -{ $code "[ ] [ ] ?if" "swap or" } -"The following two lines are equivalent, where " { $snippet "L" } " is a literal:" -{ $code "[ L ] unless*" "L or" } ; - -ARTICLE: "conditionals" "Conditionals and logic" -"The basic conditionals:" -{ $subsection if } -{ $subsection when } -{ $subsection unless } -"Forms abstracting a common stack shuffle pattern:" -{ $subsection if* } -{ $subsection when* } -{ $subsection unless* } -"Another form abstracting a common stack shuffle pattern:" -{ $subsection ?if } -"Sometimes instead of branching, you just need to pick one of two values:" -{ $subsection ? } -"There are some logical operations on booleans:" -{ $subsection >boolean } -{ $subsection not } -{ $subsection and } -{ $subsection or } -{ $subsection xor } -{ $subsection "conditionals-boolean-equivalence" } -"See " { $link "combinators" } " for forms which abstract away common patterns involving multiple nested branches." -{ $see-also "booleans" "bitwise-arithmetic" both? either? } ; - ARTICLE: "equality" "Equality" "There are two distinct notions of “sameness” when it comes to objects." $nl @@ -1116,34 +862,3 @@ ARTICLE: "assertions" "Assertions" { $subsection assert } { $subsection assert= } ; -ARTICLE: "dataflow-combinators" "Data flow combinators" -"Data flow combinators pass values between quotations:" -{ $subsection "slip-keep-combinators" } -{ $subsection "cleave-combinators" } -{ $subsection "spread-combinators" } -{ $subsection "apply-combinators" } -{ $see-also "curried-dataflow" } ; - -ARTICLE: "dataflow" "Data and control flow" -{ $subsection "evaluator" } -{ $subsection "words" } -{ $subsection "effects" } -{ $subsection "booleans" } -{ $subsection "shuffle-words" } -"A central concept in Factor is that of a " { $emphasis "combinator" } ", which is a word taking code as input." -{ $subsection "dataflow-combinators" } -{ $subsection "conditionals" } -{ $subsection "looping-combinators" } -{ $subsection "compositional-combinators" } -{ $subsection "combinators" } -"More combinators are defined for working on data structures, such as " { $link "sequences-combinators" } " and " { $link "assocs-combinators" } "." -$nl -"Advanced topics:" -{ $subsection "assertions" } -{ $subsection "implementing-combinators" } -{ $subsection "macros" } -{ $subsection "errors" } -{ $subsection "continuations" } ; - -ABOUT: "dataflow" - diff --git a/core/math/math-docs.factor b/core/math/math-docs.factor index f79dcb5481..c28bf062c1 100644 --- a/core/math/math-docs.factor +++ b/core/math/math-docs.factor @@ -355,8 +355,9 @@ ARTICLE: "bitwise-arithmetic" "Bitwise arithmetic" { $subsection 2/ } { $subsection 2^ } { $subsection bit? } -"The " { $vocab-link "math.bitwise" } " vocabulary implements additional bitwise integer operations." -{ $see-also "conditionals" } ; +{ $subsection "math.bitwise" } +{ $subsection "math.bits" } +{ $see-also "booleans" } ; ARTICLE: "arithmetic" "Arithmetic" "Factor attempts to preserve natural mathematical semantics for numbers. Multiplying two large integers never results in overflow, and dividing two integers yields an exact ratio. Floating point numbers are also supported, along with complex numbers." diff --git a/core/math/order/order-docs.factor b/core/math/order/order-docs.factor index 1bdd1009e9..8b2200aa67 100644 --- a/core/math/order/order-docs.factor +++ b/core/math/order/order-docs.factor @@ -87,7 +87,14 @@ ARTICLE: "order-specifiers" "Ordering specifiers" { $subsection +lt+ } { $subsection +eq+ } { $subsection +gt+ } ; - + +ARTICLE: "math.order.example" "Linear order example" +"A tuple class which defines an ordering among instances by comparing the values of the " { $snippet "id" } " slot:" +{ $code + "TUPLE: sprite id name bitmap ;" + "M: sprite <=> [ id>> ] compare ;" +} ; + ARTICLE: "math.order" "Linear order protocol" "Some classes have an intrinsic order amongst instances:" { $subsection <=> } @@ -101,6 +108,8 @@ ARTICLE: "math.order" "Linear order protocol" { $subsection before? } { $subsection after=? } { $subsection before=? } +"Out of the above generic words, it suffices to implement " { $link <=> } " alone. The others may be provided as an optimization." +{ $subsection "math.order.example" } { $see-also "sequences-sorting" } ; ABOUT: "math.order" diff --git a/core/namespaces/namespaces-docs.factor b/core/namespaces/namespaces-docs.factor index ff0542a7b8..74d7c58963 100644 --- a/core/namespaces/namespaces-docs.factor +++ b/core/namespaces/namespaces-docs.factor @@ -32,7 +32,7 @@ ARTICLE: "namespaces.private" "Namespace implementation details" { $subsection >n } { $subsection ndrop } ; -ARTICLE: "namespaces" "Variables and namespaces" +ARTICLE: "namespaces" "Dynamic variables and namespaces" "The " { $vocab-link "namespaces" } " vocabulary implements simple dynamically-scoped variables." $nl "A variable is an entry in an assoc of bindings, where the assoc is implicit rather than passed on the stack. These assocs are termed " { $emphasis "namespaces" } ". Nesting of scopes is implemented with a search order on namespaces, defined by a " { $emphasis "namestack" } ". Since namespaces are just assoc, any object can be used as a variable, however by convention, variables are keyed by symbols (see " { $link "words.symbol" } ")." @@ -43,7 +43,6 @@ $nl "Various utility words abstract away common variable access patterns:" { $subsection "namespaces-change" } { $subsection "namespaces-combinators" } -{ $subsection "namespaces-global" } "Implementation details your code probably does not care about:" { $subsection "namespaces.private" } "An alternative to dynamic scope is lexical scope. Lexically-scoped values and closures are implemented in the " { $vocab-link "locals" } " vocabulary." ; diff --git a/core/parser/parser-docs.factor b/core/parser/parser-docs.factor index 547f7c0490..be4b345f4f 100644 --- a/core/parser/parser-docs.factor +++ b/core/parser/parser-docs.factor @@ -92,9 +92,7 @@ ARTICLE: "parser" "The parser" "This parser is a general facility for reading textual representations of objects and definitions. The parser is implemented in the " { $vocab-link "parser" } " and " { $vocab-link "syntax" } " vocabularies." $nl "This section concerns itself with usage and extension of the parser. Standard syntax is described in " { $link "syntax" } "." -{ $subsection "vocabulary-search" } { $subsection "parser-files" } -{ $subsection "top-level-forms" } "The parser can be extended." { $subsection "parsing-words" } { $subsection "parser-lexer" } diff --git a/core/quotations/quotations-docs.factor b/core/quotations/quotations-docs.factor index 2a03b7c74f..a72f4adf88 100644 --- a/core/quotations/quotations-docs.factor +++ b/core/quotations/quotations-docs.factor @@ -24,7 +24,7 @@ ARTICLE: "wrappers" "Wrappers" "Wrappers are used to push words on the data stack; they evaluate to the object being wrapped:" { $subsection wrapper } { $subsection literalize } -{ $see-also "dataflow" "combinators" } ; +{ $see-also "combinators" } ; ABOUT: "quotations" diff --git a/core/sequences/sequences-docs.factor b/core/sequences/sequences-docs.factor index e2badc2031..4103950005 100755 --- a/core/sequences/sequences-docs.factor +++ b/core/sequences/sequences-docs.factor @@ -1354,14 +1354,16 @@ ARTICLE: "virtual-sequences" "Virtual sequences" "Virtual sequences allow different ways of accessing a sequence without having to create a new sequence or a new data structure altogether. To do this, they translate the virtual index into a normal index into an underlying sequence using the " { $link "virtual-sequences-protocol" } "." { $subsection "virtual-sequences-protocol" } ; -ARTICLE: "sequences-integers" "Integer sequences and counted loops" +ARTICLE: "sequences-integers" "Counted loops" "Integers support the sequence protocol in a trivial fashion; a non-negative integer presents its non-negative predecessors as elements. For example, the integer 3, when viewed as a sequence, contains the elements 0, 1, and 2. This is very useful for performing counted loops." $nl "For example, the " { $link each } " combinator, given an integer, simply calls a quotation that number of times, pushing a counter on each iteration that ranges from 0 up to that integer:" { $example "3 [ . ] each" "0\n1\n2" } "A common idiom is to iterate over a sequence, while also maintaining a loop counter. This can be done using " { $link each-index } ", " { $link map-index } " and " { $link reduce-index } "." $nl -"Combinators that produce new sequences, such as " { $link map } ", will output an array if the input is an integer." ; +"Combinators that produce new sequences, such as " { $link map } ", will output an array if the input is an integer." +$nl +"More elaborate counted loops can be performed with " { $link "math.ranges" } "." ; ARTICLE: "sequences-access" "Accessing sequence elements" { $subsection ?nth } @@ -1593,7 +1595,6 @@ $nl "Sequences implement a protocol:" { $subsection "sequence-protocol" } { $subsection "sequences-f" } -{ $subsection "sequences-integers" } "Sequence utility words can operate on any object whose class implements the sequence protocol. Most implementations are backed by storage. Some implementations obtain their elements from an underlying sequence, or compute them on the fly. These are known as " { $link "virtual-sequences" } "." { $subsection "sequences-access" } { $subsection "sequences-combinators" } @@ -1612,6 +1613,10 @@ $nl { $subsection "binary-search" } { $subsection "sets" } { $subsection "sequences-trimming" } +{ $subsection "sequences.deep" } +"Using sequences for looping:" +{ $subsection "sequences-integers" } +{ $subsection "ranges" } "For inner loops:" { $subsection "sequences-unsafe" } ; diff --git a/core/slots/slots-docs.factor b/core/slots/slots-docs.factor index 840fe628e0..1e5f9bf1dd 100644 --- a/core/slots/slots-docs.factor +++ b/core/slots/slots-docs.factor @@ -83,7 +83,7 @@ $nl "A word can be used to check if a class has an initial value or not:" { $subsection initial-value } ; -ARTICLE: "slots" "Slots" +ARTICLE: "slots" "Low-level slot operations" "The " { $vocab-link "slots" } " vocabulary contains words for introspecting the slots of an object. A " { $emphasis "slot" } " is a component of an object which can store a value." $nl { $link "tuples" } " are composed entirely of slots, and instances of " { $link "builtin-classes" } " consist of slots together with intrinsic data." @@ -104,6 +104,9 @@ $nl { $subsection define-changer } { $subsection define-slot-methods } { $subsection define-accessors } +"Unsafe slot access:" +{ $subsection slot } +{ $subsection set-slot } { $see-also "accessors" "mirrors" } ; ABOUT: "slots" diff --git a/extra/peg-lexer/tags.txt b/extra/peg-lexer/tags.txt index 47619a17f8..44385cf3b7 100644 --- a/extra/peg-lexer/tags.txt +++ b/extra/peg-lexer/tags.txt @@ -1 +1,2 @@ -reflection \ No newline at end of file +extensions +reflection