# Applies a [lambda](https://docs.puppetlabs.com/puppet/latest/reference/lang_lambdas.html) # to every value in a data structure from the first argument, carrying over the returned # value of each iteration, and returns the result of the lambda's final iteration. This # lets you create a new value or data structure by combining values from the first # argument's data structure. # # This function takes two mandatory arguments, in this order: # # 1. An array, hash, or other iterable object that the function will iterate over. # 2. A lambda, which the function calls for each element in the first argument. It takes # two mandatory parameters: # 1. A memo value that is overwritten after each iteration with the iteration's result. # 2. A second value that is overwritten after each iteration with the next value in the # function's first argument. # # @example Using the `reduce` function # # `$data.reduce |$memo, $value| { ... }` # # or # # `reduce($data) |$memo, $value| { ... }` # # You can also pass an optional "start memo" value as an argument, such as `start` below: # # `$data.reduce(start) |$memo, $value| { ... }` # # or # # `reduce($data, start) |$memo, $value| { ... }` # # When the first argument (`$data` in the above example) is an array, Puppet passes each # of the data structure's values in turn to the lambda's parameters. When the first # argument is a hash, Puppet converts each of the hash's values to an array in the form # `[key, value]`. # # If you pass a start memo value, Puppet executes the lambda with the provided memo value # and the data structure's first value. Otherwise, Puppet passes the structure's first two # values to the lambda. # # Puppet calls the lambda for each of the data structure's remaining values. For each # call, it passes the result of the previous call as the first parameter ($memo in the # above examples) and the next value from the data structure as the second parameter # ($value). # # If the structure has one value, Puppet returns the value and does not call the lambda. # # @example Using the `reduce` function # # ~~~ puppet # # Reduce the array $data, returning the sum of all values in the array. # $data = [1, 2, 3] # $sum = $data.reduce |$memo, $value| { $memo + $value } # # $sum contains 6 # # # Reduce the array $data, returning the sum of a start memo value and all values in the # # array. # $data = [1, 2, 3] # $sum = $data.reduce(4) |$memo, $value| { $memo + $value } # # $sum contains 10 # # # Reduce the hash $data, returning the sum of all values and concatenated string of all # # keys. # $data = {a => 1, b => 2, c => 3} # $combine = $data.reduce |$memo, $value| { # $string = "${memo[0]}${value[0]}" # $number = $memo[1] + $value[1] # [$string, $number] # } # # $combine contains [abc, 6] # ~~~ # # @example Using the `reduce` function with a start memo and two-parameter lambda # # ~~~ puppet # # Reduce the array $data, returning the sum of all values in the array and starting # # with $memo set to an arbitrary value instead of $data's first value. # $data = [1, 2, 3] # $sum = $data.reduce(4) |$memo, $value| { $memo + $value } # # At the start of the lambda's first iteration, $memo contains 4 and $value contains 1. # # After all iterations, $sum contains 10. # # # Reduce the hash $data, returning the sum of all values and concatenated string of # # all keys, and starting with $memo set to an arbitrary array instead of $data's first # # key-value pair. # $data = {a => 1, b => 2, c => 3} # $combine = $data.reduce( [d, 4] ) |$memo, $value| { # $string = "${memo[0]}${value[0]}" # $number = $memo[1] + $value[1] # [$string, $number] # } # # At the start of the lambda's first iteration, $memo contains [d, 4] and $value # # contains [a, 1]. # # $combine contains [dabc, 10] # ~~~ # # @since 4.0.0 # Puppet::Functions.create_function(:reduce) do dispatch :reduce_without_memo do param 'Iterable', :enumerable block_param 'Callable[2,2]', :block end dispatch :reduce_with_memo do param 'Iterable', :enumerable param 'Any', :memo block_param 'Callable[2,2]', :block end def reduce_without_memo(enumerable) enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) enum.reduce {|memo, x| yield(memo, x) } end def reduce_with_memo(enumerable, given_memo) enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) enum.reduce(given_memo) {|memo, x| yield(memo, x) } end end