{"id":17166401,"url":"https://github.com/andreaferretti/factor-tutorial","last_synced_at":"2026-01-05T13:48:40.482Z","repository":{"id":22078179,"uuid":"25407615","full_name":"andreaferretti/factor-tutorial","owner":"andreaferretti","description":"From function composition to distributed programming","archived":false,"fork":false,"pushed_at":"2024-01-11T14:54:10.000Z","size":330,"stargazers_count":66,"open_issues_count":2,"forks_count":12,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-01-29T22:31:52.129Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://andreaferretti.github.io/factor-tutorial/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"EdwardvanRaak/MaterialBarcodeScanner","license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andreaferretti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-10-18T19:27:07.000Z","updated_at":"2025-01-23T14:32:45.000Z","dependencies_parsed_at":"2024-12-02T07:39:24.979Z","dependency_job_id":null,"html_url":"https://github.com/andreaferretti/factor-tutorial","commit_stats":{"total_commits":70,"total_committers":6,"mean_commits":"11.666666666666666","dds":"0.30000000000000004","last_synced_commit":"2c7adc263381860df4d26c20c49cbbc672a90c08"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreaferretti%2Ffactor-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreaferretti%2Ffactor-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreaferretti%2Ffactor-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreaferretti%2Ffactor-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andreaferretti","download_url":"https://codeload.github.com/andreaferretti/factor-tutorial/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245320163,"owners_count":20596115,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T23:05:28.886Z","updated_at":"2026-01-05T13:48:40.427Z","avatar_url":"https://github.com/andreaferretti.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"A panoramic tour of Factor\n==========================\n\nNB: This tutorial has been merged in the official documentation of Factor, and is available both [online](https://docs.factorcode.org/content/article-tour.html) and in the Factor integrated help. The version that is present here is not up to date, the official one will be kept up to date as the language evolves. I am leaving this up mostly for historical purposes.\n\n[Factor](http://factorcode.org) 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](http://en.wikipedia.org/wiki/Fold_%28higher-order_function%29), [higher-order functions](http://en.wikipedia.org/wiki/Higher-order_function), and [currying](http://en.wikipedia.org/wiki/Currying).\n\nEven 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 typed language. It also has a flexible object system, a [FFI](http://en.wikipedia.org/wiki/Foreign_function_interface) to C, and asynchronous I/O that works a bit like Node.js, but with a much simpler model for cooperative multithreading.\n\nYou may wonder why you should care enough about Factor to read this tutorial. Factor has a few significant advantages over other languages, most arising from the fact that it has essentially no syntax:\n\n* refactoring is very easy, leading to short and meaningful function definitions;\n* it is extremely succinct, letting the programmer concentrate on what is important instead of boilerplate;\n* it has powerful metaprogramming capabilities, exceeding even those of LISPs;\n* it is ideal to create [DSLs](http://en.wikipedia.org/wiki/Domain-specific_language);\n* it integrates easily with powerful tools.\n\nBefore you start this tutorial, [download a copy of Factor](http://factorcode.org) so you can follow along with the examples in the listener (the Factor [REPL](http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)).\n\nI assume you are using Mac OS X or some distribution of Linux, but everything should work the same on other systems, provided you adjust the file paths in the examples.\n\nThe first section gives some motivation for the rather peculiar model of computation of concatenative languages, but feel free to skip it if you want to get your feet wet and return to it after some hands on practice with Factor.\n\nConcatenative languages\n-----------------------\n\nFactor is a *concatenative* programming language in the spirit of [Forth](http://en.wikipedia.org/wiki/Forth_%28programming_language%29). What does this even mean?\n\nTo 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 juxtaposed in order to compose them. So if `f` and `g` are two functions, their composition is just `f g` (unlike in mathematical notation, functions are read from left to right, so this means first execute `f`, then execute `g`).\n\nThis requires some explanation, since we know functions often have multiple inputs and outputs, and it is not always the case that the output of `f` matches the input of `g`. For instance, `g` may need access to values computed by earlier functions. But the only thing that `g` can see is the output of `f`, so the output of `f` is the whole state of the world as far as `g` is concerned. To make this work, functions have to thread the global state, passing it to each other.\n\nThere are various ways this global state can be encoded. The most naive would use a hashmap that maps variable names to their values. This turns out to be too flexible: if every function can access any piece of global state, there is little control on what functions can do, little encapsulation, and ultimately programs become an unstructured mess of routines mutating global variables.\n\nIt 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., `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.\n\nSo, functions are encouraged to stay small and only refer to the top two or three elements on the stack. In a sense, there is no distinction between local and global variables, but values can be more or less local depending on their distance from the top of the stack.\n\nNotice 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.\n\nThis leaves concatenative languages like Factor in a strange position, they are both extremely functional - only allowing composition of simpler functions into more complex ones - and largely imperative - describing operations on a mutable stack.\n\nPlaying with the stack\n----------------------\n\nLet us start looking what Factor actually feels like. Our first words will be literals, like `3`, `12.58` or `\"Chuck Norris\"`. Literals can be thought as functions that push themselves on the stack. Try writing `5` in the listener and then press enter to confirm. You will see that the stack, initially empty, now looks like\n\n    5\n\nYou can enter more that one number, separated by spaces, like `7 3 1`, and get\n\n    5\n    7\n    3\n    1\n\n(the interface shows the top of the stack on the bottom). What about operations? If you write `+`, you will run the `+` function, which pops the two topmost elements and pushes their sum, leaving us with\n\n    5\n    7\n    4\n\nYou can put additional inputs in a single line, so for instance `- *` will leave the single number `15` on the stack (do you see why?).\n\nThe function `.` (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.\n\nIf we write everything on one line, our program so far looks like\n\n    5 7 3 1 + - * .\n\nwhich 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](https://en.wikipedia.org/wiki/Reverse_Polish_notation) (RPN). Notice that RPN requires no parenthesis, unlike the [polish notation](http://en.wikipedia.org/wiki/Polish_notation) of Lisps where the operator comes first, and RPN requires no precedence rules, unlike the [infix notation](http://en.wikipedia.org/wiki/Infix_notation) used in most programming languages and in everyday arithmetic. For instance in any Lisp, the same computation would be written\n\n    (* 5 (- 7 (+ 3 1)))\n\nand in familiar infix notation\n\n    (7 - (3 + 1)) * 5\n\nAlso 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.\n\nDefining our first word\n-----------------------\n\nWe will now define our first function. Factor has slightly odd naming of functions: since functions are read from left to right, they are simply called **words**, and this is what we'll call them from now on. Modules in Factor define words in terms of previous words and these sets of words are then called **vocabularies**.\n\nSuppose we want to compute the [factorial](http://en.wikipedia.org/wiki/Factorial). To start with a concrete example, we'll compute the factorial of `10`, so we start by writing `10` on the stack. Now, the factorial is the product of the numbers from `1` to `10`, so we should produce such a list of numbers first.\n\nThe word to produce a range is called `[a,b]` (tokenization is trivial in Factor because words are always separated by spaces, so this allows you to use any combination of non-whitespace characters as the name of a word; there are no semantics to the `[`, the `,` and the `]` in `[a,b]` since it is just a token like `foo` or `bar`).\n\nThe range we want starts with `1`, so we can use the simpler word `[1,b]` that assumes the range starts at `1` and only expects the value at the top of the range to be on the stack. If you write `[1,b]` in the listener, Factor will prompt you with a choice, because the word `[1,b]` is not imported by default. Factor is able to suggest you import the `math.ranges` vocabulary, so choose that option and proceed.\n\nYou should now have on your stack a rather opaque structure which looks like\n\n    T{ range f 1 10 1 }\n\nThis 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 `1` to `10`, we convert the lazy response on the stack into an array using the word `\u003earray`. Enter that word and your stack should now look like\n\n    { 1 2 3 4 5 6 7 8 9 10 }\n\nwhich is promising!\n\nNext, we want to take the product of those numbers. In many functional languages, this could be done with a function called reduce or fold. Let's look for one. Pressing `F1` in the listener will open a contextual help system, where you can search for `reduce`. It turns out that `reduce` is actually the word we are looking for, but at this point it may not be obvious how to use it.\n\nTry writing `1 [ * ] reduce` and look at the output: it is indeed the factorial of `10`. Now, `reduce` usually takes three arguments: a sequence (and we had one on the stack), a starting value (this is the `1` we put on the stack next) and a binary operation. This must certainly be the `*`, but what about those square brackets around the `*`?\n\nIf we had written just `*`, 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 **quotation**. To quote one or more words, you just surround them by `[` and `]` (leaving spaces!). What you get is akin to an anonymous function in other languages.\n\nLet's type the word `drop` into the listener to empty the stack, and try writing what we have done so far in a single line: `10 [1,b] 1 [ * ] reduce`. This will leave `3628800` on the stack as expected.\n\nWe now want to define a word for factorial that can be used whenever we want a factorial. We will call our word `fact` (although `!` is customarily used as the symbol for factorial, in Factor `!` is the word used for comments). To define it, we first need to use the word `:`. Then we put the name of the word being defined, then the **stack effects** and finally the body, ending with the `;` word:\n\n    : fact ( n -- n! ) [1,b] 1 [ * ] reduce ;\n\nWhat are stack effects? In our case it is the `( 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 `n`. Factor will perform a consistency check that the number of inputs and outputs you specify agrees with what the body does.\n\nIf you try to write\n\n    : fact ( m n -- n! ) [1,b] 1 [ * ] reduce ;\n\nFactor will signal an error that the 2 inputs (`m` and `n`) are not consistent with the body of the word. To restore the previous correct definition press `Ctrl+P` two times to get back to the previous input and then enter it.\n\nWe 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.\n\nIn any case, you have succesfully defined your first word: if you write `10 fact` in the listener you can prove it.\n\nNotice that the `1 [ * ] reduce` part of the definition sort of makes sense on its own, being the product of a sequence. The nice thing about a concatenative language is that we can just factor this part out and write\n\n    : prod ( {x1,...,xn} -- x1*...*xn ) 1 [ * ] reduce ;\n    : fact ( n -- n! ) [1,b] prod ;\n\nOur 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.\n\nOf course, Factor already has a word for the factorial (actually there is a whole `math.factorials` vocabulary, including many variants of the usual factorial) and a word for the product (`product` in the `sequences` vocabulary), but as it often happens introductory examples overlap with the standard library.\n\nParsing words\n-------------\n\nIf 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 `[`, `]`, `:` and `;` that don't seem to follow this rule.\n\nThese are **parsing words** and they behave differently from simpler words like `5`, `[1,b]` or `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.\n\nThey are not defined using the `:` word, but with the word `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 `:` asks for the next tokens from the parsers until `;` is found and tries to compile that stream of tokens into a word definition.\n\nA common use of parsing words is to define literals. For instance `{` is a parsing word that starts an array definition and is terminated by `}`. Everything in-between is part of the array. An example of array that we have seen before is `{ 1 2 3 4 5 6 7 8 9 10 }`.\n\nThere are also literals for hashmaps, `H{ { \"Perl\" \"Larry Wall\" } { \"Factor\" \"Slava Pestov\" } { \"Scala\" \"Martin Odersky\" } }`, and byte arrays, `B{ 1 14 18 23 }`.\n\nOther uses of parsing word include the module system, the object-oriented features of Factor, enums, memoized functions, privacy modifiers and more. In theory, even `SYNTAX:` can be defined in terms of itself, although of course the system has to be bootstrapped somehow.\n\nStack shuffling\n---------------\n\nNow that you know the basics of Factor, you may want to start assembling more complex words. This may sometimes require you to use variables that are not on top of the stack, or to use variables more than once. There are a few words that can be used to help with this. I mention them now since you need to be aware of them, but I warn you that using too many of these words to manipulate the stack will cause your code to quickly become harder to read and write. Stack shuffling requires mentally simulating moving values on a stack, which is not a natural way to program. In the next section we'll see a much more effective way to handle most needs.\n\nHere 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, and explore the online help to find out more.\n\n    dup ( x -- x x )\n    drop ( x -- )\n    swap ( x y -- y x )\n    over ( x y -- x y x )\n    dupd ( x y -- x x y )\n    swapd ( x y z -- y x z )\n    nip ( x y -- y )\n    rot ( x y z -- y z x )\n    -rot ( x y z -- z x y )\n    2dup ( x y -- x y x y )\n\nCombinators\n-----------\n\nAlthough the words mentioned in the previous paragraph are occasionally useful (especially the simpler `dup`, `drop` and `swap`), you should write code that does as little stack shuffling as possible. This requires practice getting the function arguments in the right order. Nevertheless, there are certain common patterns of needed stack manipulation that are better abstracted away into their own words.\n\nSuppose we want to define a word to determine whether a given number `n` is prime. A simple algorithm is to test each number from `2` to the square root of `n` and see whether it is a divisor of `n`. In this case, `n` is used in two places: as an upper bound for the sequence, and as the number to test for divisibility.\n\nThe word `bi` applies two different quotations to the single element on the stack above them, and this is precisely what we need. For instance `5 [ 2 * ] [ 3 + ] bi` yields\n\n    10\n    8\n\n`bi` applies the quotation `[ 2 * ]` to the value `5` and then the quotation `[ 3 + ]` to the value `5` leaving us with `10` and then `8` on the stack. Without `bi`, we would have to first `dup` `5`, then multiply, and then `swap` the result of the multiplication with the second `5`, so we could do the addition\n\n    5 dup 2 * swap 3 +\n\nYou can see that `bi` replaces a common pattern of `dup`, then calculate, then `swap` and calculate again.\n\nTo continue our prime example, we need a way to make a range starting from `2`. We can define our own word for this `[2,b]`, using the `[a,b]` range word we discussed earlier\n\n    : [2,b] ( n -- {2,...,n} ) 2 swap [a,b] ; inline\n\nWhat's up with that `inline` word? This is one of the modifiers we can use after defining a word, another one being `recursive`. This will allow us to have the definition of a short word inlined wherever it is used, rather than incurring a function call.\n\nTry our new `[2,b]` word and see that it works\n\n    6 [2,b] \u003earray .\n\nUsing `[2,b]` to produce the range of numbers from `2` to the square root of an `n` that is already on the stack is easy: `sqrt floor [2,b]` (technically `floor` isn't necessary here, as `[a,b]` works for non-integer bounds). Let's try that out\n\n    16 sqrt [2,b] \u003earray .\n\nNow, we need a word to test for divisibility. A quick search in the online help shows that `divisor?` is the word we want. It will help to have the arguments for testing divisibility in the other direction, so we define `multiple?`\n\n    : multiple? ( a b -- ? ) swap divisor? ; inline\n\nBoth of these return `t`\n\n    9 3 divisor? .\n    3 9 multiple? .\n\nIf we're going to use `bi` in our `prime` definition, as we implied above, we need a second quotation. Our second quotation needs to test for a value in the range being a divisor of `n` - in other words we need to partially apply the word `multiple?`. This can be done with the word `curry`, like this: `[ multiple? ] curry`.\n\nFinally, once we have the range of potential divisors and the test function on the stack, we can test whether any element satisfied divisibility with `any?` and then negate that answer with `not`. Our full definition of `prime` looks like\n\n    : prime? ( n -- ? ) [ sqrt [2,b] ] [ [ multiple? ] curry ] bi any? not ;\n\nAltough the definition of `prime` is complicated, the stack shuffling is minimal and is only used in the small helper functions, which are simpler to reason about than `prime?`.\n\nNotice that `prime?` uses two levels of quotation nesting since `bi` operates on two quotations, and our second quotation contains the word `curry`, which also operates on a quotation. In general, Factor words tend to be rather shallow, 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.\n\nMany more combinators exists other than `bi` (and its relative `tri`), and you should become acquainted at least with `bi`, `tri`, `bi*` and `bi@` by reading about them in the online help and trying them out in the listener.\n\nVocabularies\n------------\n\nIt 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 **vocabularies**. You can import all names from a vocabulary with the word `USE:`. In fact, you may have seen something like\n\n    USE: math.ranges\n\nwhen you asked the listener to import the word `[1,b]` for you. You can also use more than one vocabulary at a time with the word `USING:`, which is followed by a list of vocabularies and terminated by `;`, like\n\n    USING: math.ranges sequences.deep ;\n\nFinally, you define the vocabulary where your definitions are stored with the word `IN:`. If you search the online help for a word you have defined so far, like `prime?`, you will see that your definitions have been grouped under the default `scratchpad` vocabulary. By the way, this shows that the online help automatically collects information about your own words, which is a very useful feature.\n\nThere are a few more words, like `QUALIFIED:`, `FROM:`, `EXCLUDE:` and `RENAME:`, that allow more fine-grained control over the imports, but `USING:` is the most common.\n\nOn 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 `basis`, `core`, `extra`, `work` under the Factor home. You can add more, both at runtime with the word `add-vocab-root`, and by creating a configuration file `.factor-rc`, but for now we will store our vocabularies under the `work` directory, which is reserved for the user.\n\nGenerate a template for a vocabulary writing\n\n    USE: tools.scaffold\n    \"github.tutorial\" scaffold-work\n\nYou will find a file `work/github/tutorial/tutorial.factor` containing an empty vocabulary. Factor integrates with many editors, so you can try `\"github.tutorial\" edit`: this will prompt you to choose your favourite editor, and use that editor to open the newly created vocabulary.\n\nYou can add the definitions of the previous paragraph, so that it looks like\n\n    ! Copyright (C) 2014 Andrea Ferretti.\n    ! See http://factorcode.org/license.txt for BSD license.\n    USING: ;\n    IN: github.tutorial\n\n    : [2,b] ( n -- {2,...,n} ) 2 swap [a,b] ; inline\n\n    : multiple? ( a b -- ? ) swap divisor? ; inline\n\n    : prime? ( n -- ? ) [ sqrt [2,b] ] [ [ multiple? ] curry ] bi any? not ;\n\nSince the vocabulary was already loaded when you scaffolded it, we need a way to refresh it from disk. You can do this with `\"github.tutorial\" refresh`. There is also a `refresh-all` word, with a shortcut `F2`.\n\nYou will be prompted a few times to use vocabularies, since your `USING:` statement is empty. After having accepted all of them, Factor suggests you a new header with all the needed imports:\n\n    USING: kernel math.functions math.ranges sequences ;\n    IN: github.tutorial\n\nNow that you have some words in your vocabulary, you can edit, say, the `multiple?` word with `\\ multiple? edit`. You will find your editor open on the relevant line of the right file. This also works for words in the Factor distribution, although it may be a bad idea to modify them.\n\nThis `\\` 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 `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 `multiple?`.\n\nBack to our task, you may notice that the words `[2,b]` and `multiple?` are just helper functions that you may not want to expose directly. To hide them from view, you can wrap them in a private block like this\n\n    \u003cPRIVATE\n\n    : [2,b] ( n -- {2,...,n} ) 2 swap [a,b] ; inline\n\n    : multiple? ( a b -- ? ) swap divisor? ; inline\n\n    PRIVATE\u003e\n\nAfter making this change and refreshed the vocabulary, you will see that the listener is not able to refer to words like `[2,b]` anymore. The `\u003cPRIVATE` word works by putting all definitions in the private block under a different vocabulary, in our case `github.tutorial.private`.\n\nIt is still possible to refer to words in private vocabularies, as you can confirm by searching for `[2,b]` in the online help, but of course this is discouraged, since people do not guarantee any API stability for private words. Words under `github.tutorial` can refer to words in `github.tutorial.private` directly, like `prime?` does.\n\nTests and documentation\n-----------------------\n\nThis is a good time to start writing some unit tests. You can create a skeleton with\n\n    \"github.tutorial\" scaffold-tests\n\nYou fill find a generated file under `work/github/tutorial/tutorial-tests.factor`, that you can open with `\"github.tutorial\" edit-tests`. Notice the line\n\n    USING: tools.test github.tutorial ;\n\nthat imports the unit testing module as well as your own. We will only test the public `prime?` function.\n\nTests are written using the `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 `github.tutorial-tests`:\n\n    [ t ] [ 2 prime? ] unit-test\n    [ t ] [ 13 prime? ] unit-test\n    [ t ] [ 29 prime? ] unit-test\n    [ f ] [ 15 prime? ] unit-test\n    [ f ] [ 377 prime? ] unit-test\n    [ f ] [ 1 prime? ] unit-test\n    [ t ] [ 20750750228539 prime? ] unit-test\n\nYou can now run the tests with `\"github.tutorial\" test`. You will see that we have actually made a mistake, and pressing `F3` will show more details. It seems that our assertions fails for `2`.\n\nIn fact, if you manually try to run our functions for `2`, you will see that our defition of `[2,b]` returns `{ 2 }` for `2 sqrt`, due to the fact that the square root of two is less than two, so we get a descending interval. Try making a fix so that the tests now pass.\n\nThere are a few more words to test errors and inference of stack effects. `unit-test` suffices for now, but later on you may want to check `must-fail` and `must-infer`.\n\nWe 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 `\"github.tutorial\" scaffold-docs` and then `\"github.tutorial\" edit-docs`.\n\nThe generated file `work/github/tutorial-docs.factor` imports `help.markup` and `help.syntax`. These two vocabularies define words to generate documentation. The actual help page is generated by the `HELP:` parsing word.\n\nThe arguments to `HELP:` are nested array of the form `{ $directive content... }`. In particular, you see here the directives `$values` and`$description`, but a few more exist, such as `$errors`, `$examples` and `$see-also`.\n\nNotice that the type of the output `?` has been inferred to be boolean. Change the first lines to look like\n\n    USING: help.markup help.syntax kernel math ;\n    IN: github.tutorial\n\n    HELP: prime?\n    { $values\n        { \"n\" fixnum }\n        { \"?\" boolean }\n    }\n    { $description \"Tests if n is prime. n is assumed to be a positive integer.\" } ;\n\nand refresh the `github.tutorial` vocabulary. If you now look at the help for `prime?`, for instance with `\\ prime? help`, you will see the updated documentation.\n\nYou can also render the directives in the listener for quicker feedback. For instance, try writing\n\n    { $values\n        { \"n\" integer }\n        { \"?\" boolean }\n    } print-content\n\nThe help markup contains a lot of possible directives, and you can use them to write stand-alone articles in the help system. Have a look at some more with `\"element-types\" help`.\n\nThe object system and protocols\n-------------------------------\n\nAlthough it is not apparent from what we have said so far, Factor has object-oriented features, and many core words are actually method invocations. To better understand how objects behave in Factor, a quote is in order:\n\n\u003e I invented the term Object-Oriented and I can tell you I did not have C++ in mind.\n\n\u003e Alan Kay\n\nThe term object-oriented has as many different meanings as people using it. One point of view - which was actually central to the work of Alan Kay - is that it is about late binding of function names. In Smalltalk, the language where this concept was born, people do not talk about calling a method, but rather sending a message to an object. It is up to the object to decide how to respond to this message, and the caller should not know about the implementation. For instance, one can send the message `map` both to an array and a linked list, but internally the iteration will be handled differently.\n\nThe binding of the message name to the method implementation is dynamic, and this is regarded as the core strenght of objects. As a result, fairly complex systems can evolve from the cooperation of independent objects who do not mess with each other internals.\n\nTo be fair, Factor is very different from Smalltalk, but still there is the concept of classes, and generic words can defined having different implementations on different classes.\n\nSome classes are builtin in Factor, such as `string`, `boolean`, `fixnum` or `word`. Next, the most common way to define a class is as a **tuple**. Tuples are defined with the `TUPLE:` parsing word, followed by the tuple name and the fields of the class that we want to define, which are called **slots** in Factor parlance.\n\nLet us define a class for movies:\n\n    TUPLE: movie title director actors ;\n\nThis also generates setters `\u003e\u003etitle`, `\u003e\u003edirector` and `\u003e\u003eactors` and getters `title\u003e\u003e`, `director\u003e\u003e` and `actors\u003e\u003e`. For instance, we can create a new movie with\n\n    movie new \"The prestige\" \u003e\u003etitle\n      \"Christopher Nolan\" \u003e\u003edirector\n      { \"Hugh Jackman\" \"Christian Bale\" \"Scarlett Johansson\" } \u003e\u003eactors\n\nWe can also shorten this to\n\n    \"The prestige\" \"Christopher Nolan\"\n    { \"Hugh Jackman\" \"Christian Bale\" \"Scarlett Johansson\" }\n    movie boa\n\nThe word `boa` stands for 'by-order-of-arguments' and is a constructor that fills the slots of the tuple with the items on the stack in order. `movie boa` is called a **boa constructor**, a pun on the Boa Constrictor. It is customary to define a most common constructor called `\u003cmovie\u003e`, which in our case could be simply\n\n    : \u003cmovie\u003e ( title director actors -- movie ) movie boa ;\n\nIn fact, boa constructor are so common, that the above line can be shortened to\n\n    C: \u003cmovie\u003e movie\n\nIn other cases, you may want to use some defaults, or compute some fields.\n\nThe functional minded will be worried about the mutability of tuples. Actually, slots can be declared to be read-only with `{ slot-name read-only }`. In this case, the field setter will not be generated, and the value must be set a the beginning with a boa constructor. Other valid slot modifiers are `initial:` - to declare a default value - and a class word, such as `integer`, to restrict the values that can be inserted.\n\nAs an example, we define another tuple class for rock bands\n\n    TUPLE: band\n      { keyboards string read-only }\n      { guitar string read-only }\n      { bass string read-only }\n      { drums string read-only } ;\n    : \u003cband\u003e ( keyboards guitar bass drums -- band ) band boa ;\n\ntogether with one instance\n\n\t\"Richard Wright\" \"David Gilmour\" \"Roger Waters\" \"Nick Mason\" \u003cband\u003e\n\nNow, of course everyone knows that the star in a movie is the first actor, while in a rock band it is the bass player. To encode this, we first define a **generic word**\n\n    GENERIC: star ( item -- star )\n\nAs you can see, it is declared with the parsing word `GENERIC:` and declares its stack effects but it has no implementation right now, hence no need for the closing `;`. Generic words are used to perform dynamic dispatch. We can define implementations for various classes using the word `M:`\n\n    M: movie star actors\u003e\u003e first ;\n    M: band star bass\u003e\u003e ;\n\nIf you write `star .` two times, you can see the different effect of calling a generic word on instances of different classes.\n\nBuiltin and tuple classes are not all that there is to the object system: more classes can be defined with set operations like `UNION:` and `INTERSECTION:`. Another way to define a class is as a **mixin**.\n\nMixins are defined with the `MIXIN:` word, and existing classes can be added to the mixin writing\n\n    INSTANCE: class mixin\n\nMethods 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.\n\nTwo important examples of mixins are `sequence` and `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, such as hashtables or association lists.\n\nThis enables all sequences in Factor to be acted upon with a common set of words, while differing in implementation and minimizing code repetition (because only few primitives are needed, and other operations are defined for the `sequence` class). The most common operations you will use on sequences are `map`, `filter` and `reduce`, but there are many more - as you can see with `\"sequences\" help`.\n\nLearning the tools\n------------------\n\nA big part of the productivity of Factor comes from the deep integration of the language and libraries with the tools around them, which are embodied in the listener. Many functions of the listener can be used programmatically, and vice versa. You have seen some examples of this:\n\n* the help is navigable online, but you can also invoke it with `help` and print help items with `print-content`;\n* the `F2` shortcut or the words `refresh` and `refresh-all` can be used to refresh vocabularies from disk while continuing working in the listener;\n* the `edit` word gives you editor integration, but you can also click on file names in the help pages for vocabularies to open them.\n\nThe refresh is actually quite smart. Whenever a word is redefined, words that depend on it are recompiled against the new defition. You can check by yourself doing\n\n    : inc ( x -- y ) 1 + ;\n    : inc-print ( x -- ) inc . ;\n    5 inc-print\n\nand then\n\n    : inc ( x -- y ) 2 + ;\n    5 inc-print\n\nThis 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.\n\nYou can also save the whole state of Factor with the word `save-image` and later restore it by starting Factor with\n\n    ./factor -i=path-to-image\n\nIn fact, Factor is image-based and only uses files when loading and refreshing vocabularies.\n\nThe power of the listener does not end here. Elements of the stack can be inspected by clicking on them, or by calling the word `inspector`. For instance try writing\n\n    TUPLE: trilogy first second third ;\n    : \u003ctrilogy\u003e ( first second third -- trilogy ) trilogy boa ;\n    \"A new hope\" \"The Empire strikes back\" \"Return of the Jedi\" \u003ctrilogy\u003e\n    \"George Lucas\" 2array\n\nYou will get an item that looks like\n\n    { ~trilogy~ \"George Lucas\" }\n\non 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 by implementing the `content-gadget` method.\n\nThere is another inspector for errors. Whenever an error arises, it can be inspected with `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 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 `Ctrl+w`.\n\nAnother feature of the listener allows you to benchmark code. As an example, we write an intentionally inefficient Fibonacci:\n\n    DEFER: fib-rec\n    : fib ( n -- f(n) ) dup 2 \u003c [ ] [ fib-rec ] if ;\n    : fib-rec ( n -- f(n) ) [ 1 - fib ] [ 2 - fib ] bi + ;\n\n(notice the use of `DEFER:` to define two mutually recursive words). You can benchmark the running time writing `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 `time` word on a quotation to do the same.\n\nYou can also add watches on words, to print inputs and outputs on entry and exit. Try writing\n\n    \\ fib watch\n\nand then run `10 fib` to see what happens. You can then remove the watch with `\\ fib reset`.\n\nAnother very useful tool is the `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\n\n    \"lintme\" scaffold-work\n\nand add the following definition\n\n    USING: kernel sequences ;\n    IN: lintme\n\n    : startswith? ( str sub -- ? ) dup length swapd head = ;\n\nLoad the lint tool with `USE: lint` and write `\"lintme\" lint-vocab`. You will get a report mentioning that the word sequence `length swapd` is already used in the word `(split)` of `splitting.private`, hence it could be factored out.\n\nNow, 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 time to time, to avoid code duplication and as a good way to discover library words that you may have accidentally redefined.\n\nFinally, there are a few utilities to inspect words. You can see the definition of a word in the help tool, but a quicker way can be `see`. Or, vice versa, you may use `usage.` to inspect the callers of a given word. Try `\\ reverse see` and `\\ reverse usage.`.\n\nMetaprogramming\n---------------\n\nWe now venture into the metaprogramming world, and write our first parsing word. By now, you have seen a lot of parsing words, such as `[`. `{`, `H{`, `USE:`, `IN:`, `\u003cPRIVATE`, `GENERIC:` and so on. Each of those is defined with the parsing word `SYNTAX:` and interacts with Factor's parser.\n\nThe parser accumulates tokens onto an accumulator vector, unless it finds a parsing word, which is executed immediately. Since parsing words execute at compile time, they cannot interact with the stack, but they have access to the accumulator vector. Their stack effect must be `( accum -- accum )`. Usually what they do is ask the parser for some more tokens, do something with them, and finally push a result on the accumulator vector with the word `suffix!`.\n\nAs an example, we will define a literal for DNA sequences. A DNA sequence is a sequence of one of the bases cytosine, guanine, adenine and thymine, which we will denote by the letters c, g, a, t. Since there are four possible bases, we can encode each with two bits. Let use define a word\n\n    : dna\u003ebits ( token -- bits ) {\n      { \"a\" [ { f f } ] }\n      { \"c\" [ { t t } ] }\n      { \"g\" [ { f t } ] }\n      { \"t\" [ { t f } ] }\n    } case ;\n\nwhere the first bit represents whether the basis is a purine or a pyrimidine, and the second one identifies bases that pair together.\n\nOur aim is to read a sequence of letters a, c, g, t - possibly with spaces - and convert them to a bit array. Factor supports bit arrays, and literal bit arrays look like `?{ f f t }`.\n\nOur syntax for DNA will start with `DNA{` and get all tokens until the closing token `}` is found. The intermediate tokens will be put into a string, and using our function `dna\u003ebits` we will map this string into a bit array. To read tokens, we will use the word `parse-tokens`. There are a few higher-level words to interact with the parser, such as `parse-until` and `parse-literal`, but we cannot apply them in our case, since the tokens we will find are just sequences of a c g t, instead of valid Factor words. Let us start with a simple approximation that just reads tokens between our delimiters and outputs the string obtained by concatenation\n\n    SYNTAX: DNA{ \"}\" parse-tokens concat suffix!\n\nYou can test the effect by doing `DNA{ a ccg t a g }`, which should output `\"accgtag\"`. As a second approximation, we transform each letter into a boolean pair:\n\n    SYNTAX: DNA{ \"}\" parse-tokens concat\n      [ 1string dna\u003ebits ] { } map-as suffix! ;\n\nNotice the use of `map-as` instead of `map`. Since the target collection is not a string, we did not use `map`, which preserves the type, but `map-as`, which take as an additional argument an examplar of the target collection - here `{ }`.  Our final version flattens the array of pairs with `concat` and finally makes into a bit array:\n\n    SYNTAX: DNA{ \"}\" parse-tokens concat\n      [ 1string dna\u003ebits ] { } map-as\n      concat \u003ebit-array suffix! ;\n\nIf you try it with `DNA{ a ccg t a g }` you should get\n\n    `?{ f f t t t t f t t f f f f t }`\n\nLet 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 `[a,b]` to create a range. We can make a syntax that is friendlier to people coming from other languages using `...` as an infix word.\n\nWe can use `scan-object` to ask the parser for the next parsed object, and `unclip-last` to get the top element from the accumulator vector. This way, we can define `...` simply with\n\n    SYNTAX: ... unclip-last scan-object [a,b] suffix! ;\n\nYou can try it with `12 ... 18 \u003earray`.\n\nWe only scratched the surface of parsing words; in general, they allow you to perform arbitrary computations at compile time, enabling powerful forms of metaprogramming.\n\nIn 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. 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 `\u003cJS ... JS\u003e` 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.\n\nWhen the stack is not enough\n----------------------------\n\nUntil 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.\n\nOne thing you may want to do is to actually name local variables. The `::` word works like `:`, 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 instance, let us define a word to solve quadratic equations. I will spare you the purely stack-based version, and present you a version with locals (this will require the `locals` vocabulary):\n\n    :: solveq ( a b c -- x )\n      b neg\n      b b * 4 a c * * - sqrt\n      +\n      2 a * / ;\n\nIn this case we have chosen the + sign, but we can do better and output both solutions:\n\n    :: solveq ( a b c -- x1 x2 )\n      b neg\n      b b * 4 a c * * - sqrt\n      [ + ] [ - ] 2bi\n      [ 2 a * / ] bi@ ;\n\nYou can check that this definition works with something like `2 -16 30 solveq`, which should output both `3.0` and `5.0`. Apart from being written in RPN style, our first version of `solveq` looks exactly the same it would in a language with local variables. For the second definition, we apply both the `+` and `-` operations to -b and delta, using the combinator `2bi`, and then divide both results by 2a using `bi@`.\n\nThere is also support for locals in quotations - using `[|` - and methods - using `M::` - and one can also create a scope where to bind local variables outside definitions using `[let`. Of course, all of these are actually compiled to 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.\n\nAnother 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 `curry`. But 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 `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.\n\nThe example from the documentation probably tells more than the above sentence: try writing `1 { 1 2 3 } [ / ] with map`.\n\nLet me take again `prime?`, but this time write it without using helper words:\n\n    : prime? ( n -- ? ) [ sqrt 2 swap [a,b] ] [ [ swap divisor? ] curry ] bi any? not ;\n\nUsing `with` instead of `curry`, this simplifies to\n\n    : prime? ( n -- ? ) 2 over sqrt [a,b] [ divisor? ] with any? not ;\n\nIf you do not visualize what is happening, you may want to consider the `fry` vocabulary. It defines **fried quotations**; these are quotations that have holes in them - marked by `_` - that are filled with values from the stack.\n\nThe first quotation is rewritten more simply as\n\n    [ '[ 2 _ sqrt [a,b] ] call ]\n\nHere we use a fried quotation - starting with `'[` - to inject the element on the top of the stack in the second position, and then use `call` to evaluate the resulting quotation. The second quotation becomes simply\n\n    [ '[ _ swap divisor? ] ]\n\nso an alternative defition of `prime?` is\n\n    : prime? ( n -- ? ) [ '[ 2 _ sqrt [a,b] ] call ] [ '[ _ swap divisor? ] ] bi any? not ;\n\nDepending on your taste, you may find this version more readable. In this case, the added clarity is probably lost due to the fact that the fried quotations are themselves inside quotations, but occasionally their use can do a lot to simplify the flow.\n\nFinally, there are times where one just wants to give names to variables that are available inside some scope, and use 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.\n\nFactor allows you to create **dynamic variables** and bind them in scopes. The first thing is to create a **symbol** for a variable, say\n\n    SYMBOL: favorite-language\n\nThen one can use the word `set` to bind the variable and `get` to retrieve its values, like\n\n    \"Factor\" favorite-language set\n    favorite-language get\n\nScopes are nested, and new scopes can be created with the word `with-scope`. Try for instance\n\n    : on-the-jvm ( -- ) [\n      \"Scala\" favorite-language set\n      favorite-language get .\n    ] with-scope ;\n\nIf you run `on-the-jvm` you will get `\"Scala\"` printed, but still after execution `favorite-language get` return `\"Factor\"`.\n\nAll 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 does not shy from offering features that are less pure but nevertheless often useful.\n\n\nInput/Output\n------------\n\nWe now leave the tour of the language, and start investigating how to interact with the outside world. 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.\n\nFactor 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.\n\nAll of Factor input/output words are centered on **streams**. Streams are lazy sequences which can be read or written to, typical examples being files, network ports or the standard input and output. Factor holds a couple of dynamic variables called `input-stream` and `output-stream`, which are used by most I/O words. These variables can be rebound locally using `with-input-stream`, `with-output-stream` and `with-streams`. When you are in the listener, the default streams write and read in the listener, but once you deploy your application as an executable, they are usually bound to the standard input and output of your console.\n\nThe words `\u003cfile-reader\u003e` and `\u003cfile-writer\u003e` (or `\u003cfile-appender\u003e`) can be used to create a read or write stream to a file, given its path and encoding. Putting everything together, we make a simple example of a word that reads each line of a file encoded in UTF8, and writes the first letter of the line to the listener.\n\nFirst, we want a `safe-head` word, that works like `head`, but returns its input if the sequence is too short. To do so, we will use the word `recover`, which allows us to declare a try-catch block. It requires two quotations: the first one is executed, and on failure, the second one is executed with the error as input. Hence we can define\n\n    : safe-head ( seq n -- seq' ) [ head ] [ 2drop ] recover ;\n\nThis is mostly an occasion to show an example of exceptions, as Factor defines the `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\n\n    : safe-head ( seq n -- seq' ) short head ;\n\nWith this definition, we can make a word to read the first character of the first line:\n\n    : read-first-letters ( path -- )\n      utf8 \u003cfile-reader\u003e [\n        readln 1 safe-head write nl\n      ] with-input-stream ;\n\nUsing the helper word `with-file-reader`, we can also shorten this to\n\n    : read-first-letters ( path -- )\n      utf8 [\n        readln 1 safe-head write nl\n      ] with-file-reader ;\n\nUnfortunately, we are limited to one line. To read more lines, we should chain calls to `readln` until one returns `f`. Factor helps us with the word `file-lines`, which lazily iterates over lines. Our final definition becomes\n\n    : read-first-letters ( path -- )\n      utf8 file-lines [ 1 safe-head write nl ] each ;\n\nWhen the file is small, one can also use `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.\n\nWe end this section investigating some words to walk the filesystem. Our aim is a very minimal implementation of the `ls` command.\n\nThe word `directory-entries` lists the contents of a directory, giving a list of tuple elements, each one having the slots `name` and `type`. You can see this by trying `\"/home\" directory-entries [ name\u003e\u003e ] map`. If you inspect the directory entries, you will see that the type is either `+directory+` or `+regular-file+` (well, there are symlinks as well, but we will ignore them for simplicity). Hence we can define a word that lists files and directories with\n\n    : list-files-and-dirs ( path -- files dirs )\n        directory-entries [ type\u003e\u003e +regular-file+ = ] partition ;\n\nWith this, we can define a word `ls` that will print directory contents as follows:\n\n    : ls ( path -- )\n      list-files-and-dirs\n      \"DIRECTORIES:\" write nl\n      \"------------\" write nl\n      [ name\u003e\u003e write nl ] each\n      \"FILES:\" write nl\n      \"------\" write nl\n      [ name\u003e\u003e write nl ] each ;\n\nTry the word on your home directory to see the effects. In the next section, we shall look at how to create an executable for our simple program.\n\nDeploying programs\n------------------\n\nThere are two ways to run Factor programs outside the listener: as scripts, which are interpreted by Factor, or as standalone executable compiled for your platform. Both require you to define a vocabulary with an entry point (altough there is an even simpler way for scripts), so let's do that first.\n\nStart by creating our `ls` vocabulary with `\"ls\" scaffold-work` and make it look like this:\n\n    ! Copyright (C) 2014 Andrea Ferretti.\n    ! See http://factorcode.org/license.txt for BSD license.\n    USING: accessors command-line io io.directories io.files.types\n      kernel namespaces sequences ;\n    IN: ls\n\n    \u003cPRIVATE\n\n    : list-files-and-dirs ( path -- files dirs )\n        directory-entries [ type\u003e\u003e +regular-file+ = ] partition ;\n\n    PRIVATE\u003e\n\n    : ls ( path -- )\n      list-files-and-dirs\n      \"DIRECTORIES:\" write nl\n      \"------------\" write nl\n      [ name\u003e\u003e write nl ] each\n      \"FILES:\" write nl\n      \"------\" write nl\n      [ name\u003e\u003e write nl ] each ;\n\nWhen we run our vocabulary, we will need to read arguments from the command line. Command-line arguments are stored under the `command-line` dynamic variable, which holds an array of strings. Hence - forgetting any error checking - we can define a word which runs `ls` on the first command-line argument with\n\n    : ls-run ( -- ) command-line get first ls ;\n\nFinally, we use the word `MAIN:` to declare the main word of our vocabulary:\n\n    MAIN: ls-run\n\nHaving added those two lines to your vocabulary, you are now ready to run it. The simplest way is to run the vocabulary as a script with the `-run` flag passed to Factor. For instance to list the contents of my home I can do\n\n    ./factor -run=ls /home/andrea\n\nIn order to produce an executable, we must set some options and call the `deploy` word. The simplest way to do this graphically is to invoke the `deploy-tool` word. If you write `\"ls\" deploy-tool`, you will be presented with a window to choose deployment options. For our simple case, we will leave the default options and choose Deploy.\n\nAfter a little while, you should be presented with an executable that you can run like\n\n    cd ls\n    ./ls /home/andrea\n\nTry making the `ls` program more robust by handling missing command-line arguments and non-existent or non-directory arguments.\n\nMultithreading\n--------------\n\nAs we have said, the Factor runtime is single-threaded, like Node. Still, one can emulate concurrency in a single-threaded setting by making use of **coroutines**. These are essentially cooperative threads, which periodically release control with the `yield` word, so that the scheduler can decide which coroutine to run next.\n\nAlthough cooperative threads do not allow to make use of multiple cores, they still have some benefits:\n* input/output operations can avoid blocking the entire runtime, so that one can implement quite performant applications if I/O is the bottleneck;\n* user interfaces are naturally a multithreaded construct, and they can be implemented in this model, as the listener itself shows;\n* finally, some problems may just naturally be easier to write making use of the multithreaded constructs.\n\nFor 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 **channels**, as we will see in a later section.\n\nThreads in Factors are created out of a quotation and a name, with the `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:\n\n    SYMBOL: star-wars\n\n    \"A long time ago, in a galaxy far, far away....\n\n    It is a period of civil war. Rebel\n    spaceships, striking from a hidden\n    base, have won their first victory\n    against the evil Galactic Empire.\n\n    During the battle, rebel spies managed\n    to steal secret plans to the Empire's\n    ultimate weapon, the DEATH STAR, an\n    armored space station with enough\n    power to destroy an entire planet.\n\n    Pursued by the Empire's sinister agents,\n    Princess Leia races home aboard her\n    starship, custodian of the stolen plans\n    that can save her people and restore\n    freedom to the galaxy....\"\n    \"\\n\" split star-wars set\n\nWe will spawn 18 threads, each one printing a line. The operation that a thread must run amounts to\n\n    star-wars get ?nth print\n\nNote that dynamic variables are shared between threads, so each one has access to star-wars. This is fine, since it is read-only, but the usual caveats about shared memory in a multithreaded settings apply.\n\nLet us define a word for the thread workload\n\n    : print-a-line ( i -- ) star-wars get ?nth print ;\n\nIf we give the i-th thread the name \"i\", our example amounts to\n\n    18 [0,b) [\n      [ [ print-a-line ] curry ]\n      [ number\u003estring ]\n      bi spawn\n    ] each\n\nNote the use of `curry` to send i to the quotation that prints the i-th line. This is almost what we want, but it runs too fast. We need to put the thread to sleep for a while. So we `clear` the stack that now contains a lot of thread objects and look for the `sleep` word in the help.\n\nIt turns out that `sleep` does exactly what we need, but it takes a **duration** object as input. We can create a duration of i seconds with... well `i seconds`. So we define\n\n    : wait-and-print ( i -- ) dup seconds sleep print-a-line ;\n\nLet us try\n\n    18 [0,b) [\n      [ [ wait-and-print ] curry ]\n      [ number\u003estring ]\n      bi spawn\n    ] each\n\nInstead of `spawn`, we can also use `in-thread` which uses a dummy thread name and discards the returned thread, simplifying the above to\n\n    18 [0,b) [\n      [ wait-and-print ] curry in-thread\n    ] each\n\nThis is good enough for our simple purpose. In serious applications theads will be long-running. In order to make them cooperate, one can use the `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 `stop`, `suspend` or `resume` threads.\n\nServers and Furnace\n-------------------\n\nA very common case for using more than one thread is when writing server applications. 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).\n\nTo simplify this, Factor has the word `spawn-server`, which works like `spawn`, but in addition repeatedly spawns the quotation until it returns `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.\n\nThe vocabulary `io.servers` allows to write and configure TCP servers. A server is created with the word `\u003cthreaded-server\u003e`, 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 `handler`, which contains a quotation that is executed for each incoming connection. You can see a very simple example of server with\n\n    \"resource:extra/time-server/time-server.factor\" edit-file\n\nWe will raise the level of abstraction even more and show how to run a simple HTTP server. First, `USE: http.server`.\n\nAn HTTP application is built out of a **responder**. A responder is essentially a function from a path and an HTTP request to an HTTP response, but more concretely it is anything that implements the method `call-responder*`. Responses are instances of the tuple `response`, so are usually generated calling `\u003cresponse\u003e` and customizing a few slots. Let us write a simple echo responder:\n\n    TUPLE: echo-responder ;\n\n    : \u003cecho-responder\u003e ( -- responder ) echo-responder new ;\n\n    M: echo-responder call-responder*\n      drop\n      \u003cresponse\u003e\n        200 \u003e\u003ecode\n        \"Document follows\" \u003e\u003emessage\n        \"text/plain\" \u003e\u003econtent-type\n        swap concat \u003e\u003ebody ;\n\nResponders are usually combined to form more complex responders in order to implement routing and other features. In our simplistic example, we will use just this one responder, and set it globally with\n\n    \u003cecho-responder\u003e main-responder set-global\n\nOnce you have done this, you can start the server with `8080 httpd`. You can then visit `http://localhost:8080/hello/%20/from/%20/factor` in your browser to see your first responder in action. You can then stop the server with `stop-server`.\n\nNow, if this was all that Factor offers to write web applications, it would still be rather low level. In reality, web applications are usually written using a web framework called **Furnace**.\n\nFurnace 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 **Chloe**. Furnace allows us to use create **page actions** from Chloe templates, and in order to create a responder we will need to add routing.\n\nLet 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 between our echo responder and a default responder used to serve static files.\n\n    dispatcher new-dispatcher\n      \u003cecho-responder\u003e \"echo\" add-responder\n      \"/home/andrea\" \u003cstatic\u003e \"home\" add-responder\n      main-responder set-global\n\nOf course, substitute the path `/home/andrea` with any folder you like. If you start again the server with `8080 httpd`, you should be able to see both our simple echo responder (under `/echo`) and the contents of your files (under `/home`). Notice that directory listing is disabled by default, you can only access the content of files.\n\nNow that you know how to do routing, we can write page actions in Chloe. Things are starting to become complicated, so we scaffold a vocabulary with `\"hello-furnace\" scaffold-work`. Make it look like this:\n\n    ! Copyright (C) 2014 Andrea Ferretti.\n    ! See http://factorcode.org/license.txt for BSD license.\n    USING: accessors furnace.actions http http.server\n      http.server.dispatchers http.server.static kernel sequences ;\n    IN: hello-furnace\n\n\n    TUPLE: echo-responder ;\n\n    : \u003cecho-responder\u003e ( -- responder ) echo-responder new ;\n\n    M: echo-responder call-responder*\n      drop\n      \u003cresponse\u003e\n        200 \u003e\u003ecode\n        \"Document follows\" \u003e\u003emessage\n        \"text/plain\" \u003e\u003econtent-type\n        swap concat \u003e\u003ebody ;\n\n    TUPLE: hello-dispatcher \u003c dispatcher ;\n\n    : \u003cexample-responder\u003e ( -- responder )\n      hello-dispatcher new-dispatcher\n        \u003cecho-responder\u003e \"echo\" add-responder\n        \"/home/andrea\" \u003cstatic\u003e \"home\" add-responder\n        \u003cpage-action\u003e\n          { hello-dispatcher \"greetings\" } \u003e\u003etemplate\n        \"chloe\" add-responder ;\n\nMost things are the same as we have done in the listener. The only difference is that we have added a third responder in our dispatcher, under `chloe`. This responder is created with a page action. The page action has many slots - say, to declare the behaviour of receiving the result of a form - but we only set its template. This is the pair with the dispatcher class and the relative path of the template file.\n\nIn order for all this to work, create a file `work/hello-furnace/greetings.xml` with a content like\n\n    \u003c?xml version='1.0' ?\u003e\n\n    \u003ct:chloe xmlns:t=\"http://factorcode.org/chloe/1.0\"\u003e\n      \u003cp\u003eHello from Chloe\u003c/p\u003e\n    \u003c/t:chloe\u003e\n\nReload the `hello-furnace` vocabulary and `\u003cexample-responder\u003e main-responder set-global`. You should be able to see the results of your efforts under `http://localhost:8080/chloe`. Notice that there was no need to restart the server, we can change the main responder dynamically.\n\nThis 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.\n\nProcesses and channels\n----------------------\n\nAs 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 CSP model, based on the use of **channels**.\n\nAs a warm-up, we will make a simple example of communication between threads in the same process.\n\n    FROM: concurrency.messaging =\u003e send receive ;\n\nWe can start a thread that will receive a message and print it repeatedly:\n\n    : print-repeatedly ( -- ) receive . print-repeatedly ;\n    [ print-repeatedly ] \"printer\" spawn\n\nA thread whose quotation starts with `receive` and calls itself recursively behaves like an actor in Erlang or Akka. We can then use `send` to send messages to it. Try `\"hello\" over send` and then `\"threading\" over send`.\n\nChannels are slightly different abstractions, used for instance in Go and in Clojure core.async. They decouple the sender and the receiver, and are usually used synchronously. For instance, one side can receive from a channel before some other party sends something to it. This just means that the receiving end yields control to the scheduler, which waits for a message to be sent before giving control to the receiver again. This feature sometimes makes it easier to synchronize multithreaded applications.\n\nAgain, we first use a channel to communicate between threads in the same process. As expected, `USE: channels`. You can create a channel with `\u003cchannel\u003e`, write to it with `to` and read from it with `from`. Note that both operations are blocking: `to` will block until the value is read in a different thread, and `from` will block until a value is available.\n\nWe create a channel and give it a name with\n\n    SYMBOL: ch\n    \u003cchannel\u003e ch set\n\nThen we write to it in a separate thread, in order not to block the UI\n\n    [ \"hello\" ch get to ] in-thread\n\nWe can then read the value in the UI with\n\n    ch get from\n\nWe can also invert the order:\n\n    [ ch get from . ] in-thread\n    \"hello\" ch get to\n\nThis works fine, since we had set the reader first.\n\nNow, 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 `serialize` vocabulary.\n\nStart another instance of Factor, and run a node server on it. We will use the word `\u003cinet4\u003e`, that creates an IPv4 address from a host and a port, and the `\u003cnode-server\u003e` constructor\n\n    USE: concurrency.distributed\n    f 9000 \u003cinet4\u003e \u003cnode-server\u003e start-server\n\nHere we have used `f` as host, which just stands for localhost. We will also start a thread that keeps a running count of the numbers it has received.\n\n    FROM: concurrency.messaging =\u003e send receive ;\n    : add ( x -- y ) receive + dup . add ;\n    [ 0 add ] \"adder\" spawn\n\nOnce we have started the server, we can make a thread available with `register-remote-thread`:\n\n    dup name\u003e\u003e register-remote-thread\n\nNow we switch to the other instance of Factor. Here we will receive a reference to the remote thread and start sending numbers to it. The address of a thread is just the address of its server and the name we have registered the thread with, so we obtain a reference to our adder thread with\n\n    f 9000 \u003cinet4\u003e \"adder\" \u003cremote-thread\u003e\n\nNow, we reimport `send` just to be sure (there is an overlap with a word having the same name in `io.sockets`, that we have imported)\n\n    FROM: concurrency.messaging =\u003e send receive ;\n\nand we can start sending numbers to it. Try `3 over send`, and then `8 over send` - you should see the running total printed in the other Factor instance.\n\nWhat about channels? We go back to our server, and start a channel there, just as above. This time, though, we `publish` it to make it available remotely:\n\n    USING: channels channels.remote ;\n    \u003cchannel\u003e dup publish\n\nWhat you get in return is an id you can use remotely to communicate. For instance, I just got `72581372615274718877979307388951222312843084896785643440879198703359628058956` (yes, they really want to be sure it is unique!).\n\nWe will wait on this channel, thereby blocking the UI:\n\n    swap from .\n\nIn the other Factor instance we use the id to get a reference to the remote channel and write to it\n\n    f 9000 \u003cinet4\u003e 72581372615274718877979307388951222312843084896785643440879198703359628058956 \u003cremote-channel\u003e\n    \"Hello, channels\" over to\n\nIn the server instance, the message should be printed.\n\nRemote channels and threads are both useful to implement distributed applications and make good use of multicore servers. Of course, it remains the question how to start worker nodes in the first place. Here we have done it manually - if the set of nodes is fixed, this is actually an option.\n\nOtherwise, one could use the `io.launcher` vocabulary to start other Factor instances programmatically.\n\nWhere to go from here?\n----------------------\n\nWe have covered a lot of ground, and I hope that by now you have a feeling whether Factor clicks for you. You can now work your way through the documentation, and hopefully contribute to Factor yourself.\n\nLet me end with a few tips:\n\n- when starting to write Factor, it is *very* easy to deal a lot with stack shuffling. Learn the [combinators](http://docs.factorcode.org/content/article-combinators.html) well, and do not fear to throw away your first examples;\n- no definition is too short: aim for one line;\n- the help system and the inspector are your best friends.\n\nTo be fair, we also have to mention some drawbacks of Factor:\n\n- 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;\n- the concatenative model is very powerful, but also very hard to get right;\n- Factor lacks threads: although the distributed processes make up for it, they incur some cost in serialization;\n- finally, Factor does not currently have a package manager, and this probably hinders contribution.\n\nWe 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:\n\n- first, I have not talked a lot about errors and exceptions. Learn more with `\"errors\" help`;\n- the `macros` vocabulary implements a form of compile time metaprogramming less general than parsing words, but still quite convenient;\n- the `models` vocabulary lets you implement a form of dataflow programming using objects with observable slots;\n- the `match` vocabulary implements a form of pattern matching;\n- the `monads` vocabulary implements Haskell-style monads.\n\nI think these vocabularies are a testament to the power and expressivity of Factor. Happy hacking!\n\n    USE: images.http\n    \"http://factorcode.org/logo.png\" http-image.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreaferretti%2Ffactor-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandreaferretti%2Ffactor-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreaferretti%2Ffactor-tutorial/lists"}