Как использовать StringBuilder в функциональном программировании?

#c# #functional-programming #stringbuilder

#c# #функциональное программирование #stringbuilder

Вопрос:

Недавно я читал о функциональном программировании. и я больше всего говорю, что это дает большие преимущества, но у меня есть некоторые проблемы с производительностью, например, при рендеринге очень большой строки, например, html-страницы, где я объединяю много строк. Обычно я бы использовал String builder. но я не мог использовать его, все еще следуя парадигме функционального программирования.

Низкая производительность кода:
Как вы можете видеть, ToListItem и ToUl являются чистыми функциями

     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);

        }
    }
  

Более быстрый код
Но, как вы можете видеть, ToListItem и ToUl больше не являются чистыми функциями, и я не смог предложить решение, которое использует StringBuilder в чистых функциях

     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());

        }
    }
  

Итак, мой вопрос:

Возможно ли использовать StringBuilder способом функционального программирования? Как? и если нет, то какое альтернативное решение с точки зрения производительности?

Update1 Я включил несколько примеров. производительность здесь не имеет значения, но по мере линейного роста списка разрыв в производительности будет расти экспоненциально.

Комментарии:

1. Я не уверен, почему вы думаете, StringBuilder что его нельзя использовать в кодировании в стиле функциональной парадигмы? Можете ли вы подробнее рассказать об этом?

2. Пожалуйста, добавьте немного кода, чтобы было легче понять, какая у вас проблема

3. @Fildor потому что, когда я вызываю StringBuilder. Добавить Я изменяю состояние StringBuilder, и когда у меня сложная логика, мне нужно иметь более одной функции, и для использования string builder мне обычно приходится передавать его в качестве параметра.и вызовите Add во внутренней функции, что нарушает правила функционального программирования чистой функции .

4. Итак, вопрос в том, «разрешено ли мне использовать ссылки на объекты в качестве параметров в FP?» Ответ «нет».

5. Мне кажется, что вы столкнулись с концепцией FP и теперь пытаетесь внедрить ее повсюду. Пожалуйста, не делайте этого. Если вы хотите использовать чистый FP, делайте это на языке FP, таком как F #, в противном случае примите, что попытка использовать чистый FP на языке ООП, таком как C #, всегда будет компромиссом.

Ответ №1:

Это не совсем соответствует описанному выше случаю, но обеспечивает базовую основу, на которой вы могли бы создать что-то для своего случая, с параметрами верхнего и нижнего колонтитулов.

 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();
    }
}
  

Вы можете использовать его следующим образом:

     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");
  

Комментарии:

1. Интересное решение.. но это не завершено . что, если дерево очень глубокое. затем в какой-то момент я буду рекурсивно вызывать BuildString и передавать строки по кругу. строки станут длиннее, а производительность упадет. Я искал способ передать String Builder для нескольких функций в отношении FP. но я думаю, что это все-таки невозможно :/

2. @DiaaEddin Хороший момент. Я видел такую возможность. Однако то, что метод может вызываться рекурсивно, не означает, что вы должны это делать.

3. @DiaaEddin Не уверен, что вам доступны эти инструменты, но мне пришло в голову, что вряд ли StringBuilder является правильным решением для вашего случая. Если вы можете, создайте тип, который можно сериализовать для разметки в виде дерева.