How to use StringBuilder in functional programming?

Viewed 314

I was recently reading about functional programming. and I most say it comes with great benefits, but I have some performance concerns like when rendering a very big string like say an html page where I concatenate a lot of strings. Normally I would use String builder. but I could not use it while still following functional programming paradigm.

Poor Performance Code:
As you can see ToListItem and ToUl are pure functions

    class Program
    {
        static string ToListItem(string s)
        {
            return "<li>" + s + "</li>";
        }
        static string ToUl(string[] items)
        {
            return "<ul>" + String.Join("", items.Select(x => ToListItem(x))) + "</ul>";
        }

        static void Main(string[] args)
        {
            string[] items = new string[]
            {
               "Apple",
               "Orange",
               "Banana"
            };

            string htmlUl = ToUl(items);
            Console.WriteLine(htmlUl);

        }
    }

Faster Code
But as you can see ToListItem and ToUl are no longer pure functions and I could not come with a solution that make use of StringBuilder in pure functions

    class Program
    {
        static void ToListItem(string s,StringBuilder sb)
        {
            sb.Append("<li>" + s + "</li>");
        }
        static void ToUl(string[] items, StringBuilder sb)
        {
            sb.Append("<ul>");

            foreach (var item in items)
                ToListItem(item, sb);

            sb.Append("</ul>");
        }

        static void Main(string[] args)
        {
            string[] items = new string[]
            {
               "Apple",
               "Orange",
               "Banana"
            };

            StringBuilder sb = new StringBuilder();

            ToUl(items, sb);
            Console.WriteLine(sb.ToString());

        }
    }

So My Question Is:

Is It possible to use StringBuilder the functional programming way? How? and if not what is the alternative performance-wise solution?

Update1 I included some examples. performance here do not matter but as the list grow linearly the Performance gap will grow exponentially.

1 Answers

This does not address the case above exactly, but it provides a baseline on which you could build something for your case, with header and footer parameters.

using System;
using System.Collections.Generic;
using System.Text;

public static class FunctionalStringBuilder
{
    public static string BuildString<T>(this IEnumerable<T> enumerable, Func<T, string> response)
    {
        var builder = new StringBuilder();

        foreach (var item in enumerable)
        {
            builder.Append(response(item));
        }

        return builder.ToString();
    }
}

You can use it like this:

    var list = new List<Employee>
    {
        AutoFaker.Generate<Employee>(),
        AutoFaker.Generate<Employee>(),
        AutoFaker.Generate<Employee>(),
        AutoFaker.Generate<Employee>()
    };
    var result = list.BuildString(
                    e => $"Employee Id: {e.Id}, Name: {e.Name}, DateOfBirth: {e.DateOfBirth}\n");
Related