THE CONCATENATIVE LANGUAGE X (incomplete) * Introduction X is a concatenative language with K semantics. * Notation "abc" string "a" string of one character 'a character 10 integer 10.2 float 10: negative integer 10.2: negative float [a 10] lazy list (quotation) [10] list of one element A name begins with a-zA-Z, followed by characters drawn from .:a-zA-Z0-9. For example, the following are valid names: a a: a.b2.c: a..foo123:bar.. * Words and Comments An X word is an association of a symbol and an evaluation rule. A word is created by enclosing the symbol and the rule in semicolons: ;add2 2+; A word is destroyed by enclosing just the symbol in semicolons: ;add2; A (single-line) comment is preceded by two semicolons: ;; this is a comment A single semicolon entered at the prompt clears the stack: ; * Constants X has eleven constants: X K meaning - - ------- nul _n atomic null sym ` empty symbol atom SYM 0#` null symbol vector INT 0#0 null integer vector FLT 0#0. null float vector NAN 0N min int nan 0n NaN: not a number INF 0I max int INF: -0I NAN+1 inf 0i Inf: infinity inf: -0i -Inf: negative infinity * Data X has all but one of the primitive K datatypes: integers, floats, characters, symbols, dictionaries, null, and lists. X does not have lambdas. To say that X has datatype d means that an element of type d may appear in the result stack. * Valence and Charge The valence of a function is the number of arguments it takes. For example, + has valence 2 and !: has valence 1. In K, the valence of a function and the rank (dimensionality) of an array are puns. If f is a function of valence k > 1, then f[a] -- f applied to a -- is a function of valence k-1. f is said to be "projected", or "curried" on a. The charge of a function is the number of results it returns. In K, all functions have charge 1. This is true even when the function returns a list of arbitrary length and depth. In a concatenative language, all objects are functions from the stack to the stack. For example, 10 is a function which takes the stack and returns it with TOS (top of stack) = 10. In such a language, data has charge 1. Stack operations have valence and charge. For example, 'dup' has valence 1 and charge 2, and 'zap' has valence 1 and charge 0. * Functions X has the twenty symbolic K functions: ~ | @ # $ % ^ & * - _ = + | < , > : . ? Each function has three forms: v dyad v: monad v. commuted dyad X has the seven IO functions of K. For example, K's 4: is spelled "four", and 4:: is spelled "four:". X also has all the system functions of K. Leading underscores are dropped in this case; for example, K's _in is spelled "in". The dyadic system functions have commuted forms: for example, "in." is y _in x. X has eight additional functions: words return a list of the words of X x signal 'x x trace x=0: no trace, x>0: trace, x<0: timings, no display x y def ;y x; x def: value of word x x def. ;x; x parse parse x, return the result as a list x represent represent x, return the result as a string * Combinators A combinator is a function which returns a function. Every X combinator takes at least one quotation as an argument, and may in addition take one or more parameters. The function returned by the combinator is said to be "derived" by the combinator. Functions are not X datatypes. That is, a function may not appear on the result stack. When X detects a functional result, it prepends it to the input queue. When X detects a functional input, it applies it to the stack. All derived functions are treated as though they have valence 1. If the function has valence k > 1, then the result will be a function of valence k-1. The K adverbs are combinators which derive functions of charge 1.