Recursion
Recursion in Scilla takes some collection type with a beginning and end like a Natural number or the entries of a finite List and can process some logic based on that.
#
forall List entries, call procedureLets assume we are dealing with a Map of ByStr20 Uint128
. This map stores user wallets to token account values.
let user_map : Map ByStr20 Uint128 = Emp ByStr20 Uint128
We want to create some functionality to do something to these entries, our example usecase will be give every user in the Map a singular token everytime a Transition is called.
We cannot use a Map
directly in forall, but we can use the builtin builtin to_list map_name
to return us a list based on the current state of the map. We can use this to iterate, this will cost gas for the conversion equal to the elements being transformed from Map entry into List entry. When RewardEveryoneOneToken
passes user_map_as_list
to GiveReward
it passes each element as a Pair ByStr20 Uint128
to which the developer then parses these types out to use them.
transition RewardEveryoneOneToken() (* read the whole map *) full_read_user_map <- user_map;
(* convert each Map element to a List *) user_map_as_list = builtin to_list full_read_user_map;
(* when we iterate a MappedList, it's passed as a Pair of map_key, map_value*) forall user_map_as_list GiveReward;end
let uint128_one = Uint128 1
procedure GiveReward(user_amount_pair : Pair ByStr20 Uint128) (* get the first value of a Pair of ByStr20 Uint128 *) user_address = let fst_user_address = @fst ByStr20 Uint128 in fst_user_address user_amount_pair;
(* get the second value of a Pair of ByStr20 Uint128 *) user_amount = let snd_user_amount = @snd ByStr20 Uint128 in snd_user_amount user_amount_pair;
(* user_amount += 1 *) user_amount_plus_rewards = builtin add user_amount uint128_one;
(* set this value in state *) user_map[user_address] := user_amount_plus_rewardsend
#
Fibonacci folding examplelet fib = fun (n : Nat) => let iter_fun = fun (res : Product Int Int) => fun (n: Nat) => match res with | Pair x y => let z = builtin add x y in Pair {Int Int} z x end in let zero = 0 in let one = 1 in let init_val = Pair {Int Int} one zero in let typed_folder = @nat_fold (Product Int Int) in let folder = typed_folder iter_fun init_val in let res = folder n in match res with | Pair x y => x end