Overview

This is a brief getting-started guide to rhoScript which introduces the key ideas behind the design of rhoScript.

While rhoScript defines both the high-level and the low-level dense code, all code here is in the rhoScript high-level language. The only difference is that instead of having to manually compute function lengths, and type call functions by typing bit by bit, coding is done with multi-character mnemonics. Think of low-level rhoScript as machine code, and the high-level rhoScript as an assembly language, with an assembler which converts one to the other.

It is important to realize this means that while the functions here look to be quite long, in reality they are significantly shorter. The online repl will report the actual size of entered commands. Click on the run buttons to send any of the commands to the online repl.

This getting started tutorial will cover the basics needed to start writing rhoScript in a few minutes. This is not an attempt to provide an exaustive look at how rhoScript works, or a description of all the commands. See the specification for the former and the reference for the latter.


Basic Commands and Stack Operations

The main mode of operation in rhoScript is the stack. Anything that is not a builtin function pushes itself on to the stack. For example, the following program will add two integers.
1 2 add print run
First 1 is pushed on the stack, then 2 is pushed on the stack. The add function pops the top two values off of the stack, adds them, and then pushes the result back on to the stack. The result is 3. The print function then prints the result. The final print is not actually required: rhoScript automatically prints out the top element of the stack at the end of the program.

You can create a function by enclosing commands with parentheses. This pushes the function on top of the stack. Other operations can then use this function from the top of the stack.
(1 2 add print) call run
This program is very similar to the first program, but with on minor difference. Instead of pushing 1, 2, adding, and printing, the first thing that is done is a function is pushed on to the stack that, when called, will print 3. Then, the builtin call is executed which actually runs the top element of the stack.

In the previous case, there is no reason to push a function. However consider the following case where it is required.
10 range (2 multiply) map run
In this case, first the integer 10 is pushed. Then range is called, which constructs the list of integers from 0 (inclusive) to 10 (exclusive). Next, a function is pused to the stack which, when executed, will multiply the top element of the stack by two. Finally, map is called. Map is one of many higher-order functions built in to rhoScript. Map takes two arguments: a list, and a function. It then constructs a new list by calling the function on each element of the list. The result, in this case, will be the even integers starting from 0 and ending at 18. Note that map is not a destructive map. rhoScript has every other higher order function you may be familiar with: including reduce, filter, fold, but also some you may not be familiar with: unreduce, tabulate, and fixpoint are just a few of them.

List operations in rhoScript are usually lazy operations. That is, they don't run over every element all at once. They are only executed when they are required. This means we can construct and manipulate infinite sequences easily.
naturals rest prefixes (sum) map 100 take run
We begin by constructing an infinite list of all of the integers from 1. Then, we gather all of its prefixes. This is a list, where the first element is the empty list, the second is the list containing just 1, the third contains 1 and 2, and so on. Mapping the sum over the list gives the triangle number sequence A000217. We then take 100 of them.

As a more complicated example, we show how to construct all subsequences of a list.
naturals prefixes (suffixes) map flatten uniq 100 take run
First we create an infinite stream of integers. We then take all prefixes of this list. For each prefix, we then take all suffixes. This leaves us with several duplicates, so we only take the unique ones. Finally, we remove the first 100 and display them.


Arguments and Function Modifiers

The functions in rhoScript are the primary difference between it and most other stack based languages. Below we describe two of the important features of rhoScript functions.

The first of these are function arguments, which allow partial bypassing of the stack for the top four values on a stack when a function is called.

One of the downside of stack-based languages is that they can sometimes require a relatively large amount of stack manipulation to preform a few meaningful operations. To make this less common, rhoScript automatically binds four variables whenever a function is called, from the top four elements on the stack.
100 range (2 mod 0 eq arg-a 3 mod 0 eq or) filter run
This function returns those integers which are divisible by either 2 or 3. It saves saves calling both duplicate/swap within the function by using the saved arguments. arg-a refers to the top element of the stack when the function was called. The same is true for arguments b through d.

Next, we describe function modifiers. These modifiers state common properties about functions which change their behavior. There are two main function modifiers, one states whether or not a function is "restoring" and the other if a function is "exploding".

Functions are stack-restoring by default, but can be made to be not. This allows the stack to be modified in between function calls of higher-order functions.
1 10 range (*non-restoring add dup) map run
Under normal situations, the top element of the stack would be a list from 1 to 10 (inclusive). The extra argument on the stack at the end of each map call is discarded. The non-restoring stack, means that while the first time the mapping function is called, there is already a 1 on the stack, the second time, there is already a 2 on the stack. This results in the list (1 2 4 7 11 16 22 29 37 46). Functions that are not stack restoring are automatically forced; this means you can not use non-stack-restoring functions with infinite lists.


Strings

In rhoScript, strings are simply lists of integers, each being a single byte. A string is created on the stack by surrounding text with double quotes. For example, the following program will concatenate two strings.
"hello " "world" concatenate run
At the moment, strings take a full eight bits per character, and they are not compressed in any way. In the future, strings will be compressed in multiple different ways, with the best method selected as the low-level representation.

Unlike most languages, strings need not be one dimensional lists. rhoScript also allows strings to be a list of list of bytes. In this case, the string is treated as a if each sub-list was a line, and they are joined with a newline when operated on.
"four word list here" split-by-spaces list-to-string transpose run
First, a string represented as a one dimensional byte array is created, which contains the byte 0x10 in three places. split-by-newlines results in a string with four elements: "four", "word", "list", and "here". Converting it to a string results in a new (two-dimensional) string, with the same four substrings. Finally, "transpose" operates by exchanging rows and columns. The resulting string will have the same message, with text printed in columns.


That's it!

You should now know enough to be able to write some simple rhoScript programs. Continue from here by either writing some programs or reading the specification.