]> gitweb.factorcode.org Git - factor.git/commitdiff
help.tour: touch-up and testing done
authorrazetime <raghuallthetime@hotmail.com>
Mon, 5 Dec 2022 10:23:08 +0000 (15:53 +0530)
committerJohn Benediktsson <mrjbq7@gmail.com>
Tue, 6 Dec 2022 03:51:08 +0000 (19:51 -0800)
extra/help/tour/tour.factor

index 517166e332c95afddddb2ad749f1f90cc7e3def6..53a17bab1df109d59a90078b1fb566be02ad092e 100644 (file)
@@ -8,14 +8,15 @@ parser prettyprint ranges see sequences stack-checker strings
 threads tools.crossref tools.test tools.time ui.gadgets.panes
 ui.tools.deploy vocabs vocabs.loader vocabs.refresh words
 io.servers http io.sockets io.launcher channels 
-concurrency.distributed channels.remote ;
+concurrency.distributed channels.remote help.cookbook
+splitting.private ;
 IN: help.tour
 
 ARTICLE: "tour-concatenative" "Concatenative Languages" 
-Factor is a { $emphasis concatenative } programming language in the spirit of Forth. What does this mean?
+Factor is a { $emphasis concatenative } programming language in the spirit of Forth. What is a concatenative language?
 
-To understand concatenative programming, imagine a world where every value is a function, and the only operation 
-allowed is function composition. Since function composition is so pervasive, it is implicit, and functions can be literally 
+To understand concatenative programming, imagine a world where every value is a function, and the only operation
+allowed is function composition. Since function composition is so pervasive, it is implicit, and functions can be 
 juxtaposed in order to compose them. So if { $snippet "f" } and { $snippet "g" } are two functions, their composition is just { $snippet "f g" } (unlike in 
 mathematical notation, functions are read from left to right, so this means first execute { $snippet "f" } , then execute { $snippet "g" } ).
 
@@ -31,7 +32,7 @@ routines mutating global variables.
 
 It works well in practice to represent the state of the world as a stack. Functions can only refer to the topmost 
 element of the stack, so that elements below it are effectively out of scope. If a few primitives are given to manipulate a 
-few elements on the stack (e.g., { $snippet "swap" } , that exchanges the top two elements on the stack), then it becomes possible to 
+few elements on the stack (e.g., { $link swap } , that exchanges the top two elements on the stack), then it becomes possible to 
 refer to values down the stack, but the farther the value is down the stack, the harder it becomes to refer to it.
 
 So, functions are encouraged to stay small and only refer to the top two or three elements on the stack. In a sense, 
@@ -41,7 +42,6 @@ distance from the top of the stack.
 Notice that if every function takes the state of the whole world and returns the next state, its input is never used 
 anymore. So, even though it is convenient to think of pure functions as receiving a stack as input and outputting a stack,
 the semantics of the language can be implemented more efficiently by mutating a single stack.
-
 ;
 
 ARTICLE: "tour-stack" "Playing with the stack"
@@ -70,12 +70,14 @@ $nl
 $nl
 You can put additional inputs in a single line, so for instance { $snippet "- *" } will leave the single number { $snippet "15" } on the stack (do you see why?).
 
+You may end up pushing many values to the stack, or end up with an incorrect result. You can then clear the stack with the
+keystroke { $snippet "Alt+Shift+K" } .
+
 The function { $snippet "." } (a period or a dot) prints the item at the top of the stack, while popping it out of the stack, leaving the stack empty.
 
 If we write everything on one line, our program so far looks like
 
-{ $code "5 7 3 1 + - * ."
-}
+{ $code "5 7 3 1 + - * ." }
 $nl
 which shows Factor's peculiar way of doing arithmetic by putting the arguments first and the operator last - a 
 convention which is called Reverse Polish Notation (RPN). Notice that 
@@ -84,16 +86,13 @@ the operator comes first, and RPN requires no precedence rules, unlike the infix
 used in most programming languages and in everyday arithmetic. For instance in any Lisp, the same 
 computation would be written as
 
-{ $code "(* 5 (- 7 (+ 3 1)))"
-}
+{ $code "(* 5 (- 7 (+ 3 1)))" }
 $nl
 and in familiar infix notation
 
-{ $code "(7 - (3 + 1)) * 5"
-}
+{ $code "(7 - (3 + 1)) * 5" }
 $nl
 Also notice that we have been able to split our computation onto many lines or combine it onto fewer lines rather arbitrarily, and that each line made sense in itself.
-
 ;
 
 ARTICLE: "tour-first-word" "Defining our first word" 
@@ -120,13 +119,13 @@ option and proceed.
 You should now have on your stack a rather opaque structure which looks like
 
 { $code "T{ range f 1 10 1 }" }
-
+$nl
 This is because our range functions are lazy and only create the range when we attempt to use it. To confirm that we 
 actually created the list of numbers from { $snippet "1" }  to { $snippet "10" } , we convert the lazy response on the 
 stack into an array using the word { $link >array } . Enter that word and your stack should now look like
 
 { $code "{ 1 2 3 4 5 6 7 8 9 10 }" }
-
+$nl
 which is promising!
 
 Next, we want to take the product of those numbers. In many functional languages, this could be done with a function 
@@ -141,9 +140,9 @@ Now, { $link reduce }  usually takes three arguments: a sequence (and we had one
 
 If we had written just { $link * } , Factor would have tried to apply multiplication to the topmost two elements 
 on the stack, which is not what we wanted. What we need is a way to get a word onto the stack without applying it. 
-Keeping to our textual metaphor, this mechanism is called { $strong "quotation" } . To quote one or more words, you just surround them 
-by { $snippet "[" }  and { $snippet "]" }  (leaving spaces!). What you get is akin to an anonymous function in other 
-languages.
+Keeping to our textual metaphor, this mechanism is called { $strong "quotation" } . To quote one or more words, you just surround them 
+with { $link POSTPONE: [ }  and { $link POSTPONE: ] }  (leaving spaces!). What you get is an anonymous function, which can be
+shuffled around, manipulated and called.
 
 Let's type the word { $link drop }  into the listener to empty the stack, and try writing what we have done so 
 far in a single line: { $snippet "10 [1..b] 1 [ * ] reduce" } . This will leave { $snippet "3628800" }  on the stack as 
@@ -151,12 +150,12 @@ expected.
 
 We now want to define a word for factorial that can be used whenever we want a factorial. We will call our word { $snippet "fact" }
 "(" although { $snippet "!" }  is customarily used as the symbol for factorial, in Factor { $snippet "!" }  
-is the word used for comments ")" . To define it, we first need to use the word { $snippet ":" } . Then we put the name of 
-the word being defined, then the { $strong "stack effects" }  and finally the body, ending with the { $snippet ";" }  word:
+is the word used for comments ")" . To define it, we first need to use the word { $link POSTPONE: : } . Then we put the name of 
+the word being defined, then the { $strong "stack effects" }  and finally the body, ending with the { $link POSTPONE: ; }  word:
 
 { $code ": fact ( n -- n! ) [1..b] 1 [ * ] reduce ;" }
-
-What are stack effects? In our case it is the { $snippet "( n -- n! )" } . Stack effects are how you document the 
+$nl
+What is a stack effect? In our case it is { $snippet "( n -- n! )" } . Stack effects are how you document the 
 inputs from the stack and outputs to the stack for your word. You can use any identifier to name the stack elements, here we 
 use { $snippet "n" } . Factor will perform a consistency check that the number of inputs and outputs you specify agrees 
 with what the body does.
@@ -164,13 +163,12 @@ with what the body does.
 If you try to write
 
 { $code ": fact ( m n -- ..b ) [1..b] 1 [ * ] reduce ;" }
-
-Factor will signal an error that the 2 inputs "(" { $snippet "m" }  and { $snippet "n" } ) are not consistent with the 
+$nl
+Factor will signal an error that the 2 inputs { $snippet "m" }  and { $snippet "n" } are not consistent with the 
 body of the word. To restore the previous correct definition press { $snippet "Ctrl+P" }  two times to get back to the 
 previous input and then enter it.
 
-We can think at the stack effects in definitions both as a documentation tool and as a very simple type system, which 
-nevertheless does catch a few errors.
+The stack effects in definitions  act both as a documentation tool and as a very simple type system, which helps to catch a few errors.
 
 In any case, you have succesfully defined your first word: if you write { $snippet "10 fact" }  in the listener you 
 can prove it.
@@ -179,37 +177,36 @@ Notice that the { $snippet "1 [ * ] reduce" }  part of the definition sort of ma
 
 { $code ": prod ( {x1,...,xn} -- x1*...*xn ) 1 [ * ] reduce ;
 : fact ( n -- n! ) [1..b] prod ;" }
-
+$nl
 Our definitions have become simpler and there was no need to pass parameters, rename local variables, or do anything 
 else that would have been necessary to refactor our function in most languages.
 
-Of course, Factor already has a word for the factorial (actually there is a whole { $vocab-link "math.factorials" }  
-vocabulary, including many variants of the usual factorial) and a word for the product "(" { $link product }  in the 
-{ $vocab-link "sequences" }  vocabulary), but as it often happens introductory examples overlap with the standard library.
-
+Of course, Factor already has a word for calculating factorial (there is a whole { $vocab-link "math.factorials" }  
+vocabulary, including many variants of the usual factorial) and a word for calculating product "(" { $link product }  in the 
+{ $vocab-link "sequences" }  vocabulary), but as it often happens, introductory examples overlap with the standard library.
 ;
 
 ARTICLE: "tour-parsing-words" "Parsing Words"
-If you've been paying close attention so far, you realize I've lied to you. I said each word acts on the stack in order
-, but there a few words like { $snippet "[" } , { $snippet "]" } , { $snippet ":" } and { $snippet ";" } that don't seem to follow this rule.
+If you've been paying close attention so far, you will realize that you have been lied to. { $emphasis "Most" } words act on the stack in order
+, but there a few words like { $link POSTPONE: [ } , { $link POSTPONE: ] } , { $link POSTPONE: : } and { $link POSTPONE: ; } that don't seem to follow this rule.
 
-These are { $strong "parsing words" }  and they behave differently from simpler words like { $snippet "5" } , { $link [1..b] } or { $link drop } . We will cover 
+These are { $strong "parsing words" }  and they behave differently from ordinary words like { $snippet "5" } , { $link [1..b] } or { $link drop } . We will cover 
 these in more detail when we talk about metaprogramming, but for now it is enough to know that parsing words are special.
 
-They are not defined using the { $snippet ":" } word, but with the word { $snippet "SYNTAX:" } instead. When a parsing words is encountered, it 
-can interact with the parser using a well-defined API to influence how successive words are parsed. For instance { $snippet ":" } 
-asks for the next tokens from the parsers until { $snippet ";" } is found and tries to compile that stream of tokens into a word 
+They are not defined using the { $link POSTPONE: : } word, but with the word { $link POSTPONE: SYNTAX: } instead. When a parsing words is encountered, it 
+can interact with the parser using a well-defined API to influence how successive words are parsed. For instance { $link POSTPONE: : } 
+asks for the next token from the parser until { $link POSTPONE: ; } is found and tries to compile that stream of tokens into a word 
 definition.
 
-A common use of parsing words is to define literals. For instance { $snippet "{" } is a parsing word that starts an array 
-definition and is terminated by { $snippet "} " } . Everything in-between is part of the array. An example of array that we have seen before is 
+A common use of parsing words is to define literals. For instance { $link POSTPONE: { } is a parsing word that starts an array 
+definition and is terminated by { $link POSTPONE: } } . Everything in-between is part of the array. An example of array that we have seen before is 
 { $snippet "{ 1 2 3 4 5 6 7 8 9 10 } " } .
 
 There are also literals for hashmaps, { $snippet "H{ { \"Perl\" \"Larry Wall\" } { \"Factor\" \"Slava Pestov\" } { \"Scala\" \"Martin Odersky\" } } " }
 , and byte arrays, { $snippet "B{ 1 14 18 23 } " } .
 
-Other uses of parsing word include the module system, the object-oriented features of Factor, enums, memoized functions
-, privacy modifiers and more. In theory, even { $snippet "SYNTAX:" } can be defined in terms of itself, although of course the 
+Other uses of parsing words include the module system, the object-oriented features of Factor, enums, memoized functions
+, privacy modifiers and more. In theory, even { $link POSTPONE: SYNTAX: } can be defined in terms of itself, but the 
 system has to be bootstrapped somehow.
 
 ;
@@ -223,7 +220,7 @@ requires mentally simulating moving values on a stack, which is not a natural wa
 see a much more effective way to handle most needs.
 
 Here is a list of the most common shuffling words together with their effect on the stack. Try them in the listener to 
-get a feel for how they manipulate the stack using the listener.
+get a feel for how they manipulate the stack.
 { $subsections
   dup
   drop
@@ -237,6 +234,7 @@ get a feel for how they manipulate the stack using the listener.
   2dup
 }
 
+For a deeper look at stack shuffling, see the { $link "cookbook-colon-defs" } .
 ;
 
 ARTICLE: "tour-combinators" "Combinators"
@@ -254,48 +252,54 @@ what we need. For instance { $snippet "5 [ 2 * ] [ 3 + ] bi" }  yields
 { $code "
 10
 8
-" } { $link bi }  applies the quotation { $snippet "[ 2 * ]" }  to the value { $snippet "5" }  and then the quotation { $snippet "[ 3 + ]" }  to the value { $snippet "5" }  leaving us 
+" }
+$nl
+{ $link bi }  applies the quotation { $snippet "[ 2 * ]" }  to the value { $snippet "5" }  and then the quotation { $snippet "[ 3 + ]" }  to the value { $snippet "5" }  leaving us 
 with { $snippet "10" }  and then { $snippet "8" }  on the stack. Without { $link bi } , we would have to first { $link dup }  { $snippet "5" } , then multiply, and then { $link swap }  the 
 result of the multiplication with the second { $snippet "5" } , so we could do the addition
 { $code "
 5 dup 2 * swap 3 +
 " }
+$nl
 You can see that { $link bi }  replaces a common pattern of { $link dup } , then calculate, then { $link swap }  and calculate again.
 
-To continue our prime example, we need a way to make a range starting from { $snippet "2" } . We can define our own word for this { $snippet "[2..b]" } 
-, using the { $link [a..b] } range word we discussed earlier.
+To continue our prime example, we need a way to make a range starting from { $snippet "2" } . We can define our own word for this { $snippet "[2..b]" } , using the { $link [a..b] } word:
 { $code "
 : [2..b] ( n -- {2,...,n} ) 2 swap [a..b] ; inline
 " }
+$nl
 What's up with that { $snippet "inline" }  word? This is one of the modifiers we can use after defining a word, another one being 
 { $snippet "recursive" } . This will allow us to have the definition of a short word inlined wherever it is used, rather than incurring 
 a function call.
 
-Try our new { $snippet "[2..b]" }  word and see that it works
+Try our new { $snippet "[2..b]" }  word and see that it works:
 { $code "
 6 [2..b] >array .
 " }
+$nl
 Using { $snippet "[2..b]" }  to produce the range of numbers from { $snippet "2" }  to the square root of an { $snippet "n" }  that is already on the stack is 
 easy: { $snippet "sqrt floor [2..b]" }  (technically { $link floor }  isn't necessary here, as { $link [a..b] }  works for non-integer bounds). Let's try 
 that out
 { $code "
 16 sqrt [2..b] >array .
 " }
+$nl
 Now, we need a word to test for divisibility. A quick search in the online help shows that { $link divisor? }  is the word we 
-want. It will help to have the arguments for testing divisibility in the other direction, so we define { $snippet "multiple?" } 
+want. It will help to have the arguments for testing divisibility in the other direction, so we define { $snippet "multiple?" } ":"
 { $code "
 : multiple? ( a b -- ? ) swap divisor? ; inline
 " }
-Both of these return { $link t } 
+We can verify that both of these return { $link t } .
 { $code "
 9 3 divisor? .
 3 9 multiple? .
 " }
-If we're going to use { $link bi }  in our { $snippet "prime" }  definition, as we implied above, we need a second quotation. Our second 
+$nl
+Since we're going to use { $link bi } in our { $snippet "prime?" }  definition, we need a second quotation. Our second 
 quotation needs to test for a value in the range being a divisor of { $snippet "n" }  - in other words we need to partially apply the word  { $snippet "multiple?" } . This can be done with the word { $link curry } , like this: { $snippet "[ multiple? ] curry" } .
 
 Finally, once we have the range of potential divisors and the test function on the stack, we can test whether any 
-element satisfied divisibility with { $link any? }  and then negate that answer with { $snippet "not" } . Our full definition of { $snippet "prime" }  looks like
+element satisfied divisibility with { $link any? }  and then negate that answer with { $link not } . Our full definition of { $snippet "prime" }  looks like
 { $code "
 : prime? ( n -- ? ) [ sqrt [2..b] ] [ [ multiple? ] curry ] bi any? not ;
 " }
@@ -307,7 +311,7 @@ quotation contains the word { $link curry } , which also operates on a quotation
 using one level of nesting for each higher-order function, unlike Lisps or more generally languages based on the lambda 
 calculus, which use one level of nesting for each function, higher-order or not.
 
-Many more combinators exists other than { $link bi }  (and its relative { $link tri } ), and you should become acquainted at least with 
+{ $link bi } and its relative { $link tri } are a small subset of the shuffle words you will use in Factor. You ahouls also become familiar with 
 { $link bi } , { $link tri } , and { $link bi@ } by reading about them in the online help and trying them out in the listener.
 
 ;
@@ -315,23 +319,23 @@ Many more combinators exists other than { $link bi }  (and its relative { $link
 ARTICLE: "tour-vocabularies" "Vocabularies"
 
 It is now time to start writing your functions in files and learn how to import them in the listener. Factor organizes 
-words into nested namespaces called { $strong "vocabularies" } . You can import all names from a vocabulary with the word { $snippet "USE:" } . 
+words into nested namespaces called { $strong "vocabularies" } . You can import all names from a vocabulary with the word { $link POSTPONE: USE: } . 
 In fact, you may have seen something like
 
 { $code "USE: ranges" }
 
 when you asked the listener to import the word { $link [1..b] } for you. You can also use more than one vocabulary at a time 
-with the word { $snippet "USING:" } , which is followed by a list of vocabularies and terminated by { $snippet ";" } , like
+with the word { $link  POSTPONE: USING: } , which is followed by a list of vocabularies and terminated by { $link POSTPONE: ; } , like
 
 { $code "USING: math.ranges sequences.deep ;" }
-
-Finally, you define the vocabulary where your definitions are stored with the word { $snippet "IN:" } . If you search the online 
+$nl
+Finally, you define the vocabulary where your definitions are stored with the word { $link POSTPONE: IN: } . If you search the online 
 help for a word you have defined so far, like { $link prime? } , you will see that your definitions have been grouped under the 
-default { $snippet "scratchpad" } vocabulary. By the way, this shows that the online help automatically collects information about your 
+default { $vocab-link "scratchpad" } vocabulary. By the way, this shows that the online help automatically collects information about your 
 own words, which is a very useful feature.
 
-There are a few more words, like { $snippet "QUALIFIED:" } , { $snippet "FROM:" } , { $snippet "EXCLUDE:" } and { $snippet "RENAME:" } , that allow more fine-grained control 
-over the imports, but { $snippet "USING:" } is the most common.
+There are a few more words, like { $link POSTPONE: QUALIFIED: } , { $link POSTPONE: FROM: } , { $link POSTPONE: EXCLUDE: } and { $link POSTPONE: RENAME: } , that allow more fine-grained control 
+over the imports, but { $link POSTPONE: USING: } is the most common.
 
 On disk, vocabularies are stored under a few root directories, much like with the classpath in JVM languages. By 
 default, the system starts looking up into the directories { $snippet "basis" } , { $snippet "core" } , { $snippet "extra" } , { $snippet "work" } under the Factor home. You can 
@@ -364,7 +368,7 @@ IN: github.tutorial
 Since the vocabulary was already loaded when you scaffolded it, we need a way to refresh it from disk. You can do this 
 with { $snippet "\"github.tutorial\" refresh" } . There is also a { $link refresh-all } word, with a shortcut { $snippet "F2" } .
 
-You will be prompted a few times to use vocabularies, since your { $snippet "USING:" } statement is empty. After having accepted 
+You will be prompted a few times to use vocabularies, since your { $link POSTPONE: USING: } statement is empty. After having accepted 
 all of them, Factor suggests you a new header with all the needed imports:
 { $code "
 USING: kernel math.functions math.ranges sequences ;
@@ -375,7 +379,7 @@ will find your editor open on the relevant line of the right file. This also wor
 although it may be a bad idea to modify them.
 
 This { $snippet "\\" } word requires a little explanation. It works like a sort of escape, allowing us to put a reference to the 
-next word on the stack, without executing it. This is exactly what we need, because { $snippet "edit" } is a word that takes words 
+next word on the stack, without executing it. This is exactly what we need, because { $link edit } is a word that takes words 
 themselves as arguments. This mechanism is similar to quotations, but while a quotation creates a new anonymous function, 
 here we are directly refering to the word { $snippet "multiple?" } .
 
@@ -393,11 +397,13 @@ PRIVATE>
 " }
 
 After making this change and refreshed the vocabulary, you will see that the listener is not able to refer to words 
-like { $snippet "[2..b]" } anymore. The { $snippet "<PRIVATE" } word works by putting all definitions in the private block under a different 
+like { $snippet "[2..b]" } anymore. The { $link POSTPONE: <PRIVATE } word works by putting all definitions in the private block under a different 
 vocabulary, in our case { $snippet "github.tutorial.private" } .
 
+You can have more than one { $link POSTPONE: <PRIVATE } block in a vocabulary, so feel free to organize them as you find necessary.
+
 It is still possible to refer to words in private vocabularies, as you can confirm by searching for { $snippet "[2..b]" } in the 
-online help, but of course this is discouraged, since people do not guarantee any API stability for private words. Words 
+browser, but of course this is discouraged, since people do not guarantee any API stability for private words. Words 
 under { $snippet "github.tutorial" } can refer to words in { $snippet "github.tutorial.private" } directly, like { $link prime? } does.
 
 ;
@@ -417,7 +423,7 @@ USING: tools.test github.tutorial ;
 that imports the unit testing module as well as your own. We will only test the public { $snippet "prime?" }  function.
 
 Tests are written using the { $link POSTPONE: unit-test }  word, which expects two quotations: the first one containing the expected 
-outputs and the second one containing the words to run in order to get that output. Add these lines to 
+outputs, and the second one containing the words to run in order to get that output. Add these lines to 
 { $snippet "github.tutorial-tests" } ":"
 
 { $code "
@@ -429,6 +435,7 @@ outputs and the second one containing the words to run in order to get that outp
 [ f ] [ 1 prime? ] unit-test
 [ t ] [ 20750750228539 prime? ] unit-test
 " }
+$nl
 You can now run the tests with { $snippet "\"github.tutorial\" test" } . You will see that we have actually made a mistake, and 
 pressing { $snippet "F3" }  will show more details. It seems that our assertions fails for { $snippet "2" } .
 
@@ -437,17 +444,17 @@ for { $snippet "2 sqrt" } , due to the fact that the square root of two is less
 fix so that the tests now pass.
 
 There are a few more words to test errors and inference of stack effects. { $link POSTPONE: unit-test }  suffices for now, but later on 
-you may want to check { $link POSTPONE: must-fail }  and { $link POSTPONE: must-infer } .
+you may want to check the main documentation on { $link "tools.test" } .
 
 We can also add some documentation to our vocabulary. Autogenerated documentation is always available for user-defined 
 words (even in the listener), but we can write some useful comments manually, or even add custom articles that will 
-appear in the online help. Predictably, we start with { $snippet "\"github.tutorial\" scaffold-docs" }  and then 
+appear in the online help. Predictably, we start with { $snippet "\"github.tutorial\" scaffold-docs" }  and 
 { $snippet "\"github.tutorial\" edit-docs" } .
 
 The generated file { $snippet "work/github/tutorial-docs.factor" }  imports { $vocab-link "help.markup" } and { $vocab-link "help.syntax" } . These two vocabularies 
-define words to generate documentation. The actual help page is generated by the { $snippet "HELP:" }  parsing word.
+define words to generate documentation. The actual help page is generated by the { $link POSTPONE: HELP: }  parsing word.
 
-The arguments to { $snippet "HELP:" }  are nested array of the form { $snippet "{ $directive content... }" } . In particular, you see here the 
+The arguments to { $link POSTPONE: HELP: }  are nested array of the form { $snippet "{ $directive content... }" } . In particular, you see here the 
 directives { $link $values } and { $link $description } , but a few more exist, such as { $link $errors } , { $link $examples }  and { $link $see-also } .
 
 Notice that the type of the output { $snippet "?" }  has been inferred to be boolean. Change the first lines to look like
@@ -524,7 +531,8 @@ We can also shorten this to
 { \"Hugh Jackman\" \"Christian Bale\" \"Scarlett Johansson\" }
 movie boa
 " }
-The word { $link boa } stands for 'by-order-of-arguments' and is a constructor that fills the slots of the tuple with the 
+$nl
+The word { $link boa } stands for 'by-order-of-arguments'. It is a constructor that fills the slots of the tuple with the 
 items on the stack in order. { $snippet "movie boa" } is called a { $strong "boa constructor" } , a pun on the Boa Constrictor. It is customary to 
 define a most common constructor called { $snippet "<movie>" } , which in our case could be simply
 
@@ -578,14 +586,14 @@ classes.
 Builtin and tuple classes are not all that there is to the object system: more classes can be defined with set 
 operations like { $link POSTPONE: UNION: } and { $link POSTPONE: INTERSECTION: } . Another way to define a class is as a { $strong "mixin" } .
 
-Mixins are defined with the { $snippet "MIXIN:" } word, and existing classes can be added to the mixin writing
+Mixins are defined with the { $link POSTPONE: MIXIN: } word, and existing classes can be added to the mixin like so:
 
 { $code "
 INSTANCE: class mixin
 " }
 Methods defined on the mixin will then be available on all classes that belong to the mixin. If you are familiar with 
 Haskell typeclasses, you will recognize a resemblance, although Haskell enforces at compile time that instance of 
-typeclasses implent certain functions, while in Factor this is informally specified in documentation.
+typeclasses implement certain functions, while in Factor this is informally specified in documentation.
 
 Two important examples of mixins are { $link sequence } and { $link assoc } . The former defines a protocol that is available to all 
 concrete sequences, such as strings, linked lists or arrays, while the latter defines a protocol for associative arrays, 
@@ -609,7 +617,7 @@ You have seen some examples of this:
   {  " The "  { $link edit  }  " word gives you editor integration, but you can also click on file names in the help pages for vocabularies to open them. "  }
 }
 
-The refresh is actually quite smart. Whenever a word is redefined, words that depend on it are recompiled against the new 
+The refresh is an efficient mechanism. Whenever a word is redefined, words that depend on it are recompiled against the new 
 defition. You can check by yourself doing
 
 { $code "
@@ -623,10 +631,10 @@ and then
 : inc ( x -- y ) 2 + ;
 5 inc-print
 " }
-This allows you to always keep a listener open, improving your definitions, periodically saving your definitions to file 
-and refreshing, without ever having to reload Factor.
+This allows you to keep a listener open, improve your definitions, periodically save your definitions to a file 
+and refresh to view your changes, without ever having to reload Factor.
 
-You can also save the whole state of Factor with the word { $link save-image } and later restore it by starting Factor with
+You can also save the state of your current session with the word { $link save-image } and later restore it by starting Factor with
 
 { $code "
 ./factor -i=path-to-image
@@ -647,40 +655,39 @@ You will get an item that looks like
 { $code "
 { ~trilogy~ \"George Lucas\" }
 " }
-on the stack. Try clicking on it: you will be able to see the slots of the array and focus on the trilogy or on the string 
-by double-clicking on them. This is extremely useful for interactive prototyping. Special objects can customize the inspector 
+on the stack. Try clicking on it: you will be able to see the slots of the array. You can inspect a slot shown in the inspector by double clicking on it. This is extremely useful for interactive prototyping. Special objects can customize the inspector 
 by implementing the { $link content-gadget } method.
 
 There is another inspector for errors. Whenever an error arises, it can be inspected with { $snippet "F3" } . This allows you to investigate 
-exceptions, bad stack effects declarations and so on. The debugger allows you to step into code, both forwards and 
+exceptions, bad stack effect declarations and so on. The debugger allows you to step into code, both forwards and 
 backwards, and you should take a moment to get some familiarity with it. You can also trigger the debugger manually, by 
 entering some code in the listener and pressing { $snippet "Ctrl+w" } .
 
-Another feature of the listener allows you to benchmark code. As an example, we write an intentionally inefficient Fibonacci:
+The listener has provisions for benchmarking code. As an example, here is an intentionally inefficient Fibonacci:
 
 { $code "
 DEFER: fib-rec
 : fib ( n -- f(n) ) dup 2 < [ ] [ fib-rec ] if ;
 : fib-rec ( n -- f(n) ) [ 1 - fib ] [ 2 - fib ] bi + ;
 " }
-(notice the use of { $snippet "DEFER:" } to define two mutually "recursive" words). You can benchmark the running time writing { $snippet "40 fib" }  
+(notice the use of { $link POSTPONE: DEFER: } to define two mutually "recursive" words). You can benchmark the running time writing { $snippet "40 fib" }  
 and then pressing Ctrl+t instead of Enter. You will get timing information, as well as other statistics. Programmatically
 , you can use the { $link time } word on a quotation to do the same.
 
 You can also add watches on words, to print inputs and outputs on entry and exit. Try writing
 
 { $code "
-\ fib watch
+\\ fib watch
 " }
 and then run { $snippet "10 fib" }  to see what happens. You can then remove the watch with { $snippet "\\ fib reset" } .
 
-Another very useful tool is the { $vocab-link "lint" }  vocabulary. This scans word definitions to find duplicated code that can be factored 
+Another useful tool is the { $vocab-link "lint" }  vocabulary. This scans word definitions to find duplicated code that can be factored 
 out. As an example, let us define a word to check if a string starts with another one. Create a test vocabulary
 
 { $code "
 \"lintme\" scaffold-work
 " }
-and add the following definition
+and add the following definition:
 
 { $code "
 USING: kernel sequences ;
@@ -689,10 +696,10 @@ IN: lintme
 : startswith? ( str sub -- ? ) dup length swapd head = ;
 " }
 Load the lint tool with { $snippet "USE: lint" }  and write { $snippet "\"lintme\" lint-vocab" } . You will get a report mentioning that the word sequence 
-{ $snippet "length swapd" }  is already used in the word { $snippet "(split)" } of { $snippet "splitting.private" } , hence it could be factored out.
+{ $snippet "length swapd" }  is already used in the word { $link (split) } of { $vocab-link "splitting.private" } , hence it could be factored out.
 
-Now, you would not certainly want to modify the source of a word in the standard library - let alone a private one - but 
-in more complex cases the lint tool is able to find actual repetitions. It is a good idea to lint your vocabularies from 
+Modifying the source of a word in the standard library is unadvisable - let alone a private one - but 
+in more complex cases the lint tool can help you prevent code duplication. It is not unusual that Factor has a word that does exactly what you want, owing to its massive standard library. It is a good idea to lint your vocabularies from 
 time to time, to avoid code duplication and as a good way to discover library words that you may have accidentally redefined
 .
 
@@ -738,7 +745,7 @@ c g t, instead of valid Factor words. Let us start with a simple approximation t
 delimiters and outputs the string obtained by concatenation
 
 { $code "
-SYNTAX: DNA{ \"}\" parse-tokens concat suffix!
+SYNTAX: DNA{ \"}\" parse-tokens concat suffix! ;
 " }
 You can test the effect by doing { $snippet "DNA{ a ccg t a g }" } , which should output { $snippet "\"accgtag\"" } . As a second approximation, we 
 transform each letter into a boolean pair:
@@ -761,11 +768,12 @@ If you try it with { $snippet "DNA{ a ccg t a g }" } you should get
 { $code "
 { $snippet \"?{ f f t t t t f t t f f f f t }\" }
 " }
-Let us make another very simple example, stolen from [John Benediktsson](http://re-factor.blogspot.it/2014/06/swift-ranges.html), 
-which is about infix syntax for ranges. Until now, we have used { $link [a..b] } to create a range. We can make a 
+
+Let us try an example from { $url "http://re-factor.blogspot.it/2014/06/swift-ranges.html" "Re-Factor" } , 
+which adds infix syntax for ranges. Until now, we have used { $link [a..b] } to create a range. We can make a 
 syntax that is friendlier to people coming from other languages using { $snippet "..." } as an infix word.
 
-We can use { $link scan-object } to ask the parser for the next parsed object, and { $snippet "unclip-last" } to get the top element from 
+We can use { $link scan-object } to ask the parser for the next parsed object, and { $link unclip-last } to get the top element from 
 the accumulator vector. This way, we can define { $snippet "..." } simply with
 
 { $code "
@@ -777,17 +785,16 @@ We only scratched the surface of parsing words; in general, they allow you to pe
 compile time, enabling powerful forms of metaprogramming.
 
 In a sense, Factor syntax is completely flat, and parsing words allow you to introduce syntaxes more complex than a 
-stream of tokens to be used locally. This permits to increase the Factor language by adding many new features as libraries
+stream of tokens to be used locally. This lets any programmer expand the language by adding these syntactic features in libraries
 . In principle, it would even be possible to have an external language compile to Factor - say JavaScript - and embed it 
-as a Factor DSL inside the boundaries of a { $snippet "<JS ... JS>" } parsing word. Some taste is needed not to abuse too much of 
+as a domain-specific language in the boundaries of a { $snippet "<JS ... JS>" } parsing word. Some taste is needed not to abuse too much of 
 this to introduce styles that are much too alien in the concatenative world.
 ;
 
 ARTICLE: "tour-stack-ne" "When the stack is not enough"
 
-Until now I have cheated a bit, and tried to avoid writing examples that would have been too complex to write in 
-concatenative style. Truth is, you *will* find occasions where this is too restrictive. Fortunately, parsing words allow you 
-to break these restrictions, and Factor comes with a few to handle the most common annoyances.
+Until now we have cheated a bit, and tried to avoid writing examples that would have been too complex to write in 
+concatenative style. Truth is, you { $emphasis "will" } find occasions where this is too restrictive. Parsing words can ease some of these restrictions, and Factor comes with a few to handle the most common annoyances.
 
 One thing you may want to do is to actually name local variables. The { $link POSTPONE: :: } word works like { $link POSTPONE: : } , but allows you to 
 actually bind the name of stack parameters to variables, so that you can use them multiple times, in the order you want. For 
@@ -820,8 +827,7 @@ scope where to bind local variables outside definitions using { $link POSTPONE:
 concatenative code with some stack shuffling. I encourage you to browse examples for these words, but bear in mind that 
 their usage in practice is actually much less prominent than one would expect - about 1% of Factor's own codebase.
 
-Another more common case happens when you need to specialize a quotation to some values, but these do not appear in 
-the right place. Remember that you can partially apply a quotation using { $link curry } . But this assumes that the value you are 
+Another common case happens when you need to add values to a quotation in specific places. You can partially apply a quotation using { $link curry } . This assumes that the value you are 
 applying should appear leftmost in the quotation; in the other cases you need some stack shuffling. The word { $link with }  is a 
 sort of partial application with a hole. It also curries a quotation, but uses the third element on the stack instead 
 of the second. Also, the resulting curried quotation will be applied to an element inserting it in the second position.
@@ -838,7 +844,7 @@ Using { $link with }  instead of { $link curry } , this simplifies to
 { $code "
     : prime? ( n -- ? ) 2 over sqrt [a,b] [ divisor? ] with any? not ;
 " }
-If you do not visualize what is happening, you may want to consider the { $vocab-link "fry" } vocabulary. It defines { $strong "fried quotations" } ";" 
+If you are not able to visualize what is happening, you may want to consider the { $vocab-link "fry" } vocabulary. It defines { $strong "fried quotations" } ";" 
 these are quotations that have holes in them - marked by { $snippet "_" } - that are filled with values from the stack.
 
 The first quotation is rewritten more simply as
@@ -847,7 +853,7 @@ The first quotation is rewritten more simply as
     [ '[ 2 _ sqrt [a,b] ] call ]
 " }
 Here we use a fried quotation - starting with { $link POSTPONE: '[ } - to inject the element on the top of the stack in the second 
-position, and then use { $snippet "call" } to evaluate the resulting quotation. The second quotation becomes simply
+position, and then use { $link call } to evaluate the resulting quotation. The second quotation can be rewritten as follows:
 
 { $code "
     [ '[ _ swap divisor? ] ]
@@ -865,7 +871,7 @@ Finally, there are times where one just wants to give names to variables that ar
 them where necessary. These variables can hold values that are global, or at least not local to a single word. A 
 typical example could be the input and output streams, or database connections.
 
-Factor allows you to create { $strong "dynamic variables" }  and bind them in scopes. The first thing is to create a { $strong "symbol" }  
+For this purpose, Factor allows you to create { $strong "dynamic variables" }  and bind them in scopes. The first thing is to create a { $strong "symbol" }  
 for a variable, say
 
 { $code "
@@ -885,25 +891,24 @@ Scopes are nested, and new scopes can be created with the word { $link with-scop
       favorite-language get .
     ] with-scope ;
 " }
-If you run { $snippet "on-the-jvm" } you will get { $snippet "\"Scala\"" } printed, but still after execution { $snippet "favorite-language get" } return { $snippet "\"Factor\"" } .
+If you run { $snippet "on-the-jvm" } , { $snippet "\"Scala\"" } will be printed, but after execution, { $snippet "favorite-language get" } will hold { $snippet "\"Factor\"" } as its value.
 
-All the tools that we have seen in this section should be used when necessary, as they break concatenativity and make 
-words less easy to factor, but they can greatly increase clarity when needed. Factor has a very practical approach and 
+All the tools that we have seen in this section should only be used when absolutely necessary, as they break concatenativity and make 
+words less easy to factor. However, they can greatly increase clarity when needed. Factor has a very practical approach and 
 does not shy from offering features that are less pure but nevertheless often useful.
 ;
 
 ARTICLE: "tour-io" "Input/Output"
 
-We now leave the tour of the language, and start investigating how to tour the outside world with Factor. I will begin in 
-this section with some examples of input/output, but inevitably this will lead into a discussion of asynchrony. The 
-rest of the tutorial will then go in more detail about parallel and distributed computing.
+We will now leave the tour of the language, and start investigating how to tour the outside world with Factor. This section will begin with basic input and output, and move on to asynchronous, parallel
+and distributed I/O.
 
 Factor implements efficient asynchronous input/output facilities, similar to NIO on the JVM or the Node.js I/O system. 
 This means that input and output operations are performed in the background, leaving the foreground task free to 
 perform work while the disk is spinning or the network is buffering packets. Factor is currently single threaded, but 
 asynchrony allows it to be rather performant for applications that are I/O-bound.
 
-All of Factor input/output words are centered on { $strong "streams" } . Streams are lazy sequences which can be read or written 
+All of Factor input/output words are centered on { $strong "streams" } . Streams are lazy sequences which can be read from or written 
 to, typical examples being files, network ports or the standard input and output. Factor holds a couple of dynamic 
 variables called { $link input-stream } and { $link output-stream } , which are used by most I/O words. These variables can be rebound locally 
 using { $link with-input-stream } , { $link with-output-stream } and { $link with-streams } . When you are in the listener, the default streams 
@@ -921,7 +926,7 @@ one is executed, and on failure, the second one is executed with the error as in
 { $code "
     : safe-head ( seq n -- seq' ) [ head ] [ 2drop ] recover ;
 " }
-This is mostly an occasion to show an example of exceptions, as Factor defines the { $link short } word, which takes a 
+This is an impractical example of exceptions, as Factor defines the { $link short } word, which takes a 
 sequence and a number, and returns the minimum between the length of the sequence and the number. This allows us to write simply
 
 { $code "
@@ -953,7 +958,7 @@ Factor helps us with { $link file-lines } , which lazily iterates "over" lines.
 When the file is small, one can also use { $link file-contents } to read the whole contents of a file in a single string. 
 Factor defines many more words for input/output, which cover many more cases, such as binary files or sockets.
 
-We end this section investigating some words to walk the filesystem. Our aim is a very minimal implementation of the { $snippet "ls" } command.
+We will end this section investigating some words to walk the filesystem. Our aim is a very minimal implementation of the { $snippet "ls" } command.
 
 The word { $link directory-entries } lists the contents of a directory, giving a list of tuple elements, each one having the 
 slots { $snippet "name" } and { $snippet "type" } . You can see this by trying { $snippet "\"/home\" directory-entries [ name>> ] map" } . If you inspect the 
@@ -1021,7 +1026,7 @@ define a word which runs { $snippet "ls" } on the first command-line argument wi
 { $code "
     : ls-run ( -- ) command-line get first ls ;
 " }
-Finally, we use the word { $snippet "MAIN:" } to declare the main word of our vocabulary:
+Finally, we use the word { $link POSTPONE: MAIN: } to declare the main word of our vocabulary:
 
 { $code "
     MAIN: ls-run
@@ -1062,9 +1067,9 @@ Although cooperative threads do not allow to make use of multiple cores, they st
 For the cases where one wants to make use of multiple cores, Factor offers the possibility of spawning other processes 
 and communicating between them with the use of { $strong "channels" } , as we will see in a later section.
 
-Threads in Factors are created out of a quotation and a name, with the { $link spawn } word. Let us use this to print the 
-first few lines of Star Wars, one per second, each line being printed inside its own thread. First, let us write those lines 
-inside a dynamic variable:
+Threads in Factor are created using a quotation and a name, with the { $link spawn } word. Let us use this to print the 
+first few lines of Star Wars, one per second, each line being printed inside its own thread. First, we will assign them to a 
+dynamic variable:
 
 { $code "
 SYMBOL: star-wars
@@ -1144,15 +1149,15 @@ simplifying the above to
   [ wait-and-print ] curry in-thread
 ] each
 " }
-
-This is good enough for our simple purpose. In serious applications theads will be long-running. In order to make them 
+$nl
+In serious applications theads will be long-running. In order to make them 
 cooperate, one can use the { $link yield } word to signal that the thread has done a unit of work, and other threads can gain 
 control. You also may want to have a look at other words to { $link stop } , { $link suspend } or { $link resume } threads.
 ;
 
 ARTICLE: "tour-servers" "Servers and Furnace"
 
-A very common case for using more than one thread is when writing server applications. When writing network 
+Server applications often use more than one thread. When writing network 
 applications, it is common to start a thread for each incoming connection (remember that these are green threads, so they are much 
 more lightweight than OS threads).
 
@@ -1160,10 +1165,9 @@ To simplify this, Factor has the word { $link spawn-server } , which works like
 quotation until it returns { $link f } . This is still a very low-level word: in reality one has to do much more: listen for TCP 
 connections on a given port, handle connection limits and so on.
 
-The vocabulary { $vocab-link "io.servers" } allows to write and configure TCP servers. A server is created with the word `<threaded-
-server>`, which requires an encoding as a parameter. Its slots can then be set to configure logging, connection limits, 
+The vocabulary { $vocab-link "io.servers" } allows to write and configure TCP servers. A server is created with the word { $link <threaded-server> } , which requires an encoding as a parameter. Its slots can then be set to configure logging, connection limits, 
 ports and so on. The most important slot to fill is { $snippet "handler" } , which contains a quotation that is executed for each 
-incoming connection. You can see a very simple example of server with
+incoming connection. You can see a simple example of a server with
 { $code "
 
     \"resource:extra/time-server/time-server.factor\" edit-file
@@ -1207,11 +1211,10 @@ Now, if this was all that Factor offers to write web applications, it would stil
 applications are usually written using a web framework called { $strong "Furnace" } .
 
 Furnace allows us - among other things - to write more complex actions using a template language. Actually, there are 
-two template languages shipped by default, and we will use { $strong "Chloe" } . Furnace allows us to use create { $strong "page actions" }  
+two template languages shipped by default, and we will use { $strong "Chloe" } . Furnace allows us to create { $strong "page actions" }  
 from Chloe templates, and in order to create a responder we will need to add routing.
 
-Let use first investigate a simple example of routing. To do this, we create a special type of responder called a **
-dispatcher**, that dispatches requests based on path parameters. Let us create a simple dispatcher that will choose 
+Let use first investigate a simple example of routing. To do this, we create a special type of responder called a { $strong "dispatcher" } , that dispatches requests based on path parameters. Let us create a simple dispatcher that will choose 
 between our echo responder and a default responder used to serve static files.
 { $code "
 
@@ -1281,17 +1284,15 @@ Reload the { $snippet "hello-furnace" } vocabulary and { $snippet "<example-resp
 the results of your efforts under { $url "http://localhost:8080/chloe" } . Notice that there was no need to restart the server, we 
 can change the main responder dynamically.
 
-This ends our very brief tour of Furnace. It actually does much more than this: form validation and handling, 
-authentication, logging and more. But this section is already getting too long, and you will have to find out more in the 
-documentation.
+This ends our very brief tour of Furnace. Furnace is much more expansive than the examples shown here,  as it allows for many general web
+tasks. You can learn more about it in the { $link "furnace" } documentation.
 ;
 
 ARTICLE: "tour-processes" "Processes and Channels"
 
 
-As I said, Factor is single-threaded from the point of view of the OS. If we want to make use of multiple cores, we 
-need a way to spawn Factor processes and communicate between them. Factor implements two different models of message-
-passing concurrency: the actor model, which is based on the idea of sending messages asynchronously between threads, and the 
+As discussed earlier, Factor is single-threaded from the point of view of the OS. If we want to make use of multiple cores, we 
+need a way to spawn Factor processes and communicate between them. Factor implements two different models of message-passing concurrency: the actor model, which is based on the idea of sending messages asynchronously between threads, and the 
 CSP model, based on the use of { $strong "channels" } .
 
 As a warm-up, we will make a simple example of communication between threads in the same process.
@@ -1349,7 +1350,7 @@ We can also invert the order:
 This works fine, since we had set the reader first.
 
 Now, for the interesting part: we will start a second Factor instance and communicate via message sending. Factor 
-transparently supports sending messages over the network, serializing values with the { $snippet "serialize" } vocabulary.
+transparently supports sending messages over the network, serializing values with the { $vocab-link "serialize" } vocabulary.
 
 Start another instance of Factor, and run a node server on it. We will use the word { $link <inet4> } , that creates an IPv4 
 address from a host and a port, and the { $link <node-server> } constructor
@@ -1426,40 +1427,39 @@ Otherwise, one could use the { $vocab-link "io.launcher" } vocabulary to start o
 
 ARTICLE: "tour-where" "Where to go from here?"
 
-We have covered a lot of ground, and I hope that by now you have a feeling whether Factor clicks for you. You can now 
+We have covered a lot of ground here, and we hope that this has given you a taste of the great things
+you can do with Factor. You can now 
 work your way through the documentation, and hopefully contribute to Factor yourself.
 
 Let me end with a few tips:
 
 { $list
 { "when starting to write Factor, it is " { $emphasis "very" } " easy to deal a lot with stack shuffling. Learn the " 
-{ $vocab-link "combinators" } " well, and do not fear to throw away your first examples;" }
-"no definition is too short: aim for one line;"
+{ $vocab-link "combinators" } " well, and do not fear to throw away your first examples." }
+"no definition is too short: aim for one line."
 "the help system and the inspector are your best friends."
 }
-To be fair, we also have to mention some drawbacks of Factor:
+To be fair, we have to mention some drawbacks of Factor:
 
 { $list
-"first, the community is really small. What they have done is impressive, but do not hope to find a lot of information 
-on the internet;"
-"the concatenative model is very powerful, but also very hard to get right;"
-"Factor lacks threads: although the distributed processes make up for it, they incur some cost in serialization;"
-"finally, Factor does not currently have a package manager, and this probably hinders contribution."
+"The community is small. It is difficult to find information about Factor on the internet.
+However, you can help with this by posting questions on Stack Overflow under the [factor] tag."
+"The concatenative model is very powerful, but also hard to get good at."
+"Factor lacks threads: although the distributed processes make up for it, they incur some cost in serialization."
+"Factor does not currently have a package manager. Most prominent packages are part of the main Factor distribution."
 }
-We have to balance the last observation with the convenience of having the whole source tree of Factor available in 
-the image, which certainly makes it easier to learn about libraries. Let me suggest a few vocabularies that you may want 
-to have a look at:
-
+The Factor source tree is massive, so here's a few vocabularies to get you started off:
 { $list 
-  { "first, I have not talked a lot about errors and exceptions. Learn more with " { $snippet "\"errors\" help" } ";" } 
-  { "the " { $vocab-link "macros" } " vocabulary implements a form of compile time metaprogramming less general than parsing words, but still quite convenient;" }
-  { "the " { $vocab-link "models" } " vocabulary lets you implement a form of dataflow programming using objects with observable slots;" }
-  { "the " { $vocab-link "match" } " vocabulary implements a form of pattern matching;" }
-  { "the " { $vocab-link "monads" } " vocabulary implements Haskell-style monads." }
+  { "We have not talked a lot about errors and exceptions. Learn more in the " { $vocab-link "errors" } " vocabulary." } 
+  { "The " { $vocab-link "macros" } " vocabulary implements a form of compile time metaprogramming less general than parsing words." }
+  { "The " { $vocab-link "models" } " vocabulary lets you implement a form of dataflow programming using objects with observable slots." }
+  { "The " { $vocab-link "match" } " vocabulary implements ML-style pattern matching." }
+  { "The " { $vocab-link "monads" } " vocabulary implements Haskell-style monads." }
 }
 
-I think these vocabularies are a testament to the power and expressivity of Factor. Happy hacking!
-
+These vocabularies are a testament to the power and expressivity of Factor, and we hope that they 
+help you make something you like. Happy hacking!
+$nl
 { $code "
 USE: images.http
 \"http://factorcode.org/logo.png\" http-image.
@@ -1468,9 +1468,13 @@ USE: images.http
 
 ARTICLE: "tour" "A guided tour of Factor"
 Factor is a mature, dynamically typed language based on the concatenative paradigm. Getting started with Factor can be daunting 
-since the concatenative paradigm is different from most mainstream languages. This tutorial will guide you through the basics of
-Factor so you can appreciate its simplicity and power. I assume you are an experienced programmer familiar with a functional 
-language, and I'll assume you understand concepts like folding, higher-order functions, and currying.
+since the concatenative paradigm is different from most mainstream languages.
+This tutorial will:
+{ $list 
+  "Guide you through the basics of Factor so you can appreciate its simplicity and power."
+  "Assume you are an experienced programmer familiar with a functional language"
+  "Assume you understand concepts like folding, higher-order functions, and currying"
+}
 
 Even though Factor is a niche language, it is mature and has a comprehensive standard library covering tasks from JSON 
 serialization to socket programming and HTML templating. It runs in its own optimized VM with very high performance for a dynamically 
@@ -1481,11 +1485,11 @@ Factor has a few significant advantages over
 other languages, most arising from the fact that it has essentially no syntax:
 
 { $list
-  "refactoring is very easy, leading to short and meaningful function definitions;"
-  "it is extremely succinct, letting the programmer concentrate on what is important instead of boilerplate;"
-  "it has powerful metaprogramming capabilities, exceeding even those of LISPs;"
-  "it is ideal to create DSLs;"
-  "it integrates easily with powerful tools."
+  "Refactoring is very easy, leading to short and meaningful function definitions"
+  "It is extremely succinct, letting the programmer concentrate on what is important instead of boilerplate"
+  "It has powerful metaprogramming capabilities, exceeding even those of LISPs"
+  "It is ideal for creating DSLs"
+  "It integrates easily with powerful tools"
 }
 
 This tutorial is Windows-centric, but everything should work the same on other systems, provided you adjust the file paths in