Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local functions #56

Open
kantai opened this issue Mar 14, 2023 · 1 comment
Open

Local functions #56

kantai opened this issue Mar 14, 2023 · 1 comment
Labels
clarity-3-candidate Changes that are considered to be included in Clarity 3

Comments

@kantai
Copy link
Contributor

kantai commented Mar 14, 2023

Iteration methods (especially map and filter) could be much simpler with the introduction of local functions. A local function can read the surrounding function's context, but defines its own arguments and variables. Its variable may shadow the surrounding function's variables.

An example from pox-2:

(define-private (add-pox-addr-to-ith-reward-cycle (cycle-index uint) (params (tuple
                                                            (pox-addr (tuple (version (buff 1)) (hashbytes (buff 32))))
                                                            (reward-set-indexes (list 12 uint))
                                                            (first-reward-cycle uint)
                                                            (num-cycles uint)
                                                            (stacker (optional principal))
                                                            (amount-ustx uint)
                                                            (i uint))))
    (let ((reward-cycle (+ (get first-reward-cycle params) (get i params)))
          (num-cycles (get num-cycles params))
          (i (get i params))
          (reward-set-index (if (< i num-cycles)
            (let ((total-ustx (get-total-ustx-stacked reward-cycle))
                  (reward-index
                      ;; record how many uSTX this pox-addr will stack for in the given reward cycle
                      (append-reward-cycle-pox-addr
                        (get pox-addr params)
                        reward-cycle
                        (get amount-ustx params)
                        (get stacker params)
                        )))
                  ;; update running total
                  (map-set reward-cycle-total-stacked
                     { reward-cycle: reward-cycle }
                     { total-ustx: (+ (get amount-ustx params) total-ustx) })
                  (some reward-index))
            none))
          (next-i (if (< i num-cycles) (+ i u1) i)))
    {
        pox-addr: (get pox-addr params),
        first-reward-cycle: (get first-reward-cycle params),
        num-cycles: num-cycles,
        amount-ustx: (get amount-ustx params),
        stacker: (get stacker params),
        reward-set-indexes: (match
            reward-set-index new (unwrap-panic (as-max-len? (append (get reward-set-indexes params) new) u12))
            (get reward-set-indexes params)),
        i: next-i
    }))

(define-private (add-pox-addr-to-reward-cycles (pox-addr (tuple (version (buff 1)) (hashbytes (buff 32))))
                                               (first-reward-cycle uint)
                                               (num-cycles uint)
                                               (amount-ustx uint)
                                               (stacker principal))
  (let ((cycle-indexes (list u0 u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11))
        (results (fold add-pox-addr-to-ith-reward-cycle cycle-indexes
                         { pox-addr: pox-addr, first-reward-cycle: first-reward-cycle, num-cycles: num-cycles,
                           reward-set-indexes: (list), amount-ustx: amount-ustx, i: u0, stacker: (some stacker) }))
...

Combining local functions and a range function (#50):

(define-private (add-pox-addr-to-reward-cycles (pox-addr (tuple (version (buff 1)) (hashbytes (buff 32))))
                                               (first-reward-cycle uint)
                                               (num-cycles uint)
                                               (amount-ustx uint)
                                               (stacker principal))
  (let ((local-add-to-reward-cycle 
            (lambda (cycle-index uint)
               (let ((reward-cycle (+ first-reward-cycle cycle-index))
                     (reward-set-index 
                       (if (< cycle-index num-cycles)
                         (let ((total-ustx (get-total-ustx-stacked reward-cycle))
                               (reward-index
                                ;; record how many uSTX this pox-addr will stack for in the given reward cycle
                                (append-reward-cycle-pox-addr pox-addr reward-cycle amount-ustx stacker)))
                           ;; update running total
                           (map-set reward-cycle-total-stacked
                                    { reward-cycle: reward-cycle }
                                    { total-ustx: (+ amount-ustx total-ustx) })
                           (some reward-index))
                         none))))))
        (results (map local-add-to-reward-cycle (range u0 u11)))
...

Note how much of the fold accumulator is dedicated just to marshaling local variables to the iteration.

@MarvinJanssen
Copy link
Member

+1

Lambdas would make many things a lot more efficient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clarity-3-candidate Changes that are considered to be included in Clarity 3
Projects
None yet
Development

No branches or pull requests

3 participants