That SetValueAtIndex basically rebuilds the entire tree recursively, checking if the current index is as specified by the index argument. See if you understand it better if I over-comment it:
(defun Tree:SetValueAtIndex
(tree index value
/ doSet
) (defun doSet
(tree index
/ tmp
) ;Define the helper function as a nested function so it doesn't interfere with name clashes (cond ((or (not index
) (= index
0)) (cons value
(cdr tree
))) ;If the index arg is nil or 0 this is the position where the value needs to go, so return it into the tree ((atom index
) ;If the index arg is an atom, then we're at the correct level and branch (repeat index
(setq tmp
(cons (car tree
) tmp
) tree
(cdr tree
))) ;Fill the return with the tree's nodes preceding the index (append (reverse tmp
) (list (doSet
(car tree
) nil)) (cdr tree
))) ;Join the preceding, new value and following nodes of the tree, and return it ((= (length index
) 1) (doSet tree
(car index
))) ;If the index is only 1 number, call this function with only the number, not the list (t ;Else (index consists of 2 or more levels)
(repeat (car index
) (setq tmp
(cons (car tree
) tmp
) tree
(cdr tree
))) ;Fill the return with the tree's nodes preceding the index (append (reverse tmp
) (list (doSet
(car tree
) (cdr index
))) (cdr tree
))))) ;Join the preceding, new value and following nodes of the tree, and return it ;The new value for the node is generated recursively, by removing the highest level of the index
;then calling this same function with the node of the tree as if it's a tree on its own
(doSet tree index)) ;Call the helper function and return whatever it returns.
The doSet is calling itself for each level it runs through the index. Most of the work is done in the Else portion of the cond structure.
- It copies the nodes before the current level's index argument to the returned variable
- It then calculates the new node by calling itself with only the node at that index and the rest of the index's levels
- Then it appends the values obtained from the previous 2 and the rest of the current portion of the tree.
I could've done it all without a nested helper function, but since the value argument never changes - it's not necessary to send for each recursion. Thus it's an attempt to make it a bit more optimal: AutoLisp copies each argument to the instance of the new function every time it's called.
The 1st option in the cond structure could actually be omitted. Since the repeat would not run, and the append would not include a nil into the result. It's only there for some optimization.