Primitive Types

Opshin has 5 primitive types. These are called primitive as they are the basis of all other types and not composed of others.

  • int
  • bool
  • bytes
  • str
  • None

int

This is the only numeric type in Opshin. It represents integer numbers. Opshin's int type works just like the int type in Python and can be written in different notations. Note that all of the below examples evaluate to an integer and can be compared and added to each other!

# Opshin supports typical integer literals:
my_decimal = 17  # decimal notation
my_binary  = 0b10001  # binary notation
my_hex     = 0x11  # hexadecimal notation
my_octal   = 0o121 # octal notation

# What will this print?
print(my_decimal == my_hex)

Operation on integers

OpShin offers a number of builtin operations for integers.

# Addition
a = 5 + 2  # returns 7

# Subtraction
a = 5 - 2  # returns 3

# Multiplication
a = 5 * 2  # returns 10

# Integer division (floored)
a = 5 // 2  # returns 2

# Power
a = 5 ** 2  # returns 25

Proper Division is not supported because UPLC has not way to represent floating point numbers. If you want to perform operations on rational numbers, use the fractions library

bool

The bool type has two possible values: True or False. Control flow (if/else, while) are usually controlled using boolean types.

booly = False

Operation on Booleans

OpShin offers a number of builtin operations for booleans.

# Conjunction
b = True and False  # returns False

# Disjunction
b = True or False  # returns True

# Negation
b = not True  # returns False

# Cast to integer
b = int(True)  # returns 1 (False gives 0)

str

The str type in Opshin stores Strings, i.e. human-readable text. It is mostly used for printing debug messages.

stringy = "hello world"

not_so_secret_message = "..."

Operation on Strings

OpShin offers some builtin operations for strings.

# Concatentation
s = "hello " + "world!"  # Returns "hello world!"

# Cast to integer
s = int("42")  # returns 42

.encode()

str are usually stored in binary format in the so-called UTF-8 encoding. This is for example the case for native token names. The function encode transforms a normal, readable string into its binary representation.

"OpShin".encode()  # returns b"\x4f\x70\x53\x68\x69\x6e"

str()

If you want to convert anything into a string for debugging purposes, you may call the function str on it.

str(42)  # returns "42"

Note that print also implicitly calls str on its input before printing it for your convenience.

print(42)  # prints "42"

Format strings

More conveniently, if you want to combine strings and other values to a nicely formatted output, use formatting strings like this:

print(f"the value of a is {a}, but the value of b is {b}")

This will print the original string and substitute everything between { and } with the evaluated expression.

bytes

The bytes type in Opshin represents an array/string of bytes, i.e. it is a list of integers in the range 0-255. It's usually called ByteArray or ByteString in other programming languages. You may use it to store raw binary data.

my_bytes = b"ooh a bytestring"

This type is usually used to represent hashes or CBOR. Note that bytestrings per default generate the bytestring for the ASCII character input. If you have a bytestring 0xaf2e221a represented in hexadecimal format, you can write it like this as a literal in OpShin.

hashy = b"\xaf\x2e\x22\x1a"

You may also use the helper function bytes.fromhex.

hashy = bytes.fromhex("af2e221a")

Operation on bytes (ByteStrings)

OpShin offers operations for bytestrings.

# Concatentation
s = b"hello " + b"world!"  # Returns b"hello world!"

[] - indexing and slicing

Python has a general concept of accessing elemtns at a specific index or accessing a slice of them. This also works for bytes. You can either access a single byte of the string.

b"test"[1]  # returns 101

Or you can access a substring of the bytes from the first (inclusive) to last (exclusive) indicated index using [a:b] slicing syntax.

b"test"[1:3]  # returns b"es"

In python, negative indices y indicate access at len(x) - y for object x. The following returns the byte at the last position of the byte string!

b"test"[-1]  # returns 116

This also works with slices.

.decode()

bytes may represent unicode UTF-8 encoded strings. This is for example the case for native token names. The function decode transforms a byte string into a normal, readable string.

b"\x4f\x70\x53\x68\x69\x6e".decode()  # returns "OpShin"

.hex()

bytes are better readable when displayed in hexadecimal notation. Use hex for this.

b"\x4f\x70\x53\x68\x69\x6e".hex()  # returns "4f705368696e"

len()

If you want to know the length of a bytestring, call len() on it.

len(b"OpShin")  # returns 6

None

The None type is exactly like the None type in Python. In other cardano smart contract languages it's called unit and denoted by empty brackets, (). It doesn't do anything and is usually used to denote the absence of a value.

null_val = None