More of the nested_accumulate_list_lr example: - See DEMO for definition - The nested function makes use of the accumulate_list_lr version defined from generic_accumulate_list_lr to handle the processing of each embedded list. - For the nested function, empty_val: the value to be associated with the case of an empty list combining_op: the operation function used for combining elements, as in the accumulate function elt_eval: function that evaluates individual elements to something - The function nested_accumulate_list_lr produces a function that processes a nested list, but the conditional within the body handles cases that aren't a list by applying the single element evaluator function elt_eval to them - The internal function definition for one_level_accumulate handles the implementation of the accumulate_list_lr. The call to accumulate_list_lr could have be used directly in the body, but it might have been hard to read. Application Examples: - See DEMO for definitions and exploration of the following functions. - indentity_function: again this is used as a test implementation. Should returns the input list, but only after being passed through the nested_accumulate_list_lr structure. - operation_log: similar to operation_journal from last lecture. Since we have multiple operation functions now, we must used separate symbols for each (journal used 'cons' to represent all function calls). This is the best test function for the nested_accumulate_list_lr function. - nlist_depth: determines the number of levels of nesting. It increments a counter by calling (lambda (x) (+ x 1)) at each embedded list. - nlist_number_of_atoms: counts the number of atoms in the nested list structure. Returns 0 for empty and (list), and does not count them as atoms when encountered in larger non-zero list structures. - nlist_maxmin: produces a pair of values that hold the maximum and minimum values of the nested list. General Observations on Higher-Order Functions: - The nested_accumulate_list_lr function is limited to passing information up the ladder, from the deepest embedded lists outward. This can be understood best by the following: Consider the alternate tree form of representing lists: (list 1 (list 2 3) 4) /|\ / | \ / | \ / | \ 1 / \ 4 / \ / \ 2 3 If we treat the nodes of this tree as function calls, it is clear that the information must flow up the tree. This is always true in the case of a function that only recursively calls itself. In the case of a set of mutually recursive functions, this isn't always the case, as a call to one could undo the call to the other (e.g. the parser had instances of information flow up and then down the tree).