Factor
 Appeared in:
 2003
 Influenced by:
 Influenced:
 Paradigm:
 Typing discipline:
 File extensions:
 .factor
 Versions and implementations (Collapse all  Expand all):
Factor is a modern concatenative stackbased language that supports objectorientated and functional programming.
The language was created by Slava Pestov in 2003 (JFactor) as a scripting language for a video game. Since then the language changed a lot — most of the features were added as soon as their necessity became evident.
Factor is a concatenative language: the function calls and arithmetic operators use postfix syntax instead of infix or prefix ones typical for most other languages. The code is a sequence of commands which transform input data into output ones; this style is called pipeline code, since it resembles the use of pipes in Unix shells.
Factor is a stackbased language: stack is used to pass parameters to and from functions (“words”). The parameters are pushed on the stack, and the function pops them as needed. The resulting values are returned via the stack as well. The language provides named variables, for example, local within the scope of one word, but most language constructs don’t require them. Input and output parameters of all words must be described in a formal way using stack effect notation (see examples).
Factor provides higherorder functions called combinators and anonymous functions called quotations. Quotations consist of several words enclosed in square brackets; they can be stored on the stack without being executed and passed as parameters to combinators. Some of the combinators can be used to replace shuffle words — words that change the order of the elements of the stack.
Main combinators (the arguments are listed in the order they have to be pushed on the stack):

if
performs given actions depending on the value of a boolean value. Arguments: boolean value, thenquotation, elsequotation. The versions of the combinator arewhen
(noelse
branch) andunless
(nothen
branch). 
each
corresponds toforeach
loop in other languages: it iterates over the elements of the array and applies a quotation to each of them. Arguments: array, loop bodyquotation. 
reduce
is a variation ofeach
which allows to accumulate a value between iterations. Arguments: array, initial value of the accumulator, loop bodyquotation. The quotation should take the current value of the accumulator and the current element of the array. 
map
iterates over the array and collects the output values from each iteration into a new array. Arguments: the original array, the quotation which transforms elements. 
filter
filters the elements of the array which satisfy a certain condition into a new array. Arguments: the original array, condition quotation. 
cleave
accepts a value and an array of quotations and applies each quotation to the value, resulting in an array of values. For this combinator and the next ones, there exist shorthand forms applicable when there are two or three quotations. They allow to avoid extra curly braces (array delimiting tokens). Shorthand forms forcleave
arebi
andtri
. 
spread
accepts a series of values and an array of quotations (both have the same number of elements) and applies each quotation to the corresponding value, resulting in a series of values. Shorthand forms arebi*
andtri*
. 
napply
accepts a series of values, a quotation and a number and applies the quotation to each value (the number of values in the series is given by the number argument). Shorthand forms arebi@
andtri@
.
Factor separates the module system (source code organization) and types/classes system (data processing logic organization). Source code of Factor programs is organized as a system of nested modules called dictionaries (similar to Java packages), which correspond to file structure of the code.
Object system in Factor is based on generic words which can have multiple implementations based on the classes of their arguments. Factor is a purely objectoriented language in the sense that every value is an object, and basic operations are performed by calling methods.
Factor provides support for metaprogramming, macros system and functors, which allows expanding the language easily. Besides, Factor includes tools for lowlevel programming, interfaces to procedures in other languages, binary data processing words and scoped resource management.
Elements of syntax:
Inline comments  ! 

Casesensitivity  yes 
Deep equality  = 
Comparison  < > 
Function definition  : <name> ( <input>  <output> ) <body> ; 
Function call  <name> 
Function call with no parameters  <name> 
If  then  <condition> [ <body> ] when 
If  then  else  <condition> [ <ifbranch> ] [ <elsebranch> ] if 
Factor logo
Links:
Examples:
Hello, World!:
Example for versions Factor 0.94The first line imports io
dictionary (print
word). The second line pushes the message string on the stack and then calls print
which prints the top element of the stack.
USE: io
"Hello, World!" print
Factorial:
Example for versions Factor 0.94The first line lists the necessary dictionaries: formatting
(printf
), kernel
(dup
), math
(arithmetical operators) and sequences
(iota
).
Next the definition of factorial
word follows which replaces an integer n
with its factorial on the top of the stack. To do this, it constructs an array of numbers from 0 to n — 1
(word iota
) and folds it with 1
using quotation [ 1 + * ]
(increment and multiply) and combinator reduce
.
The main program constructs a list of numbers from 0 to 16 (iota
again) and for each of them (combinator each
) applies the quotation which calculates the factorial and outputs the result in required format.
Standard dictionary math.combinatorics
contains word factorial
defined exactly like this.
USING: formatting kernel math sequences ;
IN: factorialexample
: factorial ( n  n! )
iota 1 [ 1 + * ] reduce ;
17 iota
[ dup factorial "%d! = %d\n" printf ] each
Fibonacci numbers:
Example for versions Factor 0.94This example shows recursive calculation of Fibonacci numbers.
Word fib
calculates the nth number: if the argument is not greater than 1, it stays on the stack as the return value, otherwise it is replaced with a sum of previous numbers. Word bi
is a shorthand version of cleave
combinator and allows to apply two quotations (in this case calls of fib
for smaller arguments) to the same element of the stack (n
).
USING: formatting kernel math sequences ;
IN: fibonacciexample
: fib ( n  fib(n) )
dup
1 >
[ [ 1  fib ] [ 2  fib ] bi + ]
when ;
16 iota [ 1 + fib "%d, " printf ] each
"...\n" printf
Factorial:
Example for versions Factor 0.94This example uses a purely recursive approach to factorial calculation. Word factorial
replaces n
with n!
on the stack with a side effect: it prints all values of factorial from 0 to n
. After if
combinator is applied, the stack holds values of n
and n!
. Words swap
and over
replace them with n!
, n
and n!
; two latter values are used for printing, and the first one stays on the stack as a return value.
In the main part of the program we need to add drop
to remove 16!
from the stack, so that the effect of the program on the stack is (  )
.
USING: formatting kernel math ;
IN: factorialexample
: factorial ( n  n! )
dup
0 =
[ 1 ]
[ dup dup 1  factorial * ]
if
swap over "%d! = %d\n" printf ;
16 factorial
drop
Quadratic equation:
Example for versions Factor 0.94Word quadraticequation
takes coefficients of the equation as input and prints the solution while returning nothing. Note that this word is declared using token ::
instead of :
used in most cases; this means that within it lexically scoped variables can be used, in this case parameters a
, b
and c
as well as local variables d
, x0
and sd
bound by :>
operator. Such variables can be loaded on the stack using their names. Words and operators which process lexically scoped variables are available in dictionary locals
.
Factor provides a builtin data type for complex numbers; whenever the discriminant is negative, its square root will be of type complex
. In this case complex roots are printed using words realpart
and imaginarypart
which extract corresponding parts of a number.
readln
reads a string from input stream (till the end of line), and string>number
(from math.parser
dictionary) converts a string to a floatingpoint number.
USING: formatting io kernel locals math math.functions math.parser ;
IN: quadraticexample
:: quadraticequation ( a b c  )
a 0 =
[ "Not a quadratic equation." printf ]
[ b sq a c * 4 *  :> d
b neg a 2 * / :> x0
d sqrt a 2 * / :> sd
d 0 =
[ x0 "x = %f\n" printf ]
[ d 0 >
[ x0 sd + x0 sd  "x1 = %f\nx2 = %f\n" printf ]
[ x0 sd + [ realpart ] [ imaginarypart ] bi "x1 = (%f, %f)\n" printf
x0 sd  [ realpart ] [ imaginarypart ] bi "x2 = (%f, %f)\n" printf ]
if
]
if
]
if ;
readln string>number
readln string>number
readln string>number
quadraticequation
CamelCase:
Example for versions Factor 0.94This example uses regular expressions. Word resplit
(from regexp
) splits a string into an array of strings separated by matches to the given regular expression. After this map
combinator applies word >title
(from unicode.case
) to each element of the resulting array, converting them to title case. Finally, join
(from sequences
) concatenates the strings into one using “” as a separator.
USING: kernel io regexp sequences unicode.case ;
readln R/ [^azAZ]+/ resplit
[ >title ] map
"" join print
Factorial:
Example for versions Factor 0.94This example uses a builtin word factorial
defined in dictionary math.combinatorics
.
USING: formatting kernel math.combinatorics sequences ;
17 iota [ dup factorial "%d! = %d\n" printf ] each
Comments
]]>blog comments powered by Disqus
]]>