clarity-lang / reference

The Clarity Reference
146 stars 34 forks source link

Add `element-at` native function for loading the _ith_ element of a list #39

Closed jcnelson closed 3 years ago

jcnelson commented 3 years ago

This cannot be done in a library function, since the type of element-at is the type of the individual list item. Implementing element-at for each type in a contract not only duplicates a lot of code, but is also inefficient, since it requires a O(n) fold to be applied to the list.

njordhov commented 3 years ago

This cannot be done in a library function, since the type of element-at is the type of the individual list item.

Good point. Writing something like this for each argument type would be a hassle:

(define-read-only (nth-reducer 
                   (item int) 
                   (state {n: int, result (optional int)}))                                                                
  {n: (- (get n state) 1)
   result: (if (is-eq (get n state) 1) (some item) (get result state))})

(define-read-only (nth (items (list 100 int)) (n int))
  (unwrap-panic (get result (fold nth-reducer items {n: n, result: none}))))

(nth (list 1 2 3) 2)  ;; returns the second item in the list 
njordhov commented 3 years ago

Here is a general implementation of nth assuming proposal #41:

(define-private (nth-reducer item state)                                                                
  {n: (- (get n state) 1)
   result: (if (is-eq (get n state) 1) (some item) (get result state))})

(define-private (nth items n)
  (unwrap-panic (get result (fold nth-reducer items {n: n, result: none}))))

(define-read-only (foo)
  (nth (list 1 2 3) 2))
njordhov commented 3 years ago

I suggest reconsidering the name of the function, proposing nth as an alternative, as in:

(define-private (first items)
  (nth items 1))

(define-private (second items)
  (nth items 2))

(define-private (last items)
  (nth items (len items)))
jcnelson commented 3 years ago

This happened.