Информация об изменениях

Сообщение Re[21]: Есть ли подобие LINQ на других языках/платформах? от 19.04.2021 15:10

Изменено 19.04.2021 15:30 Serginio1

Re[21]: Есть ли подобие LINQ на других языках/платформах?
Здравствуйте, Ikemefula, Вы писали:

I>Здравствуйте, Serginio1, Вы писали:


I>>>И что? Сколько стоит использование IEnumerable ?

S>> То же что и yield, а именно MoveNext и Current

I>Именно.


S>> Я подправил потому, что изначальный смыл в том, что вычисления идут с права налево и нет лишних циклов если бы вычисляли слева направо c созданием новых коллекций


I>Ты путаешь linq и ленивую обработку коллекций. Linq это про соответствующие расширения, которые можно навесить на любой интерфейс, а не только IEnumerable. Более того — совсем необязательно это будет коллекция.

I>RX, XML, WMI, IQueryable и тд и тд и тд.

I>Т.е. yield это частный случай для IEnumerable. То есть, частный случай частного случая


Да но именно yield и создает IEnumerable ленивым. Посмотрим https://github.com/dotnet/runtime/blob/main/src/libraries/System.Linq/src/System/Linq/Where.cs
Или
https://referencesource.microsoft.com/#system.core/system/linq/Enumerable.cs

private static IEnumerable<TSource> WhereIterator<TSource>(IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
        {
            int index = -1;
            foreach (TSource element in source)
            {
                checked
                {
                    index++;
                }

                if (predicate(element, index))
                {
                    yield return element;
                }
            }
        }

S>> Где ты нашел про то, что yield ничего не стоит?

I>Ты так пишешь.


I>>>Не к энумератору, а к значению. Вместо x[i] у тебя будет обращение к moveNext, switch присваивание Current, чтение Current.

S>> Ну я тебе подам на вход IEnumerable не основанном на List или array, как ты с ним будешь работать.
S>>Это же Linq!!!

I>Не подашь. У меня параметры это массивы в явном виде шоб люди навроде тебя не подпихивали хрень и не заявляли "Ваша обработка коллекций тормозит после того, как я сто фильтров объединил"

То есть вычисления слева направо. И если мне нужно вернуть из метода Ienumrable и к нему применить свои действия и вернуть другой енумератор это все будут новые списки.
И вот в конце наконец вызвать FirstOrDefault вот она вся прелесть вычислений справо на лево в отличие от твой позиции с вычислением слева направо

S>> главное, что yield обеспечивает вычисление справа на лево!!!


I>yield это просто последовательность, а не "слева направо". А вот как будут реальные элементы данных выбираться — как угодно.

Нет именно слева направо. Потому что мы вызываем MoveNext у последнего элемента в цепочке, а он уже зовет у своего родителя.
S>>то тебе не нужно перебирать всю коллекцию (возможно и не один раз) и вызвать все лямбды, new в цепочке расширений если вычисления идут слева направо.


На этом основан Linq. И часто новички пишут вместо yield
 var result= new List<TSource>();
            foreach (TSource element in source)
            {
     
                if (predicate(element, index))
                {
                   // yield return element;
                 result.Add(element);
                }
            }

return result;

При этом тратя лишнюю память и вычислений predicate если уже в вычислениях отпала необходимость.
I>Это тот самый частный случай.
Это один из массовых случаев Where
Ну и можно посмотреть тот же Select

private static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
        {
            int index = -1;
            foreach (TSource element in source)
            {
                checked
                {
                    index++;
                }

                yield return selector(element, index);
            }
        }


На yield построен Linq
Непонятно?
Re[21]: Есть ли подобие LINQ на других языках/платформах?
Здравствуйте, Ikemefula, Вы писали:

I>Здравствуйте, Serginio1, Вы писали:


I>>>И что? Сколько стоит использование IEnumerable ?

S>> То же что и yield, а именно MoveNext и Current

I>Именно.


S>> Я подправил потому, что изначальный смыл в том, что вычисления идут с права налево и нет лишних циклов если бы вычисляли слева направо c созданием новых коллекций


I>Ты путаешь linq и ленивую обработку коллекций. Linq это про соответствующие расширения, которые можно навесить на любой интерфейс, а не только IEnumerable. Более того — совсем необязательно это будет коллекция.

I>RX, XML, WMI, IQueryable и тд и тд и тд.

I>Т.е. yield это частный случай для IEnumerable. То есть, частный случай частного случая


Да но именно yield и создает IEnumerable ленивым. Посмотрим https://github.com/dotnet/runtime/blob/main/src/libraries/System.Linq/src/System/Linq/Where.cs
Или
https://referencesource.microsoft.com/#system.core/system/linq/Enumerable.cs

private static IEnumerable<TSource> WhereIterator<TSource>(IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
        {
            int index = -1;
            foreach (TSource element in source)
            {
                checked
                {
                    index++;
                }

                if (predicate(element, index))
                {
                    yield return element;
                }
            }
        }

S>> Где ты нашел про то, что yield ничего не стоит?

I>Ты так пишешь.


I>>>Не к энумератору, а к значению. Вместо x[i] у тебя будет обращение к moveNext, switch присваивание Current, чтение Current.

S>> Ну я тебе подам на вход IEnumerable не основанном на List или array, как ты с ним будешь работать.
S>>Это же Linq!!!

I>Не подашь. У меня параметры это массивы в явном виде шоб люди навроде тебя не подпихивали хрень и не заявляли "Ваша обработка коллекций тормозит после того, как я сто фильтров объединил"

То есть вычисления слева направо. И если мне нужно вернуть из метода Ienumrable и к нему применить свои действия и вернуть другой енумератор это все будут новые списки.
И вот в конце наконец вызвать FirstOrDefault вот она вся прелесть вычислений справо на лево в отличие от твой позиции с вычислением слева направо

S>> главное, что yield обеспечивает вычисление справа на лево!!!


I>yield это просто последовательность, а не "слева направо". А вот как будут реальные элементы данных выбираться — как угодно.

Нет именно слева направо. Потому что мы вызываем MoveNext у последнего элемента в цепочке, а он уже зовет у своего родителя.
S>>то тебе не нужно перебирать всю коллекцию (возможно и не один раз) и вызвать все лямбды, new в цепочке расширений если вычисления идут слева направо.


На этом основан Linq. И часто новички пишут вместо yield
 var result= new List<TSource>();
            foreach (TSource element in source)
            {
     
                if (predicate(element, index))
                {
                   // yield return element;
                 result.Add(element);
                }
            }

return result;

При этом тратя лишнюю память и вычислений predicate если уже в вычислениях отпала необходимость.
I>Это тот самый частный случай.
Это один из массовых случаев Where
Ну и можно посмотреть тот же Select

private static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
        {
            int index = -1;
            foreach (TSource element in source)
            {
                checked
                {
                    index++;
                }

                yield return selector(element, index);
            }
        }


Да для первоначальных коллекций там оптимизировано в том, реализован MoveNext по аналогии с тем, что трансформиует yield
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate");
            if (source is Iterator<TSource>) return ((Iterator<TSource>)source).Where(predicate);
            if (source is TSource[]) return new WhereArrayIterator<TSource>((TSource[])source, predicate);
            if (source is List<TSource>) return new WhereListIterator<TSource>((List<TSource>)source, predicate);
            return new WhereEnumerableIterator<TSource>(source, predicate);
        }


public override bool MoveNext() {
                switch (state) {
                    case 1:
                        enumerator = source.GetEnumerator();
                        state = 2;
                        goto case 2;
                    case 2:
                        while (enumerator.MoveNext()) {
                            TSource item = enumerator.Current;
                            if (predicate(item)) {
                                current = item;
                                return true;
                            }
                        }
                        Dispose();
                        break;
                }
                return false;
            }


На yield построен Linq
Непонятно?