diff --git a/src/utils/algorithm.hpp b/src/utils/algorithm.hpp
index 1c493e49f..a5063513b 100644
--- a/src/utils/algorithm.hpp
+++ b/src/utils/algorithm.hpp
@@ -11,6 +11,32 @@
 
 namespace utils {
 
+/**
+ * Outputs a collection of items to the given stream, separating them with the
+ * given delimiter.
+ *
+ * @param stream Destination stream.
+ * @param first Starting iterator of collection which items are going to be
+ *  printed.
+ * @param last Ending iterator of the collection.
+ * @param delim Delimiter that is put between items.
+ * @param streamer Function which accepts a TStream and an item and streams the
+ *  item to the stream.
+ */
+template <typename TStream, typename TIterator, typename TStreamer>
+inline void PrintIterable(TStream *stream, TIterator first, TIterator last,
+                          const std::string &delim = ", ",
+                          TStreamer streamer = {}) {
+  if (first != last) {
+    streamer(*stream, *first);
+    ++first;
+  }
+  for (; first != last; ++first) {
+    *stream << delim;
+    streamer(*stream, *first);
+  }
+}
+
 /**
  * Outputs a collection of items to the given stream, separating them with the
  * given delimiter.
@@ -25,14 +51,7 @@ template <typename TStream, typename TIterable, typename TStreamer>
 inline void PrintIterable(TStream &stream, const TIterable &iterable,
                           const std::string &delim = ", ",
                           TStreamer streamer = {}) {
-  bool first = true;
-  for (const auto &item : iterable) {
-    if (first)
-      first = false;
-    else
-      stream << delim;
-    streamer(stream, item);
-  }
+  PrintIterable(&stream, iterable.begin(), iterable.end(), delim, streamer);
 }
 
 /**
diff --git a/tests/unit/utils_algorithm.cpp b/tests/unit/utils_algorithm.cpp
index 39e533113..a21517ead 100644
--- a/tests/unit/utils_algorithm.cpp
+++ b/tests/unit/utils_algorithm.cpp
@@ -1,4 +1,6 @@
 #include <list>
+#include <map>
+#include <sstream>
 #include <string>
 #include <vector>
 
@@ -11,6 +13,40 @@ using vec = std::vector<std::string>;
 using namespace std::string_literals;
 using namespace utils;
 
+TEST(Algorithm, PrintIterable) {
+  // Checkss both variants of the function (using iterators and collections)
+  auto check = [](const std::vector<int> &iterable,
+                  const std::string &expected_output) {
+    {
+      std::ostringstream oss;
+      PrintIterable(oss, iterable, ", ");
+      EXPECT_EQ(oss.str(), expected_output);
+    }
+    {
+      auto streamer = [](auto &stream, const auto &item) { stream << item; };
+      std::ostringstream oss;
+      PrintIterable(&oss, iterable.begin(), iterable.end(), ", ", streamer);
+      EXPECT_EQ(oss.str(), expected_output);
+    }
+  };
+
+  check(std::vector<int>{1, 2, 3, 4}, "1, 2, 3, 4");
+  check(std::vector<int>{1}, "1");
+  check(std::vector<int>{}, "");
+
+  {
+    // Use custom streamer
+    auto map_streamer = [](auto &stream, const auto &item) {
+      stream << item.first << ": " << item.second;
+    };
+    std::ostringstream oss;
+    std::map<std::string, std::string> map;
+    map.emplace("a", "x");
+    map.emplace("b", "y");
+    PrintIterable(&oss, map.begin(), map.end(), ", ", map_streamer);
+    EXPECT_EQ(oss.str(), "a: x, b: y");
+  }
+}
 
 TEST(Algorithm, Reversed) {
   EXPECT_EQ(Reversed(""s), ""s);