diff --git a/lib/hamster/enumerable.rb b/lib/hamster/enumerable.rb
index e3faaceb..4f473b05 100644
--- a/lib/hamster/enumerable.rb
+++ b/lib/hamster/enumerable.rb
@@ -23,27 +23,27 @@ def compact
 
     # Search the collection for elements which are `#===` to `item`. Yield them to
     # the optional code block if provided, and return them as a new collection.
-    def grep(pattern, &block)
+    def grep(pattern)
       result = select { |item| pattern === item }
-      result = result.map(&block) if block_given?
+      result = result.map { |i| yield(i) } if block_given?
       result
     end
 
     # Search the collection for elements which are not `#===` to `item`. Yield
     # them to the optional code block if provided, and return them as a new
     # collection.
-    def grep_v(pattern, &block)
+    def grep_v(pattern)
       result = select { |item| !(pattern === item) }
-      result = result.map(&block) if block_given?
+      result = result.map { |i| yield(i) } if block_given?
       result
     end
 
     # Yield all integers from 0 up to, but not including, the number of items in
     # this collection. For collections which provide indexed access, these are all
     # the valid, non-negative indices into the collection.
-    def each_index(&block)
+    def each_index
       return enum_for(:each_index) unless block_given?
-      0.upto(size-1, &block)
+      0.upto(size-1) { |i| yield(i) }
       self
     end
 
@@ -153,7 +153,12 @@ def pretty_print(pp)
       # @private
       def sort_by(&block)
         result = to_a
-        result.frozen? ? result.sort_by(&block) : result.sort_by!(&block)
+
+        if result.frozen? 
+          result.sort_by { |i| yield(i) }
+        else 
+          result.sort_by! { |i| yield(i) }
+        end
       end
     end
   end
diff --git a/lib/hamster/hash.rb b/lib/hamster/hash.rb
index d1a2df08..aa21175b 100644
--- a/lib/hamster/hash.rb
+++ b/lib/hamster/hash.rb
@@ -332,9 +332,9 @@ def delete(key)
     #
     # @yield [key, value] Once for each key/value pair.
     # @return [self]
-    def each(&block)
+    def each
       return to_enum if not block_given?
-      @trie.each(&block)
+      @trie.each { |entry| yield(entry) }
       self
     end
     alias :each_pair :each
@@ -352,9 +352,9 @@ def each(&block)
     #
     # @yield [key, value] Once for each key/value pair.
     # @return [self]
-    def reverse_each(&block)
+    def reverse_each
       return enum_for(:reverse_each) if not block_given?
-      @trie.reverse_each(&block)
+      @trie.reverse_each { |entry| yield(entry) }
       self
     end
 
@@ -424,9 +424,9 @@ def map
     # @yield [key, value] Once for each key/value pair.
     # @yieldreturn Truthy if this pair should be present in the new `Hash`.
     # @return [Hash]
-    def select(&block)
+    def select
       return enum_for(:select) unless block_given?
-      derive_new_hash(@trie.select(&block))
+      derive_new_hash(@trie.select { |entry| yield(entry) })
     end
     alias :find_all :select
     alias :keep_if  :select
diff --git a/lib/hamster/mutable_hash.rb b/lib/hamster/mutable_hash.rb
index dcbc8162..1744ec1e 100644
--- a/lib/hamster/mutable_hash.rb
+++ b/lib/hamster/mutable_hash.rb
@@ -10,8 +10,8 @@ def self.[](pairs = {})
       MutableHash.new(Hash[pairs])
     end
 
-    def put(key, value = Undefined, &block)
-      transform { |hash| hash.put(key, value, &block) }
+    def put(key, value = Undefined)
+      transform { |hash| hash.put(key, value) { |i| yield(i) } }
     end
 
     def store(key, value)
diff --git a/lib/hamster/sorted_set.rb b/lib/hamster/sorted_set.rb
index 459b940c..caf3d534 100644
--- a/lib/hamster/sorted_set.rb
+++ b/lib/hamster/sorted_set.rb
@@ -86,7 +86,7 @@ def initialize(items=[], &block)
       items = items.to_a
       if block
         if block.arity == 1 || block.arity == -1
-          comparator = lambda { |a,b| block.call(a) <=> block.call(b) }
+          comparator = lambda { |a,b| yield(a) <=> yield(b) }
           items = items.sort_by(&block)
         else
           comparator = block
@@ -354,9 +354,9 @@ def values_at(*indices)
     #
     # @yield [item]
     # @return [self, Enumerator]
-    def each(&block)
+    def each
       return @node.to_enum if not block_given?
-      @node.each(&block)
+      @node.each { |entry| yield(entry) }
       self
     end
 
@@ -373,9 +373,9 @@ def each(&block)
     #   # => Hamster::SortedSet["A", "B", "C"]
     #
     # @return [self]
-    def reverse_each(&block)
+    def reverse_each
       return @node.enum_for(:reverse_each) if not block_given?
-      @node.reverse_each(&block)
+      @node.reverse_each { |entry| yield(entry) }
       self
     end
 
@@ -477,7 +477,7 @@ def include?(item)
     #
     # @return [SortedSet]
     def sort(&block)
-      if block
+      if block_given?
         self.class.new(self.to_a, &block)
       else
         self.class.new(self.to_a.sort)
@@ -757,9 +757,9 @@ def intersect?(other)
     #     # => nil
     #
     # @param item [Object]
-    def above(item, &block)
+    def above(item)
       if block_given?
-        @node.each_greater(item, false, &block)
+        @node.each_greater(item, false) { |n| yield(n) }
       else
         self.class.alloc(@node.suffix(item, false))
       end
@@ -788,9 +788,9 @@ def above(item, &block)
     #     # => nil
     #
     # @param item [Object]
-    def below(item, &block)
+    def below(item)
       if block_given?
-        @node.each_less(item, false, &block)
+        @node.each_less(item, false) { |n| yield(n) }
       else
         self.class.alloc(@node.prefix(item, false))
       end
@@ -820,9 +820,9 @@ def below(item, &block)
     #     # => nil
     #
     # @param item [Object]
-    def from(item, &block)
+    def from(item)
       if block_given?
-        @node.each_greater(item, true, &block)
+        @node.each_greater(item, true) { |n| yield(n) }
       else
         self.class.alloc(@node.suffix(item, true))
       end
@@ -854,9 +854,9 @@ def from(item, &block)
     #     # => nil
     #
     # @param item [Object]
-    def up_to(item, &block)
+    def up_to(item)
       if block_given?
-        @node.each_less(item, true, &block)
+        @node.each_less(item, true) { |n| yield(n) }
       else
         self.class.alloc(@node.prefix(item, true))
       end
@@ -888,9 +888,9 @@ def up_to(item, &block)
     #
     # @param from [Object]
     # @param to [Object]
-    def between(from, to, &block)
+    def between(from, to)
       if block_given?
-        @node.each_between(from, to, &block)
+        @node.each_between(from, to) { |n| yield(n) }
       else
         self.class.alloc(@node.between(from, to))
       end
@@ -1175,50 +1175,50 @@ def between(from, to)
         end
       end
 
-      def each_less(item, inclusive, &block)
+      def each_less(item, inclusive)
         dir = direction(item)
         if dir > 0 || (inclusive && dir == 0)
-          @left.each(&block)
+          @left.each { |entry| yield(entry) }
           yield @item
-          @right.each_less(item, inclusive, &block)
+          @right.each_less(item, inclusive) { |entry| yield(entry) }
         else
-          @left.each_less(item, inclusive, &block)
+          @left.each_less(item, inclusive) { |entry| yield(entry) }
         end
       end
 
-      def each_greater(item, inclusive, &block)
+      def each_greater(item, inclusive)
         dir = direction(item)
         if dir < 0 || (inclusive && dir == 0)
-          @left.each_greater(item, inclusive, &block)
+          @left.each_greater(item, inclusive) { |entry| yield(entry) }
           yield @item
-          @right.each(&block)
+          @right.each { |entry| yield(entry) }
         else
-          @right.each_greater(item, inclusive, &block)
+          @right.each_greater(item, inclusive) { |entry| yield(entry) }
         end
       end
 
-      def each_between(from, to, &block)
+      def each_between(from, to)
         if direction(from) > 0 # all on the right
-          @right.each_between(from, to, &block)
+          @right.each_between(from, to) { |entry| yield(entry) }
         elsif direction(to) < 0 # all on the left
-          @left.each_between(from, to, &block)
+          @left.each_between(from, to) { |entry| yield(entry) }
         else
-          @left.each_greater(from, true, &block)
+          @left.each_greater(from, true) { |entry| yield(entry) }
           yield @item
-          @right.each_less(to, true, &block)
+          @right.each_less(to, true) { |entry| yield(entry) }
         end
       end
 
-      def each(&block)
-        @left.each(&block)
+      def each
+        @left.each { |entry| yield(entry) }
         yield @item
-        @right.each(&block)
+        @right.each { |entry| yield(entry) }
       end
 
-      def reverse_each(&block)
-        @right.reverse_each(&block)
+      def reverse_each
+        @right.reverse_each { |entry| yield(entry) }
         yield @item
-        @left.reverse_each(&block)
+        @left.reverse_each { |entry| yield(entry) }
       end
 
       def drop(n)
diff --git a/lib/hamster/trie.rb b/lib/hamster/trie.rb
index d5564ef3..9f9be38c 100644
--- a/lib/hamster/trie.rb
+++ b/lib/hamster/trie.rb
@@ -28,25 +28,17 @@ def key?(key)
     end
 
     # Calls <tt>block</tt> once for each entry in the trie, passing the key-value pair as parameters.
-    def each(&block)
-      # TODO: Using block.call here is slower than using yield by 5-10%, but
-      # the latter segfaults on ruby 2.2 and above. Once that is fixed and
-      # broken versions are sufficiently old, we should revert back to yield
-      # with a warning that the broken versions are unsupported.
-      #
-      # For more context:
-      # * https://bugs.ruby-lang.org/issues/11451
-      # * https://github.com/hamstergem/hamster/issues/189
-      @entries.each { |entry| block.call(entry) if entry }
+    def each
+      @entries.each { |entry| yield(entry) if entry }
       @children.each do |child|
-        child.each(&block) if child
+        child.each { |child| yield(child) } if child
       end
       nil
     end
 
-    def reverse_each(&block)
+    def reverse_each
       @children.reverse_each do |child|
-        child.reverse_each(&block) if child
+        child.reverse_each { |child| yield(child) } if child
       end
       @entries.reverse_each { |entry| yield(entry) if entry }
       nil
diff --git a/lib/hamster/vector.rb b/lib/hamster/vector.rb
index 730035f7..581fbe8f 100644
--- a/lib/hamster/vector.rb
+++ b/lib/hamster/vector.rb
@@ -426,9 +426,9 @@ def shift
     #   # => Hamster::Vector["A", "B", "C"]
     #
     # @return [self, Enumerator]
-    def each(&block)
+    def each
       return to_enum unless block_given?
-      traverse_depth_first(@root, @levels, &block)
+      traverse_depth_first(@root, @levels) { |entry| yield(entry) }
       self
     end
 
@@ -443,9 +443,9 @@ def each(&block)
     #   Element: A
     #
     # @return [self]
-    def reverse_each(&block)
+    def reverse_each
       return enum_for(:reverse_each) unless block_given?
-      reverse_traverse_depth_first(@root, @levels, &block)
+      reverse_traverse_depth_first(@root, @levels) { |entry| yield(entry) }
       self
     end
 
@@ -1300,14 +1300,17 @@ def marshal_load(array)
 
     private
 
-    def traverse_depth_first(node, level, &block)
-      return node.each(&block) if level == 0
-      node.each { |child| traverse_depth_first(child, level - 1, &block) }
+    def traverse_depth_first(node, level)
+      return node.each { |n| yield(n) } if level == 0
+      node.each { |child| traverse_depth_first(child, level - 1) { |n| yield(n) } }
     end
 
-    def reverse_traverse_depth_first(node, level, &block)
-      return node.reverse_each(&block) if level == 0
-      node.reverse_each { |child| reverse_traverse_depth_first(child, level - 1, &block) }
+    def reverse_traverse_depth_first(node, level)
+      return node.reverse_each { |n| yield(n) } if level == 0
+
+      node.reverse_each do |child|
+        reverse_traverse_depth_first(child, level - 1) { |n| yield(n) }
+      end
     end
 
     def leaf_node_for(node, bitshift, index)