--- /dev/null
+IN: gadgets\r
+USING: generic kernel lists math matrices namespaces sdl\r
+sequences styles ;\r
+\r
+: <title> ( text -- gadget )\r
+ <label> dup 36 font-size set-paint-prop ;\r
+\r
+: <underline> ( -- gadget )\r
+ <gadget>\r
+ dup << gradient f { 1 0 0 } [ 64 64 64 ] [ 255 255 255 ] >> interior set-paint-prop\r
+ { 0 10 0 } over set-gadget-dim ;\r
+\r
+: <page> ( list -- gadget )\r
+ 0 1 <pile>\r
+ over car <title> over add-gadget\r
+ <underline> over add-gadget\r
+ swap cdr [ <label> over add-gadget ] each\r
+ empty-border ;\r
+\r
+: tutorial-pages\r
+ [\r
+ [\r
+ "Factor: a dynamic language"\r
+ "This series of slides presents a quick overview of Factor."\r
+ ""\r
+ "Factor is interactive, which means you can test out the code"\r
+ "in this tutorial immediately."\r
+ ""\r
+ "http://factor.sourceforge.net"\r
+ ] [\r
+ "The view from 10,000 feet"\r
+ "- Everything is an object"\r
+ "- A word is a basic unit of code"\r
+ "- Words are identified by names, and organized in vocabularies"\r
+ "- Words pass parameters on the stack"\r
+ "- Code blocks can be passed as parameters to words"\r
+ "- Word definitions are very short with very high code reuse"\r
+ ] [\r
+ "Basic syntax"\r
+ "Factor code is made up of whitespace-speparated tokens."\r
+ "Here is a program that prints ``Hello world'':"\r
+ ""\r
+ " \"hello world\" print"\r
+ ""\r
+ "The first token (\"hello world\") is a string."\r
+ "The second token (print) is a word."\r
+ "The string is pushed on the stack, and the print word prints it."\r
+ ] [\r
+ "The stack"\r
+ "- The stack is like a pile of papers."\r
+ "- You can ``push'' papers on the top of the pile,"\r
+ " and ``pop'' papers from the top of the pile."\r
+ ""\r
+ "Here is another code example:"\r
+ ""\r
+ " 2 3 + ."\r
+ ""\r
+ "Try running it in the listener now."\r
+ ] [\r
+ "Postfix arithmetic"\r
+ "What happened when you ran it?"\r
+ ""\r
+ "The two numbers (2 3) are pushed on the stack."\r
+ "Then, the + word pops them and pushes the result (5)."\r
+ "Then, the . word prints this result."\r
+ ""\r
+ "This is called postfix arithmetic."\r
+ "Traditional arithmetic is called infix: 3 + (6 * 2)"\r
+ "Lets translate this into postfix: 3 6 2 * + ."\r
+ ] [\r
+ "Colon definitions"\r
+ "We can define new words in terms of existing words."\r
+ ""\r
+ " : twice 2 * ;"\r
+ ""\r
+ "This defines a new word named ``twice'' that calls ``2 *''."\r
+ "Try the following in the listener:"\r
+ ""\r
+ " 3 twice twice ."\r
+ ""\r
+ "The result is the same as if you wrote:"\r
+ ""\r
+ " 3 2 * 2 * ."\r
+ ] [\r
+ "Stack effects"\r
+ "When we look at the definition of the ``twice'' word,"\r
+ "it is intuitively obvious that it takes one value from the stack,"\r
+ "and leaves one value behind. However, with more complex"\r
+ "definitions, it is better to document this so-called"\r
+ "``stack effect''."\r
+ ""\r
+ "A stack effect comment is written between ( and )."\r
+ "Factor ignores stack effect comments. Don't you!"\r
+ ""\r
+ "The stack effect of twice is ( x -- 2*x )."\r
+ "The stack effect of + is ( x y -- x+y )."\r
+ "The stack effect of . is ( object -- )."\r
+ ] [\r
+ "Shuffle words"\r
+ "The word ``twice'' we defined is useless."\r
+ "Let's try something more useful: squaring a number."\r
+ ""\r
+ "We want a word with stack effect ( n -- n*n )."\r
+ "However, we cannot use * by itself, since its stack effect"\r
+ "is ( x y -- x*y ); it expects two inputs."\r
+ ""\r
+ "However, we can use the word ``dup''. It has stack effect"\r
+ "( object -- object object ), and it does exactly what we"\r
+ "need. The ``dup'' word is known as a shuffle word."\r
+ ] [\r
+ "The squared word"\r
+ "Try entering the following word definition:"\r
+ ""\r
+ " : squared ( n -- n*n ) dup * ;"\r
+ ""\r
+ "Shuffle words solve the problem where we need to compose"\r
+ "two words, but their stack effects do not ``fit''."\r
+ ""\r
+ "Some of the most commonly-used shuffle words:"\r
+ ""\r
+ "drop ( object -- )"\r
+ "swap ( obj1 obj2 -- obj2 obj1 )"\r
+ "over ( obj1 obj2 -- obj1 obj2 obj1 )"\r
+ ] [\r
+ "Another shuffle example"\r
+ "Now let us write a word that negates a number."\r
+ "Start by entering the following in the listener"\r
+ ""\r
+ " 0 10 - ."\r
+ ""\r
+ "It will print -10, as expected. Now notice that this the same as:"\r
+ ""\r
+ " 10 0 swap - ."\r
+ ""\r
+ "So indeed, we can factor out the definition ``0 swap -'':"\r
+ ""\r
+ " : negate ( n -- -n ) 0 swap - ;"\r
+ ] [\r
+ "Seeing words"\r
+ "If you have entered every definition in this tutorial,"\r
+ "you will now have several new colon definitions:"\r
+ ""\r
+ " twice"\r
+ " squared"\r
+ " negated"\r
+ ""\r
+ "You can look at previously-entered word definitions using 'see'."\r
+ "Try the following:"\r
+ ""\r
+ " \ negated see"\r
+ ""\r
+ "Prefixing a word with \ pushes it on the stack, instead of"\r
+ "executing it. So the see word has stack effect ( word -- )."\r
+ ] [\r
+ "Booleans"\r
+ "In Factor, any object can be used as a truth value."\r
+ "- The f object is false."\r
+ "- Anything else is true."\r
+ ""\r
+ "Here is a word that outputs a boolean:"\r
+ ""\r
+ " : negative? ( n -- ? ) 0 < ;"\r
+ ] [\r
+ "Branches"\r
+ "Now suppose we want to write a word that computes the"\r
+ "absolute value of a number; that is, if it is less than 0,"\r
+ "the number will be negated to yield a positive result."\r
+ ""\r
+ " : absolute ( x -- |x| )"\r
+ " dup negative? [ negated ] when ;"\r
+ ""\r
+ "It duplicates the top of the stack, since negative? pops it."\r
+ "Then if the top of the stack was found to be negative,"\r
+ "it is negated, yielding a postive result."\r
+ ] [\r
+ "More branches"\r
+ "On the previous slide, you saw the 'when' conditional:"\r
+ ""\r
+ " ... condition ... [ ... code to run if true ... ] when"\r
+ ""\r
+ "Another commonly-used form is 'unless':"\r
+ ""\r
+ " ... condition ... [ ... code to run if true ... ] unless"\r
+ ""\r
+ "The 'ifte' conditional takes action on both branches:"\r
+ ""\r
+ " ... condition ... [ ... ] [ ... ] ifte"\r
+ ] [\r
+ "Combinators"\r
+ "ifte, when, unless are words that take lists of code as input."\r
+ ""\r
+ "Lists of code are called ``quotations''."\r
+ "Words that take quotations are called ``combinators''."\r
+ ""\r
+ "Another combinator is times ( n quot -- )."\r
+ "It calls a quotation n times."\r
+ ""\r
+ "Try this:"\r
+ ""\r
+ " 10 [ \"Hello combinators\" print ] times"\r
+ ] [\r
+ "Sequences"\r
+ "You have already seen strings, very briefly:"\r
+ ""\r
+ " \"Hello world\""\r
+ ""\r
+ "Strings are part of a class of objects called sequences."\r
+ "Two other types of sequences you will use a lot are:"\r
+ ""\r
+ " Lists: [ 1 3 \"hi\" 10 2 ]"\r
+ " Vectors: { \"the\" [ \"quick\" \"brown\" ] \"fox\" }"\r
+ ""\r
+ "As you can see in the second example, lists and vectors"\r
+ "can contain any type of object, including other lists"\r
+ "and vectors."\r
+ ] [\r
+ "Sequences and combinators"\r
+ "A very useful combinator is each ( seq quot -- )."\r
+ "It calls a quotation with each element of the sequence in turn."\r
+ ""\r
+ "Try this:"\r
+ ""\r
+ " [ 10 20 30 ] [ . ] each"\r
+ ""\r
+ "A closely-related combinator is map ( seq quot -- seq )."\r
+ "It also calls a quotation with each element."\r
+ "However, it then collects the outputs of the quotation"\r
+ "into a new sequence."\r
+ ""\r
+ "Try this:"\r
+ ""\r
+ " [ 10 20 30 ] [ 3 + ] map ."\r
+ "==> [ 13 23 33 ]"\r
+ ] [\r
+ "Numbers - integers and ratios"\r
+ "Factor's supports arbitrary-precision integers and ratios."\r
+ ""\r
+ "Try the following:"\r
+ ""\r
+ " : factorial ( n -- n! ) 0 <range> product ;"\r
+ " 100 factorial ."\r
+ ""\r
+ " 1 3 / 1 2 / + ."\r
+ "==> 5/6"\r
+ ""\r
+ "Rational numbers are added, multiplied and reduced to"\r
+ "lowest terms in the same way you learned in grade school."\r
+ ] [\r
+ "Numbers - higher math"\r
+ " 2 sqrt ."\r
+ "==> 1.414213562373095"\r
+ ""\r
+ " -1 sqrt ."\r
+ "==> #{ 0 1.0 }#"\r
+ ""\r
+ " M[ [ 10 3 ] [ 7 5 ] [ -2 0 ] ]M M[ [ 11 2 ] [ 4 8 ] ]M"\r
+ "==> M[ [ 122 44 ] [ 97 54 ] [ -22 -4 ] ]M"\r
+ ""\r
+ "... and there is much more."\r
+ ] [\r
+ "Object oriented programming"\r
+ "Each object belongs to a class."\r
+ "Generic words act differently based on an object's class."\r
+ ""\r
+ " GENERIC: describe ( object -- )"\r
+ " M: integer describe \"The integer \" write . ;"\r
+ " M: string describe \"The string \" write . ;"\r
+ " M: object describe drop \"Unknown object\" print ;"\r
+ ""\r
+ "Each M: line defines a ``method.''"\r
+ "Method definitions may appear in independent source files."\r
+ ""\r
+ "integer, string, object are built-in classes."\r
+ ] [\r
+ "Defining new classes with tuples"\r
+ "New classes can be defined:"\r
+ ""\r
+ " TUPLE: point x y ;"\r
+ " M: point describe"\r
+ " \"x =\" write dup point-x ."\r
+ " \"y =\" write point-y . ;"\r
+ " 100 200 <point> describe"\r
+ ""\r
+ "A tuple is a collection of named slots."\r
+ ""\r
+ "Tuples support custom constructors, delegation..."\r
+ "see the developer's handbook for details."\r
+ ] [\r
+ "The library"\r
+ "Offers a good selection of highly-reusable words:"\r
+ "- Operations on sequences"\r
+ "- Variety of mathematical functions"\r
+ "- Web server and web application framework"\r
+ "- Graphical user interface framework"\r
+ "Browsing the library:"\r
+ "- To list all vocabularies:"\r
+ " vocabs ."\r
+ "- To list all words in a vocabulary:"\r
+ " \"sequences\" words ."\r
+ "- To show a word definition:"\r
+ " \ reverse see"\r
+ ] [\r
+ "Learning more"\r
+ "Hopefully this tutorial has sparked your interest in Factor."\r
+ ""\r
+ "You can learn more by reading the Factor developer's handbook:"\r
+ ""\r
+ "http://factor.sourceforge.net/handbook.pdf"\r
+ ""\r
+ "Also, point your IRC client to irc.freenode.net and hop in the"\r
+ "#concatenative channel to chat with other Factor geeks."\r
+ ]\r
+ ] ;\r
+\r
+: <tutorial> ( pages -- browser )\r
+ tutorial-pages [ <page> ] map <book>\r
+ dup [ 204 204 255 ] background set-paint-prop\r
+ dup << gradient f { 0 1 0 } [ 204 204 255 ] [ 255 204 255 ] >> interior set-paint-prop\r
+ dup "Sans Serif" font set-paint-prop\r
+ dup 18 font-size set-paint-prop\r
+ <book-browser> ;\r
+\r
+: tutorial <tutorial> gadget. ;\r