main {
print "Hello world!"
}
Every Röda program consists of a list of function declarations.
When the program is run, the interpreter executes the main
function (defined by lines 1 and 3).
At line 2 there is the body of the function that happens to be a single function call.
For the rest of this guide I will omit the signature of the main program.
In Röda statements are also called commands. We have already seen a function call, which is the most used command type,
but there are also many others like if
, while
and for
.
The maybe second most used command is variable assignment. Below is a basic example of that.
name := "Caroline"
age := 31
print name, ", ", age, " years"
age = 32
print name, ", ", age, " years"
Here we declare two variables, name
and age
and use them to print an introductive text of a person: Caroline, 31 years
.
Then we change the age variable and print to same text again. In Röda :=
is used to create a new variable and =
to edit an old.
Using variables and a while loop we can print the first even numbers:
i := 0
while [ i < 10 ] do
print i*2
i++
done
Like in Bourne shell, condition is a command. It can be an arithmetic command []
or a normal function call like below.
fileExists
is used to check if the file exists.
if fileExists "log.txt" do
{} | exec "rm", "log.txt" | {}
done
Unlike Bourne shell, if
statements have do
and done
, not then
and fi
.
In this section we're going to review some syntactic features of Röda which may be confusing to beginners. In README.md, I used this prime generator as an example:
primes := [2]
seq 3, 10000 | { primes += i if [ i % p != 0 ] for p in primes } for i
print p for p in primes
What does that program do? If you execute it, it will pause for a moment and then print the first prime numbers up to 9973. It makes a heavy use of a syntactic sugar called suffix control structures. They are a shorter way to write loops and conditionals.
Let's look at the last line first. It takes the primes
array and prints its content, each number to its own line.
It consists of the statement, print p
, and the suffix, for p in primes
. The only difference to a normal loop is that the
body is written before the loop declaration.
But how does the second line work? I have written the loops and conditionals without suffix syntax below:
seq 3, 10000 | for i do
if for p in primes do [ i % p != 0 ] done do
primes += i
done
done
As you can see, it is a basic seq for
-loop that iterates numbers from 3 to 10000.
It then uses an if statement to determinate if the number is a prime, but how can there be a loop inside the condition?
It happens that in Röda conditions are just statements and the value of the condition is just taken from the output stream of the statement.
In this case the loop pushes more than one boolean to the stream and the body of the condition is executed when all of them are true.
The condition can in other words be read a number is a prime if none of the previous primes divide it.
So are these suffix commands really required? It seems that one must read the code backwards to understand them! Still, they can be handy sometimes: they provide a more natural syntax to do many things like list comprehension and looped conditions (see below). It is advisable not to nest these more than two levels, though.
The suffix syntax is a generalization of many other features like list comprehension, map
- and filter
-functions, looped conditionals, etc.
new_list := [statement for variable in list if statement]
Examples:
names := [get_name(client) for client in clients]
adults := [push(client) for client in clients if [ client.age >= 18 ]]
pwdir := pwd()
directories := [push(pwdir.."/"..f) for f in files if isDirectory(f)]
for
can also used in pipes. if
and unless
are right-associative, so braces {}
should be used around them.
["Pictures/", "Music/"] | bufferedExec("ls", dir) for dir | { [ f ] for f unless isDirectory(f) } | for f do
print f.." "..mimeType(f)
done
if [ condition ] for element in list do
done
Ensures that the condition is true for all elements in list.
if isDirectory(f) for f in [ls(".")] do
print "All files are directories!"
done