среда, 27 октября 2010 г.

Паттерн матчинг и выделение памяти

Есть небольшой и довольно простой код:


let replace = function
    | "by" :: "id" :: t :: [] -> 8
    | _ -> 0
t :: [] - используется для того, чтобы гарантировать наличие одного свободного эл-та в списке.

И вроде бы всё хорошо, но если посмотреть в рефлекторе, то можно увидеть такую картину:

public static int replace(FSharpList<string> _arg1)
{
    if (_arg1.get_TailOrNull() != null)
    {
        FSharpList<string> list = _arg1;
        if (string.Equals(list.get_HeadOrDefault(), "by"
&& (list.get_TailOrNull().get_TailOrNull() != null))
        {
            FSharpList<string> list2 = list.get_TailOrNull();
            if (string.Equals(list2.get_HeadOrDefault(), "id"
&& (list2.get_TailOrNull().get_TailOrNull() != null))
            {
                FSharpList<string> list3 = list2.get_TailOrNull();
                if (list3.get_TailOrNull().get_TailOrNull() == null)
                {
                    string t = list3.get_HeadOrDefault();
                    return 8;
                }
            }
        }
    }
    return 0;
}
Выделенная строка намекает на то, что выделяется память под ту же ссылку(а это лишняя работа).

Но, если использовать _ вместо t, то всё становится несколько радужней:

public static int replace(FSharpList<string> _arg1)
{
    if (_arg1.get_TailOrNull() != null)
    {
        FSharpList<string> list = _arg1;
        if (string.Equals(list.get_HeadOrDefault(), "by"
&& (list.get_TailOrNull().get_TailOrNull() != null))
        {
            FSharpList<string> list2 = list.get_TailOrNull();
            if ((string.Equals(list2.get_HeadOrDefault(), "id"
&& (list2.get_TailOrNull().get_TailOrNull() != null)) 
&& (list2.get_TailOrNull().get_TailOrNull().get_TailOrNull() == null))
            {
                return 8;
            }
        }
    }
    return 0;
}

Как можно заметить код становится значительно проще(пропадает один вложенный иф + не выделяется память под t + не вычисляется list3).

Отсюда нехитрый вывод - следует, по возможности, использовать запись вида h :: _ :: t вместо h :: elem :: t.

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

Отправить комментарий