diff --git a/src/array.cr b/src/array.cr index 23d1c2961859..14fe829a1e26 100644 --- a/src/array.cr +++ b/src/array.cr @@ -1327,7 +1327,7 @@ class Array(T) # and *enumerable* as a `Tuple`. # Traversal of elements starts from *enumerable*. @[Deprecated("Use `Indexable#each_cartesian(*others : Indexable, &block)` instead")] - def product(enumerable : Enumerable, &block) + def product(enumerable : Enumerable, &) self.each { |a| enumerable.each { |b| yield a, b } } end diff --git a/src/hash.cr b/src/hash.cr index 34acf10d352a..fd30463246a6 100644 --- a/src/hash.cr +++ b/src/hash.cr @@ -1384,13 +1384,8 @@ class Hash(K, V) # hash.merge!({"baz" => "qux"}) # hash # => {"foo" => "bar", "baz" => "qux"} # ``` - def merge!(other : Hash(L, W)) : self forall L, W - {% unless W <= V && L <= K %} - {% raise "Hash(#{L}, #{W}) can't be merged into Hash(#{K}, #{V})" %} - {% end %} - other.each do |k, v| - self[k] = v - end + def merge!(other : Hash) : self + other.merge_into!(self) self end @@ -1404,19 +1399,33 @@ class Hash(K, V) # hash.merge!(other) { |key, v1, v2| v1 + v2 } # hash # => {"a" => 100, "b" => 454, "c" => 300} # ``` - def merge!(other : Hash(L, W), & : L, V, W -> V) : self forall L, W - {% unless W <= V && L <= K %} - {% raise "Hash(#{L}, #{W}) can't be merged into Hash(#{K}, #{V})" %} + def merge!(other : Hash, &) : self + other.merge_into!(self) { |k, v1, v2| yield k, v1, v2 } + self + end + + protected def merge_into!(other : Hash(K2, V2)) forall K2, V2 + {% unless K2 >= K && V2 >= V %} + {% raise "#{Hash(K, V)} can't be merged into #{Hash(K2, V2)}" %} {% end %} - other.each do |k, v| - if self.has_key?(k) - self[k] = yield k, self[k], v + each do |k, v| + other[k] = v + end + end + + protected def merge_into!(other : Hash(K2, V2), & : K, V2, V -> V2) forall K2, V2 + {% unless K2 >= K && V2 >= V %} + {% raise "#{Hash(K, V)} can't be merged into #{Hash(K2, V2)}" %} + {% end %} + + each do |k, v| + if other.has_key?(k) + other[k] = yield k, other[k], v else - self[k] = v + other[k] = v end end - self end # Returns a new hash consisting of entries for which the block returns `true`. diff --git a/src/indexable.cr b/src/indexable.cr index 9d2ddd8d38f3..16af996ce055 100644 --- a/src/indexable.cr +++ b/src/indexable.cr @@ -705,7 +705,7 @@ module Indexable(T) end # Optimized version of `equals?` used when `other` is also an `Indexable`. - def equals?(other : Indexable(U), & : T, U ->) : Bool forall U + def equals?(other : Indexable, &) : Bool return false if size != other.size each_with_index do |item, i| return false unless yield(item, other.unsafe_fetch(i))