 } ;
 
 HELP: :>
-{ $syntax ":> binding" }
-{ $description "Introduces a new binding, lexically scoped to the enclosing quotation or definition." }
+{ $syntax ":> var" ":> var!" }
+{ $description "Binds the value on the top of the datastack to a new local variable named " { $snippet "var" } ", lexically scoped to the enclosing quotation or definition."
+$nl
+"If the " { $snippet "var" } " name is followed by an exclamation point (" { $snippet "!" } "), the new variable will be mutable. See " { $link "locals-mutable" } " for more information on mutable local bindings." }
 { $notes
-    "This word can only be used inside a lambda word, lambda quotation or let binding form."
-    $nl
-    "Lambda and let forms are really just syntax sugar for " { $link POSTPONE: :> } "."
-    $nl
-    "Lambdas desugar as follows:"
-    { $code
-        "[| a b | a b + b / ]"
-        "[ :> b :> a a b + b / ]"
-    }
-    "Let forms desugar as follows:"
-    { $code
-        "[|let | x [ 10 random ] | { x x } ]"
-        "10 random :> x { x x }"
-    }
-}
-{ $examples
-    { $code
-        "USING: locals math kernel ;"
-        "IN: scratchpad"
-        ":: quadratic ( a b c -- x y )"
-        "    b sq 4 a c * * - sqrt :> disc"
-        "    b neg disc [ + ] [ - ] 2bi [ 2 a * / ] bi@ ;"
-    }
-} ;
+    "This syntax can only be used inside a " { $link POSTPONE: :: } " word, " { $link POSTPONE: [let } ", " { $link POSTPONE: [let* } ",  or " { $link POSTPONE: [wlet } " form, or inside a quotation literal inside one of those forms."
+}
+{ $examples "See " { $link "locals-examples" } "." } ;
 
 HELP: ::
 { $syntax ":: word ( bindings... -- outputs... ) body... ;" }
-{ $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." }
+{ $description "Defines a word with named inputs; it reads datastack values into local variable 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." }
-{ $examples "See " { $link POSTPONE: [| } ", " { $link POSTPONE: [let } " and " { $link POSTPONE: [wlet } "." } ;
+{ $examples "See " { $link "locals-examples" } "." } ;
 
 { POSTPONE: : POSTPONE: :: } related-words
 
 HELP: MACRO::
 { $syntax "MACRO:: word ( bindings... -- outputs... ) body... ;" }
-{ $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." }
-{ $notes "The output names do not affect the word's behavior, however the compiler attempts to check the stack effect as with other definitions." } ;
+{ $description "Defines a macro with named inputs; it reads datastack values into local variable 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." }
+{ $examples "See " { $link "locals-examples" } "." } ;
 
 { POSTPONE: MACRO: POSTPONE: MACRO:: } related-words
 
 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." } ;
+{ $description "Defines a macro with named inputs; it reads datastack values into local variable bindings from left to right, then executes the body with those bindings in lexical scope." }
+{ $examples "See " { $link "locals-examples" } "." } ;
 
 { 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." } ;
+{ $description "Defines a macro with named inputs; it reads datastack values into local variable 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." }
+{ $examples "See " { $link "locals-examples" } "." } ;
 
 { POSTPONE: M: POSTPONE: M:: } related-words
 
+ARTICLE: "locals-examples" "Examples of locals"
+{ $heading "Definitions with locals" }
+"The following example demonstrates local variable bindings in word definitions. The " { $snippet "quadratic-roots" } " word is defined with " { $link POSTPONE: :: } ", so it takes its inputs from the top three elements of the datastack and binds them to the variables " { $snippet "a" } ", " { $snippet "b" } ", and " { $snippet "c" } ". In the body, the " { $snippet "disc" } " variable is bound using " { $link POSTPONE: :> } " and then used in the following line of code."
+{ $example """USING: locals math math.functions kernel ;
+IN: scratchpad
+:: quadratic-roots ( a b c -- x y )
+    b sq 4 a c * * - sqrt :> disc
+    b neg disc [ + ] [ - ] 2bi [ 2 a * / ] bi@ ;
+1.0 1.0 -6.0 quadratic-roots [ . ] bi@"""
+"""2.0
+-3.0"""
+}
+{ $snippet "quadratic-roots" } " can also be expressed with " { $link POSTPONE: [let } ":"
+{ $example """USING: locals math math.functions kernel ;
+IN: scratchpad
+:: quadratic-roots ( a b c -- x y )
+    [let | disc [ b sq 4 a c * * - sqrt ] |
+        b neg disc [ + ] [ - ] 2bi [ 2 a * / ] bi@
+    ] ;
+1.0 1.0 -6.0 quadratic-roots [ . ] bi@"""
+"""2.0
+-3.0"""
+}
+
+$nl
+
+{ $heading "Quotations with locals, and closures" }
+"These next two examples demonstrate local variable bindings in quotations defined with " { $link POSTPONE: [| } ". In this example, the values " { $snippet "5" } " and " { $snippet "3" } " are put on the datastack. When the quotation is called, those values are bound to " { $snippet "m" } " and " { $snippet "n" } " respectively in the lexical scope of the quotation:"
+{ $example
+    "USING: kernel locals math prettyprint ;"
+    "IN: scratchpad"
+    "5 3 [| m n | m n - ] call ."
+    "2"
+}
+$nl
+
+"In this example, the " { $snippet "adder" } " word creates a quotation that closes over its argument " { $snippet "n" } ". When called, the result of " { $snippet "5 adder" } " pulls " { $snippet "3" } " off the datastack and binds it to " { $snippet "m" } ":"
+{ $example
+    "USING: kernel locals math prettyprint ;"
+    "IN: scratchpad"
+    ":: adder ( n -- quot ) [| m | m n + ] ;"
+    "3 5 adder call ."
+    "8"
+}
+$nl
+
+{ $heading "Mutable bindings" }
+"This next example demonstrates closures and mutable variable bindings. The " { $snippet "make-counter" } " word outputs a tuple containing a pair of quotations that respectively increment and decrement an internal counter in the mutable " { $snippet "value" } " variable and then return the new value. The quotations close over the counter, so each invocation of the word gives new quotations with a new internal counter."
+{ $example
+"""USING: locals kernel math ;
+IN: scratchpad
+
+TUPLE: counter adder subtractor ;
+
+:: <counter> ( -- counter )
+    0 :> value!
+    counter new
+    [ value 1 + dup value! ] >>adder
+    [ value 1 - dup value! ] >>subtractor ;
+<counter>
+[ adder>>      call . ]
+[ adder>>      call . ]
+[ subtractor>> call . ] tri """
+"""1
+2
+1"""
+}
+    $nl
+    "The same variable name can be bound multiple times in the same scope. This is different from reassigning the value of a mutable variable. The most recent binding for a variable name will mask previous bindings for that name. However, the old binding referring to the previous value can still persist in closures. The following contrived example demonstrates this:"
+    { $example
+"""USING: kernel locals prettyprint ;
+IN: scratchpad
+:: rebinding-example ( -- quot1 quot2 )
+    5 :> a [ a ]
+    6 :> a [ a ] ;
+:: mutable-example ( -- quot1 quot2 )
+    5 :> a! [ a ]
+    6 a! [ a ] ;
+rebinding-example [ call . ] bi@
+mutable-example [ call . ] bi@"""
+"""5
+6
+6
+6"""
+} 
+    "In " { $snippet "rebinding-example" } ", the binding of " { $snippet "a" } " to " { $snippet "5" } " is closed over in the first quotation, and the binding of " { $snippet "a" } " to " { $snippet "6" } " is closed over in the second, so calling both quotations results in " { $snippet "5" } " and " { $snippet "6" } " respectively. By contrast, in " { $snippet "mutable-example" } ", both quotations close over a single binding of " { $snippet "a" } ". Even though " { $snippet "a" } " is assigned to " { $snippet "6" } " after the first quotation is made, calling either quotation will output the new value of " { $snippet "a" } "."
+{ $heading "Locals in literals" }
+"Some kinds of literals can include references to local variables as described in " { $link "locals-literals" } ". For example, the " { $link 3array } " word could be implemented as follows:"
+{ $example
+"""USING: locals prettyprint ;
+IN: scratchpad
+
+:: my-3array ( x y z -- array ) { x y z } ;
+1 "two" 3.0 my-3array ."""
+"""{ 1 "two" 3.0 }"""
+} ;
                                                  
 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."
+"Certain data type literals are permitted to contain local variables. Any such literals are rewritten into code which constructs an instance of the type with the values of the variables spliced in. Conceptually, this is similar to the transformation applied to quotations containing free variables."
 $nl
 "The data types which receive this special handling are the following:"
 { $list

"Conceptually, " { $link curry } " is defined so that the following two code snippets are equivalent:"
{ $code "3 [ - ] curry" }
{ $code "[ 3 - ]" }
"With lambdas, " { $link curry } " behaves differently. Rather than prepending an element, it fills in named parameters from right to left. The following two snippets are equivalent:"
{ $code "3 [| a b | a b - ] curry" }
{ $code "[| a | a 3 - ]" }
"Because of this, the behavior of fry changes when applied to a lambda, to ensure that conceptually, fry behaves as with quotations. So the following snippets are no longer equivalent:"
{ $code "'[ [| a | _ a - ] ]" }
{ $code "'[ [| a | a - ] curry ] call" }
"Instead, the first line above expands into something like the following:"
{ $code "[ [ swap [| a | a - ] ] curry call ]" }
"This ensures that the fried value appears “underneath” the local variable " { $snippet "a" } " when the quotation calls."
$nl
"The precise behavior is the following. When frying a lambda, a stack shuffle (" { $link mnswap } ") is prepended to the lambda so that the " { $snippet "m" } " curried values, which start off at the top of the stack, are transposed with the " { $snippet "n" } " inputs to the lambda." ;

ARTICLE: "locals-limitations" "Limitations of locals"
"There are two main limitations of the current locals implementation, and both concern macros."

}
"Lexical binding forms:"
{ $subsections
    POSTPONE: :>
    POSTPONE: [let
    POSTPONE: [let*
    POSTPONE: [wlet
}
"Quotation literals where the inputs are named local variables:"
{ $subsections POSTPONE: [| }
"Additional topics:"
{ $subsections
    "locals-literals"
