Sending and Receiving
Sending and receiving is one of the most important things to understand in Rholang.
Note
Because Rholang is an asynchronous programming langugage, there is no return in a function. That's why you call a function HelloWorld(args) via sending on the functions name HelloWorld. You are sending via the ! syntax.
Note
Because of the asynchrony you don't know when the function you called via HelloWorld!(args) is sending the processed data back over some other channel, Rholang has the for(args<-channels) syntax for waiting until all the needed arguments are received over the channels.
Example
1
2
3
4
5
6
new HelloWorld, stdout(`rho:io:stdout`) in {
HelloWorld!("Hello, world!") |
for (@text <- HelloWorld) {
stdout!(text)
}
}
This line declares a new name-valued variable
HelloWorldand assigns to it a newly-created private name.Every name is of the form
@P, wherePis a rholang process. The!production takes a namenon its left and a processPon its right, then sends@Pover the channel namedn. Lineforms the name@"Hello, world"and sends it on the channel whose name is stored in the variableHelloWorld.This
forproduction creates a process that waits for a single message to be sent on the channel whose name is stored in the variableHelloWorld. The pattern@textgets matched against the serialized process, binding the process-valued variabletextto the original process that was sent.Rholang runtime environments may choose to include built-in processes listening on channels. In this tutorial, we use new with the urn
rho:io:stdoutto request a channel where sent messages get printed to a console.
Note
When you send data over a channel and there is no contract which is listening with for(args<-channels) for that channel, then these data is stored in the tuplespace (like a database), until some contract is starting to listening for it.
Name Equivalence
It is possible to write one single name in several different ways. For example, the two following channels are equivalent:
1
2
@{10 + 2}
@{5 + 7}
Any message sent over these channels can be received by listening on the channel @12. There are other instances in which a name can be written in two different ways. The guiding principle for this is that if P and Q are two equivalent processes, then @P and @Q are equivalent names. In particular, all of the following channels are equivalent:
1
2
3
@{ P | Q }
@{ Q | P }
@{ Q | P | Nil }
Before using a channel, Rholang first evaluates expressions and accounts for these | rules at the top level--but only at the top level. This means that if an arithmetic expression forms part of a pattern within a pattern, it is left untouched. Because of this,
1
for( @{ x + 5 } <- @"chan" ){ ... }
will never receive any message on @"chan" since if we send anything, such as 10 + 5, over @"chan", the arithmetic expression gets evaluated and the name @15 is sent.
Finally, channels also respect a change in variable name (alpha equivalence), so the following channels are equivalent:
1
2
@{ for( x <- chan ){ ... } }
@{ for( z <- chan ){ ... } }
Replicated receive
1
2
3
4
5
6
7
new HelloWorld, stdout(`rho:io:stdout`) in {
for (@text <= HelloWorld) {
stdout!(text)
} |
HelloWorld!("Hello, world!") |
HelloWorld!("Hola, mundo!")
}
2.) Instead of handling only a single message, a for using a double arrow <= will persist, spawning a copy of the body for each message received.
5-6) We send the string processes "Hello, world!" and "Hola, mundo!" on the channel HelloWorld. It is non-deterministic which message will be processed first.
Contracts as sugar for replicated receive
1
2
3
4
5
6
7
new HelloWorld, stdout(`rho:io:stdout`) in {
contract HelloWorld(@text) = {
stdout!(text)
} |
HelloWorld!("Hello, world!") |
HelloWorld!("Hola, mundo!")
}
2.) The only difference between this example and the last one is this line. The contract production is syntactic sugar. The process contract Name(...formals) = { P } means the same as for (...formals <= Name) { P }.
Replicated send
1
2
3
4
5
6
7
8
9
new HelloWorld, stdout(`rho:io:stdout`), stderr(`rho:io:stderr`) in {
HelloWorld!!("Hello, world!") |
for (@text <- HelloWorld) {
stdout!(text)
} |
for (@text <- HelloWorld) {
stderr!(text)
}
}
2.) The double-bang !! means that this message will be sent again as soon as it is read.
3-4, 6-7) There are two listening processes; each one consumes a single message from the channel and forwards it to either "stdout" or "stderr". The order in which they get forwarded to those channels is nondeterministic.
Sequential send
In order to have one message follow after another is known to have been received, we must use an acknowledgement message.
1
2
3
4
5
6
7
8
9
new chan, ack, stdoutAck(`rho:io:stdoutAck`) in {
chan!(0) |
for (_ <- ack) {
chan!(1)
} |
for (@num <= chan) {
stdoutAck(num, *ack)
}
}
- We send the message 0 on
chan. - We wait for a message on the channel
ack, throw it away, and then proceed with the body. - We send the messageon
chan. - We listen persistently for messages sent on
chan. - We forward each message to the channel
"stdoutAck", which expects both a value to print and a channel on which to send an acknowledgement message that the text has been received and printed. In this program, we are guaranteed that 0 will be printed before 1.
Sending and receiving multiple processes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
new chan, stdout(`rho:io:stdout`) in {
chan!(1,2,3) |
chan!((4,5,6)) |
chan!(7,8) |
chan!([9, 10], 11) |
chan!(12 | 13) |
for (@x, @y, @z <= chan) {
stdout!(["three", x, y, z])
} |
for (@a, @b <= chan) {
stdout!(["two", a, b])
} |
for (@a <= chan) {
stdout!(["one", a])
}
}
- We send three numeric processes on
chan. This send necessarily synchronizes with theforon line 7. - We send one tuple process on
chan. This send necessarily synchronizes with theforon line 13. - We send two numeric processes on
chan. This send necessarily synchronizes with theforon line 10. - We send a list process and a numeric process on
chan. This send necessarily synchronizes with theforon line 10. - We send a single process that is the par of two numeric expressions on
chan. This send necessarily synchronizes with theforon line 13.