factor/basis/locals/locals-docs.factor

147 lines
8.0 KiB
Factor
Raw Normal View History

2008-04-27 02:49:05 -04:00
USING: help.syntax help.markup kernel macros prettyprint
memoize ;
2007-09-20 18:09:08 -04:00
IN: locals
HELP: [|
{ $syntax "[| bindings... | body... ]" }
{ $description "A lambda abstraction. When called, reads stack values into the bindings from left to right; the body may then refer to these bindings." }
{ $examples
{ $example
2008-03-11 20:51:58 -04:00
"USING: kernel locals math prettyprint ;"
"IN: scratchpad"
2008-02-26 19:40:32 -05:00
":: adder ( n -- quot ) [| m | m n + ] ;"
2007-09-20 18:09:08 -04:00
"3 5 adder call ."
"8"
}
2008-05-07 09:48:51 -04:00
} ;
2007-09-20 18:09:08 -04:00
HELP: [let
{ $syntax "[let | binding1 [ value1... ]\n binding2 [ value2... ]\n ... |\n body... ]" }
2008-03-19 22:16:09 -04:00
{ $description "Introduces a set of lexical bindings and evaluates the body. The values are evaluated in parallel, and may not refer to other bindings within the same " { $link POSTPONE: [let } " form; for Lisp programmers, this means that " { $link POSTPONE: [let } " is equivalent to the Lisp " { $snippet "let" } ", not " { $snippet "let*" } "." }
2007-09-20 18:09:08 -04:00
{ $examples
{ $example
2008-03-11 20:51:58 -04:00
"USING: kernel locals math math.functions prettyprint sequences ;"
"IN: scratchpad"
2008-02-26 19:40:32 -05:00
":: frobnicate ( n seq -- newseq )"
2007-09-20 18:09:08 -04:00
" [let | n' [ n 6 * ] |"
2007-12-11 22:36:40 -05:00
" seq [ n' gcd nip ] map ] ;"
2007-09-20 18:09:08 -04:00
"6 { 36 14 } frobnicate ."
"{ 36 2 }"
}
2008-05-07 09:48:51 -04:00
} ;
2007-09-20 18:09:08 -04:00
2008-03-19 22:16:09 -04:00
HELP: [let*
{ $syntax "[let* | binding1 [ value1... ]\n binding2 [ value2... ]\n ... |\n body... ]" }
{ $description "Introduces a set of lexical bindings and evaluates the body. The values are evaluated sequentially, and may refer to previous bindings from the same " { $link POSTPONE: [let* } " form; for Lisp programmers, this means that " { $link POSTPONE: [let* } " is equivalent to the Lisp " { $snippet "let*" } ", not " { $snippet "let" } "." }
{ $examples
{ $example
"USING: kernel locals math math.functions prettyprint sequences ;"
"IN: scratchpad"
2008-03-19 22:16:09 -04:00
":: frobnicate ( n seq -- newseq )"
" [let* | a [ n 3 + ]"
" b [ a 4 * ] |"
" seq [ b / ] map ] ;"
"1 { 32 48 } frobnicate ."
"{ 2 3 }"
}
2008-05-07 09:48:51 -04:00
} ;
2008-03-19 22:16:09 -04:00
{ POSTPONE: [let POSTPONE: [let* } related-words
2007-09-20 18:09:08 -04:00
HELP: [wlet
{ $syntax "[wlet | binding1 [ body1... ]\n binding2 [ body2... ]\n ... |\n body... ]" }
{ $description "Introduces a set of lexically-scoped non-recursive local functions. The bodies may not refer to other bindings within the same " { $link POSTPONE: [wlet } " form; for Lisp programmers, this means that Factor's " { $link POSTPONE: [wlet } " is equivalent to the Lisp " { $snippet "flet" } ", not " { $snippet "labels" } "." }
{ $examples
{ $example
2008-03-11 20:51:58 -04:00
"USING: locals math prettyprint sequences ;"
"IN: scratchpad"
2008-02-26 19:40:32 -05:00
":: quuxify ( n seq -- newseq )"
2007-09-20 18:09:08 -04:00
" [wlet | add-n [| m | m n + ] |"
" seq [ add-n ] map ] ;"
"2 { 1 2 3 } quuxify ."
"{ 3 4 5 }"
}
} ;
HELP: ::
2008-02-26 19:40:32 -05:00
{ $syntax ":: word ( bindings... -- outputs... ) body... ;" }
2007-09-20 18:09:08 -04:00
{ $description "Defines a word with named inputs; it reads stack values into bindings from left to right, then executes the body with those bindings in lexical scope. Any " { $link POSTPONE: [| } ", " { $link POSTPONE: [let } " or " { $link POSTPONE: [wlet } " forms used in the body of the word definition are automatically closure-converted." }
2008-02-26 19:40:32 -05:00
{ $notes "The output names do not affect the word's behavior, however the compiler attempts to check the stack effect as with other definitions." }
2007-09-20 18:09:08 -04:00
{ $examples "See " { $link POSTPONE: [| } ", " { $link POSTPONE: [let } " and " { $link POSTPONE: [wlet } "." } ;
2008-04-27 02:49:05 -04:00
{ POSTPONE: : POSTPONE: :: } related-words
2007-09-20 18:09:08 -04:00
HELP: MACRO::
2008-02-26 19:40:32 -05:00
{ $syntax "MACRO:: word ( bindings... -- outputs... ) body... ;" }
2008-04-27 02:49:05 -04:00
{ $description "Defines a macro with named inputs; it reads stack values into bindings from left to right, then executes the body with those bindings in lexical scope." }
2008-02-26 19:40:32 -05:00
{ $notes "The output names do not affect the word's behavior, however the compiler attempts to check the stack effect as with other definitions." } ;
2007-09-20 18:09:08 -04:00
{ POSTPONE: MACRO: POSTPONE: MACRO:: } related-words
2008-04-27 02:49:05 -04:00
HELP: MEMO::
{ $syntax "MEMO:: word ( bindings... -- outputs... ) body... ;" }
{ $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
2007-09-20 18:09:08 -04:00
ARTICLE: "locals-mutable" "Mutable locals"
"In the list of bindings supplied to " { $link POSTPONE: :: } ", " { $link POSTPONE: [let } " or " { $link POSTPONE: [| } ", a mutable binding may be introduced by suffixing its named with " { $snippet "!" } ". Mutable bindings are read by giving their name as usual; the suffix is not part of the binding's name. To write to a mutable binding, use the binding's with the " { $snippet "!" } " suffix."
$nl
"Here is a example word which outputs a pair of quotations which increment and decrement an internal counter, and then return the new value. The quotations are closed over the counter and each invocation of the word yields new quotations with their unique internal counter:"
{ $code
2008-02-26 19:40:32 -05:00
":: counter ( -- )"
2007-09-20 18:09:08 -04:00
" [let | value! [ 0 ] |"
" [ value 1+ dup value! ]"
" [ value 1- dup value! ] ] ;"
}
"Mutable bindings are implemented in a manner similar to the ML language; each mutable binding is actually an immutable binding of a mutable cell (in Factor's case, a 1-element array); reading the binding automatically dereferences the array, and writing to the binding stores into the array."
$nl
"Unlike some languages such as Python and Java, writing to mutable locals in outer scopes is fully supported and has the expected semantics." ;
ARTICLE: "locals-limitations" "Limitations of locals"
"The first limitation is that the " { $link >r } " and " { $link r> } " words may not be used together with locals. Instead, use the " { $link dip } " combinator."
$nl
"Another limitation concerns combinators implemented as macros. Locals can only be used with such combinators if the input array immediately precedes the combinator call. For example, the following will work:"
2007-09-20 18:09:08 -04:00
{ $code
":: good-cond-usage ( a -- ... )"
2008-04-29 03:59:14 -04:00
" {"
" { [ a 0 < ] [ ... ] }"
" { [ a 0 > ] [ ... ] }"
" { [ a 0 = ] [ ... ] }"
" } cond ;"
}
"But not the following:"
{ $code
": my-cond ( alist -- ) cond ; inline"
""
":: bad-cond-usage ( a -- ... )"
" {"
" { [ a 0 < ] [ ... ] }"
" { [ a 0 > ] [ ... ] }"
" { [ a 0 = ] [ ... ] }"
" } my-cond ;"
}
"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." ;
2007-09-20 18:09:08 -04:00
ARTICLE: "locals" "Local variables and lexical 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: :: }
2008-04-27 02:49:05 -04:00
{ $subsection POSTPONE: MEMO:: }
2007-09-20 18:09:08 -04:00
{ $subsection POSTPONE: MACRO:: }
"Lexical binding forms:"
{ $subsection POSTPONE: [let }
2008-03-19 22:16:09 -04:00
{ $subsection POSTPONE: [let* }
2007-09-20 18:09:08 -04:00
{ $subsection POSTPONE: [wlet }
"Lambda abstractions:"
{ $subsection POSTPONE: [| }
"Additional topics:"
{ $subsection "locals-mutable" }
{ $subsection "locals-limitations" }
"Locals complement dynamically scoped variables implemented in the " { $vocab-link "namespaces" } " vocabulary." ;
ABOUT: "locals"