Skip to content

Instantly share code, notes, and snippets.

@tgrospic
Last active February 18, 2019 16:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tgrospic/5e32fb9e9090c0a95af29c17e8e6c8a3 to your computer and use it in GitHub Desktop.
Save tgrospic/5e32fb9e9090c0a95af29c17e8e6c8a3 to your computer and use it in GitHub Desktop.
Rholang compose operators
new compose in {
contract compose(input ...@sends) = {
for(...@inp <= input) {
new apply in {
apply!(inp, sends) |
contract apply(argsc, @[send ...rest]) = {
match rest {
[] => {
// the last contract is the end of composition and it's called with suplied args
// and args returned from previous contract (without return channel)
match send { [s ...args] => @s!(args ++ *argsc) }
}
_ => {
new ret in {
// each contract is called with arguments combined from: suplied args,
// args returned from previous contract and a new return channel
match send { [s ...args] => @s!(args ++ *argsc ++ [*ret]) } |
// match send { {@s!(...args)} => @s!(...args ...*argsc, *ret) } |
for(...@inp' <- ret) { apply!(inp', rest) }
}
}
}
}
}
}
} |
new name, location, hash, print, out(`rho:io:stdout`) in {
contract name (@[a, ret]) = { @ret!("Name: " ++ a) } |
contract location (@[a, b, ret]) = { @ret!([a, b]) } |
contract hash (@[a, b, ret]) = { @ret!({"Hash": a, "Data": b}) } |
contract print (@[a ]) = { out!(a) } |
new nameLocHash in {
// nameLocHash contract is a composition (sequence in this case)
// of name, location, hash and print contracts
contract nameLocHash(inp) = {
new ret1, ret2, ret3 in {
name!([*inp, *ret1]) |
for(ret1' <- ret1) {
location!([42, *ret1', *ret2]) |
for(ret2' <- ret2) {
hash!(["SHA1", *ret2', *ret3]) |
for(ret3' <- ret3) {
print!([*ret3'])
}
}
}
}
} |
nameLocHash!("Beth") |
nameLocHash!("Summer")
} |
new nameLocHash in {
// - version with compose without creating intermediate channels
// nameLocHash contract is a composition (sequence in this case)
// of name, location, hash and print contracts
compose!(*nameLocHash
, [*name]
, [*location, 666]
, [*hash, "SHA256"]
, [*print]
) |
nameLocHash!("Rick") |
nameLocHash!("Morty")
/* I'm using the list because it's much easier to use it with
// spread operator to match and construct arguments, so it's
// easy to imagine compose used like this
compose!(*nameLocHash
, *name
, location!(42)
, hash!("SHA1")
, *print
)
|
// more complicated example with multiple return channels,
// we can define different connectors to match output/input
compose!(*nameLocHash
, *name
, location!(42)
, hash!("SHA1")
, *verify // returns (left, right)
, *pickRight // (left, right) -> right
, *print
)
|
// my motivation is to be able to write something like this,
// defining custom operators which looks like overloads of Par
// - we can translate this to previous example with compose!(,,,)
*nameLocHash
<= *name
|> location!(42)
|> hash!("SHA1")
|> *verify
*> *print
|
// pattern matching on custom operators would be extremely useful, if not necessary
new xr, yr in {
match proc {
{c <= x |> y} => for(@x' <= c) { @x!(x', *xr) | for(@y' <- xr) { @y!(y', *yr) } }
}
}
|
// can we go even further and encode match with (|=> and =>)?
proc
|=> {a /\ String} => out!(a ++ "!")
|=> {a /\ Int} => out!(a + 10)
*/
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment