GolfScript
GolfScript is a concatenative programming language embedded on top of Ruby, designed to allow very short programs to be written, in order to win code-golf contests. It supports a range of datatypes including arbitrary precision integers, and a wider range of standard operations than many other esoteric programming languages.
Overview
A GolfScript program is a list of items: integers, lists, strings, blocks, variables, and variable assignments. Integers, when encountered, are simply pushed onto the stack. Lists, strings, and blocks behave similarly. Variables are also pushed onto the stack, except when the variable contains a block. If that happens, the block is executed. When a variable assignment is encountered, the top item on the stack is assigned to the variable, but not popped off the stack.
Syntax and Execution
Lists and blocks are delimited by square brackets and curly brackets, respectively. A block is actually just a string that has special behavior. Variable assignment is done by placing a colon before the variable name. Comments begin with a hash and end at the end of the line. Strings are first evaluated by Ruby, allowing an escape to Ruby expressions and frameworks for those functions not provided by GolfScript, such as floating point and math libraries.
Input and Output
Before a GolfScript program is executed, the input is pushed onto the stack as one long string, and therefore interactive input is impossible. When the program finishes execution, the stack's contents are printed, (apparently) starting from the bottom. There are also some explicit built-in methods of printing.
Built-ins
Most of the golfing power of GolfScript comes from its extensive library of operators. These are actually just variables specially initialized. You can assign values to them if you want. Also, most of the operators are overloaded to provide different results if supplied with different arguments. For example, the asterisk * can mean any of:
- Multiplication, when supplied with two integers
- To execute a block a number of times, when supplied with an integer and a block
- To repeat a string or list a number of times, when supplied with an integer and a string/list
- To join the elements of a string/list together with another string/list, when supplied with two string/lists
- To reduce the elements of a string/list to one element, when supplied with a string/list and a block
Coercion
When needed, integers are coerced to arrays/strings/blocks, arrays are coerced to strings/blocks (each element is converted to a string and the results are concatenated together), and strings are coerced to blocks.
List of built-ins
Here is a list of built-ins (currently incomplete), in roughly increasing order of complexity. The arguments describe what types of objects should be on the stack, written bottom to top. A slash means that the arguments are interchangeable. 'List' means arrays or strings; 'sequence' means lists or blocks. This terminology is largely arbitrary.
Name | Arguments | Description |
---|---|---|
;
|
any | Pop, discard |
.
|
any | Duplicate on stack |
\
|
any, any | Swap top two elements |
@
|
any, any, any | Move third element on bottom to top |
!
|
any | Negation: pushes 1 if argument is 0 or empty string/array/block, 0 otherwise. |
`
|
any | Converts the element to a string that, if evaluated, returns the original |
~
|
int | Bitwise not |
string or block | Evaluate | |
array | Dump the elements onto the stack | |
,
|
int | Construct an array with elements [0, 1, ..., int - 1] |
list | Find the length | |
list, block | Filter: select elements that return true when the block is applied to them. | |
&
|
int, int | Bitwise and |
seq, seq (coerce) | Setwise and | |
|
|
int, int | Bitwise or |
seq, seq (coerce) | Setwise or | |
^
|
int, int | Bitwise xor |
seq, seq (coerce) | Setwise xor | |
$
|
int | Copy stack: copy the nth element of the stack (after popping the argument) to the top. |
list | Sort | |
list, block | Sort, according to a mapping | |
(
|
int | Decrement |
seq | Uncons: push sequence without first item, push first item | |
)
|
int | Increment |
seq | Uncons from right: push sequence without last item, push last item | |
+
|
int, int | Add two integers |
seq, seq (coerce) | Concatenate two sequences | |
-
|
int, int | Subtract |
seq, seq (coerce) | Setwise difference | |
*
|
int, int | Multiply |
int/list | Copy the sequence (int) times and concatenate them together. | |
int/block | Execute it (int) times. | |
list, list | Join. Put the elements of the second sequence in between each element of the first sequence and concatenate. | |
list, block | Fold. Reduce. Whatever. | |
/
|
int, int | Integer division |
list, list | Split around matches with a second array | |
block, block | Unfold: a while loop where the condition test is applied to the top of stack, and if the check passes the element on top of stack is collected into an array. | |
list, block | Each: execute a block over each element, and push the results. | |
%
|
int, int | Integer modulus |
list, list | Split around matches like /, but omit empty results | |
list, int | Select elements with index 0 mod int. If the int is negative the result is reversed, so [1 2 3]-1% reverses the array. | |
list, block | Map. Somewhat like Each except the results go in a list. |
Examples
99 bottles of beer (considerably golfed)
[296,{3/)}%-1%["No more"]+[" bottles":b]294*[b-1<]2*+[b]+[" of beer on the wall\n".8<"\nTake one down, pass it around\n"+1$n+]99*]zip
Quines: Note that since the stack is output at termination, a program like
5
is a quine (as long as no input is given to it). A more non-cheating example could be
{".~"}.~
How it works: block {".~"} pushes the .~ string when evaluated. It's duplicated (blocks are printed with parentheses) and evaluated.
Random example of the golfing that can be done with this code:
~{..{(h{3^3%}%2,@h{2\-}%\;++}{,}if}:h~2/zip{{"ACB"=}%}%n*\;
Computational class
GolfScript is Turing-complete, as it can be shown to be computationally equivalent to Underload: the GolfScript built-ins \.;+{}~
correspond to the TC subset of Underload commands ~:!*()^
.
External resources
- GolfScript homepage
- Examples of golfscript programs submitted with the intent of minimizing program length. (Scroll down to 'right time' or lower for ones you can view.)