Skip to content

Commit 339a572

Browse files
committed
Namespace function merge()
1 parent a58b0ad commit 339a572

File tree

4 files changed

+122
-108
lines changed

4 files changed

+122
-108
lines changed

.rubocop_todo.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
Lint/SuppressedException:
1212
Exclude:
1313
- 'lib/facter/facter_dot_d.rb'
14-
- 'lib/puppet/functions/merge.rb'
14+
- 'lib/puppet/functions/stdlib/merge.rb'
1515
- 'lib/puppet/parser/functions/getvar.rb'
1616
- 'lib/puppet/parser/functions/has_interface_with.rb'
1717

lib/puppet/functions/merge.rb

Lines changed: 8 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,14 @@
11
# frozen_string_literal: true
22

3-
# @summary
4-
# Merges two or more hashes together or hashes resulting from iteration, and returns
5-
# the resulting hash.
6-
#
7-
# @example Using merge()
8-
# $hash1 = {'one' => 1, 'two', => 2}
9-
# $hash2 = {'two' => 'dos', 'three', => 'tres'}
10-
# $merged_hash = merge($hash1, $hash2) # $merged_hash = {'one' => 1, 'two' => 'dos', 'three' => 'tres'}
11-
#
12-
# When there is a duplicate key, the key in the rightmost hash will "win."
13-
#
14-
# Note that since Puppet 4.0.0 the same merge can be achieved with the + operator.
15-
# `$merged_hash = $hash1 + $hash2`
16-
#
17-
# If merge is given a single Iterable (Array, Hash, etc.) it will call a given block with
18-
# up to three parameters, and merge each resulting Hash into the accumulated result. All other types
19-
# of values returned from the block (typically undef) are skipped (not merged).
20-
#
21-
# The codeblock can take 2 or three parameters:
22-
# * with two, it gets the current hash (as built to this point), and each value (for hash the value is a [key, value] tuple)
23-
# * with three, it gets the current hash (as built to this point), the key/index of each value, and then the value
24-
#
25-
# If the iterable is empty, or no hash was returned from the given block, an empty hash is returned. In the given block, a call to `next()`
26-
# will skip that entry, and a call to `break()` will end the iteration.
27-
#
28-
# @example counting occurrences of strings in an array
29-
# ['a', 'b', 'c', 'c', 'd', 'b'].merge | $hsh, $v | { { $v => $hsh[$v].lest || { 0 } + 1 } } # results in { a => 1, b => 2, c => 2, d => 1 }
30-
#
31-
# @example skipping values for entries that are longer than 1 char
32-
# ['a', 'b', 'c', 'c', 'd', 'b', 'blah', 'blah'].merge | $hsh, $v | { if $v =~ String[1,1] { { $v => $hsh[$v].lest || { 0 } + 1 } } } # results in { a => 1, b => 2, c => 2, d => 1 }
33-
#
34-
# The iterative `merge()` has an advantage over doing the same with a general `reduce()` in that the constructed hash
35-
# does not have to be copied in each iteration and thus will perform much better with large inputs.
36-
Puppet::Functions.create_function(:merge) do
37-
# @param args
38-
# Repeated Param - The hashes that are to be merged
39-
#
40-
# @return
41-
# The merged hash
42-
dispatch :merge2hashes do
43-
repeated_param 'Variant[Hash[Scalar,Any], Undef, String[0,0]]', :args # this strange type is backwards compatible
44-
return_type 'Hash[Scalar,Any]'
45-
end
46-
47-
# @param args
48-
# Repeated Param - The hashes that are to be merged
49-
#
50-
# @param block
51-
# A block placed on the repeatable param `args`
52-
#
53-
# @return
54-
# The merged hash
55-
dispatch :merge_iterable3 do
56-
repeated_param 'Iterable', :args
57-
block_param 'Callable[3,3]', :block
58-
return_type 'Hash'
59-
end
60-
61-
# @param args
62-
# Repeated Param - The hashes that are to be merged
63-
#
64-
# @param block
65-
# A block placed on the repeatable param `args`
66-
#
67-
# @return
68-
# The merged hash
69-
dispatch :merge_iterable2 do
70-
repeated_param 'Iterable', :args
71-
block_param 'Callable[2,2]', :block
72-
return_type 'Hash'
73-
end
74-
75-
def merge2hashes(*hashes)
76-
accumulator = {}
77-
hashes.each { |h| accumulator.merge!(h) if h.is_a?(Hash) }
78-
accumulator
79-
end
3+
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
804

81-
def merge_iterable2(iterable)
82-
accumulator = {}
83-
enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable)
84-
enum.each do |v|
85-
r = yield(accumulator, v)
86-
accumulator.merge!(r) if r.is_a?(Hash)
87-
end
88-
accumulator
5+
# @summary DEPRECATED. Use the namespaced function [`stdlib::merge`](#stdlibmerge) instead.
6+
Puppet::Functions.create_function(:merge) do
7+
dispatch :deprecation_gen do
8+
repeated_param 'Any', :args
899
end
90-
91-
def merge_iterable3(iterable)
92-
accumulator = {}
93-
enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable)
94-
if enum.hash_style?
95-
enum.each do |entry|
96-
r = yield(accumulator, *entry)
97-
accumulator.merge!(r) if r.is_a?(Hash)
98-
end
99-
else
100-
begin
101-
index = 0
102-
loop do
103-
r = yield(accumulator, index, enum.next)
104-
accumulator.merge!(r) if r.is_a?(Hash)
105-
index += 1
106-
end
107-
rescue StopIteration
108-
end
109-
end
110-
accumulator
10+
def deprecation_gen(*args)
11+
call_function('deprecation', 'merge', 'This function is deprecated, please use stdlib::merge instead.')
12+
call_function('stdlib::merge', *args)
11113
end
11214
end

lib/puppet/functions/stdlib/merge.rb

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# frozen_string_literal: true
2+
3+
# @summary
4+
# Merges two or more hashes together or hashes resulting from iteration, and returns
5+
# the resulting hash.
6+
#
7+
# @example Using stdlib::merge()
8+
# $hash1 = {'one' => 1, 'two', => 2}
9+
# $hash2 = {'two' => 'dos', 'three', => 'tres'}
10+
# $merged_hash = stdlib::merge($hash1, $hash2) # $merged_hash = {'one' => 1, 'two' => 'dos', 'three' => 'tres'}
11+
#
12+
# When there is a duplicate key, the key in the rightmost hash will "win."
13+
#
14+
# Note that since Puppet 4.0.0 the same merge can be achieved with the + operator.
15+
# `$merged_hash = $hash1 + $hash2`
16+
#
17+
# If stdlib::merge is given a single Iterable (Array, Hash, etc.) it will call a given block with
18+
# up to three parameters, and merge each resulting Hash into the accumulated result. All other types
19+
# of values returned from the block (typically undef) are skipped (not merged).
20+
#
21+
# The codeblock can take 2 or three parameters:
22+
# * with two, it gets the current hash (as built to this point), and each value (for hash the value is a [key, value] tuple)
23+
# * with three, it gets the current hash (as built to this point), the key/index of each value, and then the value
24+
#
25+
# If the iterable is empty, or no hash was returned from the given block, an empty hash is returned. In the given block, a call to `next()`
26+
# will skip that entry, and a call to `break()` will end the iteration.
27+
#
28+
# @example counting occurrences of strings in an array
29+
# ['a', 'b', 'c', 'c', 'd', 'b'].stdlib::merge | $hsh, $v | { { $v => $hsh[$v].lest || { 0 } + 1 } } # results in { a => 1, b => 2, c => 2, d => 1 }
30+
#
31+
# @example skipping values for entries that are longer than 1 char
32+
# ['a', 'b', 'c', 'c', 'd', 'b', 'blah', 'blah'].stdlib::merge | $hsh, $v | { if $v =~ String[1,1] { { $v => $hsh[$v].lest || { 0 } + 1 } } } # results in { a => 1, b => 2, c => 2, d => 1 }
33+
#
34+
# The iterative `stdlib::merge()` has an advantage over doing the same with a general `reduce()` in that the constructed hash
35+
# does not have to be copied in each iteration and thus will perform much better with large inputs.
36+
Puppet::Functions.create_function(:'stdlib::merge') do
37+
# @param args
38+
# Repeated Param - The hashes that are to be merged
39+
#
40+
# @return
41+
# The merged hash
42+
dispatch :merge2hashes do
43+
repeated_param 'Variant[Hash[Scalar,Any], Undef, String[0,0]]', :args # this strange type is backwards compatible
44+
return_type 'Hash[Scalar,Any]'
45+
end
46+
47+
# @param args
48+
# Repeated Param - The hashes that are to be merged
49+
#
50+
# @param block
51+
# A block placed on the repeatable param `args`
52+
#
53+
# @return
54+
# The merged hash
55+
dispatch :merge_iterable3 do
56+
repeated_param 'Iterable', :args
57+
block_param 'Callable[3,3]', :block
58+
return_type 'Hash'
59+
end
60+
61+
# @param args
62+
# Repeated Param - The hashes that are to be merged
63+
#
64+
# @param block
65+
# A block placed on the repeatable param `args`
66+
#
67+
# @return
68+
# The merged hash
69+
dispatch :merge_iterable2 do
70+
repeated_param 'Iterable', :args
71+
block_param 'Callable[2,2]', :block
72+
return_type 'Hash'
73+
end
74+
75+
def merge2hashes(*hashes)
76+
accumulator = {}
77+
hashes.each { |h| accumulator.merge!(h) if h.is_a?(Hash) }
78+
accumulator
79+
end
80+
81+
def merge_iterable2(iterable)
82+
accumulator = {}
83+
enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable)
84+
enum.each do |v|
85+
r = yield(accumulator, v)
86+
accumulator.merge!(r) if r.is_a?(Hash)
87+
end
88+
accumulator
89+
end
90+
91+
def merge_iterable3(iterable)
92+
accumulator = {}
93+
enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable)
94+
if enum.hash_style?
95+
enum.each do |entry|
96+
r = yield(accumulator, *entry)
97+
accumulator.merge!(r) if r.is_a?(Hash)
98+
end
99+
else
100+
begin
101+
index = 0
102+
loop do
103+
r = yield(accumulator, index, enum.next)
104+
accumulator.merge!(r) if r.is_a?(Hash)
105+
index += 1
106+
end
107+
rescue StopIteration
108+
end
109+
end
110+
accumulator
111+
end
112+
end

spec/functions/merge_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
require 'spec_helper'
44

5-
describe 'merge' do
5+
describe 'stdlib::merge' do
66
it { is_expected.not_to eq(nil) }
77
it {
88
is_expected.to run \

0 commit comments

Comments
 (0)