Code a compute graph

Code

Let's now try writing our own function. This assumes you have a running TinyChain host, following the instructions in Getting Started:
1
# new file: test.py
2
3
import tinychain as tc
4
5
# this is the local TinyChain host you just started with "docker run..."
6
HOST = tc.host.Host("http://127.0.0.1:8702")
7
8
# this endpoint will attempt to run whatever program you send it
9
# without committing any write operations
10
ENDPOINT = "/transact/hypothetical"
11
12
# define a GET Op
13
# the type annotations are important!
14
# without them, TinyChain doesn't know what type to expect the arguments to be
15
@tc.get_op
16
def hello(name: tc.String) -> tc.String:
17
return tc.String("Hello, {{name}}").render(name=name)
18
19
if __name__ == "__main__":
20
cxt = tc.Context() # construct a new execution context
21
cxt.hello = hello # include our function definition in the context
22
cxt.result = cxt.hello("Name") # call the function
23
24
print(HOST.post(ENDPOINT, cxt)) # evaluate the context on the host
25
Copied!

Test

Check that it works as expected:
1
$ python3 test.py
2
Hello, Name
Copied!
This requires some scaffolding in order to set up but it's a very convenient starting point for more advanced use cases.

Understand

If you're curious about how this works under the hood, you can inspect the JSON that gets sent to the host:
1
# ...
2
tc.print_json(cxt)
Copied!
You should see something like:
1
[
2
[
3
"hello",
4
{
5
"/state/scalar/op/get": [
6
"name",
7
[
8
[
9
"String_7f8cf85223d0",
10
"Hello, {{name}}"
11
],
12
[
13
"_return",
14
{
15
"$String_7f8cf85223d0/render": {
16
"name": {
17
"$name": []
18
}
19
}
20
}
21
]
22
]
23
]
24
}
25
],
26
[
27
"result",
28
{
29
"$hello": [
30
"Name"
31
]
32
}
33
]
34
]
35
Copied!
In general you shouldn't have to worry about what the generated JSON looks like, but it can be convenient to give explicit names to the internal states of an Op. You can do this by using the cxt or txn keyword—just like Python treats the "self" keyword specially in a method declaration, assigning it a reference to the method's instance, TinyChain treats the cxt or txn keyword specially, assigning it a reference to the Op's execution context. For example:
1
# ...
2
@tc.get_op
3
def hello(cxt, name):
4
cxt.template = tc.String("Hello, {{name}}")
5
return cxt.template.render(name=name)
6
# ...
7
Copied!
If you again inspect the JSON representation of your compute graph, you'll see that the anonymous "String..." name has been replaced by "template."
Copy link