ligo/gitlab-pages/docs/intro/what-and-why.md

152 lines
5.3 KiB
Markdown
Raw Normal View History

---
id: what-and-why
title: What & Why
---
Before we get into what LIGO is and why LIGO needs to exist, let's take a look at what options the Tezos blockchain offers us out of the box. If you want to implement smart contracts natively on Tezos, you have to learn [Michelson](https://tezos.gitlab.io/whitedoc/michelson.html).
> 💡 The (Michelson) language is stack-based, with high level data types and primitives and strict static type checking.
Here's an example of Michelson code:
**`counter.tz`**
```text
{ parameter (or (or (nat %add) (nat %sub)) (unit %default)) ;
storage int ;
code { AMOUNT ; PUSH mutez 0 ; ASSERT_CMPEQ ; UNPAIR ;
IF_LEFT
{ IF_LEFT { ADD } { SWAP ; SUB } }
{ DROP ; DROP ; PUSH int 0 } ;
NIL operation ; PAIR } }
```
The contract above maintains an `int` in its storage. It has two entrypoints *(functions)* `add` and `sub` to modify it, and the default *entrypoint* of type unit will reset it to 0.
The contract itself contains three main parts:
- `parameter` - Argument provided by a transaction invoking the contract
- `storage` - Type definition for the contract's data storage.
- `code` - Actual Michelson code that has the provided parameter & the current storage value in its initial stack. It outputs a pair of operations and a new storage value as its resulting stack.
Michelson code consists of *instructions* like `IF_LEFT`, `PUSH ...`, `UNPAIR` that are bundled togeter in what is called a *sequence*. Stack represents an intermediate state of the program, while **storage represents a persistent state**. Instructions are used to modify the run-time stack in order to yield a desired stack value when the program terminates.
> 💡 A Michelson program running on the Tezos blockchain is meant to output a pair of values including a `list of operations` to emit and a new `storage` value to persist
## Differences between a stack and traditional variable management
Stack management might be a little bit challanging, especially if you're coming from a *C-like language*. Let's implement a similar program in Javascript:
**`counter.js`**
```javascript
var storage = 0;
function add(a) {
storage += a
}
function sub(a) {
storage -= a
}
// We're calling this function reset instead of default
// because `default` is a javascript keyword
function reset() {
storage = 0;
}
```
In our javascript program the initial `storage` value is `0` and it can be modified by running the functions `add(a)`, `sub(a)` and `reset()`.
Unfortunately (???), we **can't run Javascript on the Tezos blockchain** at the moment. But we can choose LIGO, which will abstract the stack management and allow us to create readable, type-safe, and efficient smart contracts.
> 💡 You can try running the javascript program [here](https://codepen.io/maht0rz/pen/dyyvoPQ?editors=0012)
## C-like smart contracts instead of Michelson
Let's take a look at a similar LIGO program. Don't worry if it's a little confusing at first; we'll explain all the syntax in the upcoming sections of the documentation.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo
type action is
| Increment of int
| Decrement of int
| Reset of unit
function main (const p : action ; const s : int) : (list(operation) * int) is
block { skip } with ((nil : list(operation)),
case p of
| Increment(n) -> s + n
| Decrement(n) -> s - n
| Reset(n) -> 0
end)
```
<!--CameLIGO-->
```cameligo
type action =
| Increment of int
| Decrement of int
| Reset of unit
let main (p, s: action * int) : operation list * int =
let result =
match p with
| Increment n -> s + n
| Decrement n -> s - n
| Reset n -> 0
in
(([]: operation list), result)
```
<!--ReasonLIGO-->
```reasonligo
type action =
| Increment(int)
| Decrement(int)
| Reset(unit);
let main = (p_s: (action, int)) : (list(operation), int) => {
let p, s = p_s;
let result =
switch (p) {
| Increment(n) => s + n
| Decrement(n) => s - n
| Reset n => 0
};
(([]: list(operation)), result);
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
> 💡 You can find the Michelson compilation output of the contract above in **`ligo-counter.tz`**
The LIGO contract behaves exactly* like the Michelson contract we've saw first, and it accepts the following LIGO expressions/values: `Increment(n)`, `Decrement(n)` and `Reset(n)`. Those serve as `entrypoint` identification, same as `%add` `%sub` or `%default` in the Michelson contract.
**not exactly, the Michelson contract also checks if the `AMOUNT` sent is `0`*
---
## Runnable code snippets & exercises
Some of the sections in this documentation will include runnable code snippets and exercises. Sources for those are available at
the [LIGO Gitlab repository](https://gitlab.com/ligolang/ligo).
### Snippets
For example **code snippets** for the *Types* subsection of this doc, can be found here:
`gitlab-pages/docs/language-basics/src/types/**`
### Exercises
Solutions to exercises can be found e.g. here: `gitlab-pages/docs/language-basics/exercises/types/**/solutions/**`
### Running snippets / excercise solutions
In certain cases it makes sense to be able to run/evaluate the given snippet or a solution, usually there'll be an example command which you can use, such as:
```shell
ligo evaluate-value -s pascaligo gitlab-pages/docs/language-basics/src/variables-and-constants/const.ligo age
# Outputs: 25
```