Re[4]: [Linq] проверить последовательность
От: SpaceConscience  
Дата: 31.07.10 20:28
Оценка: +2 -1 :))
П>Это просто другой "мирок", никто Вам не навязывает подобные техники и подходы. Ну не нравится — ну не пользуйтесь, проблем то

Это другой мирок. Это другой, новый, прекрасный мирок. В нем живут более разумные, более совершенные, "другие" люди.

Не пытайтесь их понять, возможно, вам этого просто не дано. Они "другие". Они просто "другие".

Я уже послал Андерсу Хейлсбергу письмо c предложением включить в C# два кейворда для разделения императивного и декларативного кода:


// Кейворд aliens помечает декларативный код для "других" людей.
aliens
{
    var isAscending = xs.Replay(ys => ys.Zip(ys.Skip(1), (x, y) => x <= y), 1).All(x => x);
}

// Кейворд bydlokod помечает императивный код.
bydlokod
{
    bool isAscending = true;

    for (int i = 1; i < numbers.Length; i++)
    {
        if (numbers[i - 1] > numbers[i])
        {
            isAscending = false;
            break;
        }
    }
}


Так сразу будет видно, чей код где.

Правда, какой режим будет по умолчанию, я еще не придумал, наверно, все-таки bydlokod. Варваров всегда большинство, и они темной массой окружают цивилизованное государство, угрожая его истребить.
Собрался ставить минус? Да сам иди в жопу!

































































.
Re[9]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 09:18
Оценка: -3 :))
Здравствуйте, gandjustas, Вы писали:

JR>>Рекурсия — гадость сама по себе, тем более, что без неё практически всегда можно обойтись.

G>Расскажи это программистам на haskell\ocaml\lisp\f#

Вот потому что рекурсия гадость сама по себе ни один из этих языков не является мэйнстримовским. Выигрыш такие языки могут дать только в тех областях где по условию большинства решаемых задач без рекурсии обойтись невозможно, но таких областей очень мало.
Re[13]: [Linq] проверить последовательность
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 09.08.10 08:53
Оценка: +5
Здравствуйте, Undying, Вы писали:

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


U>>>А здесь нам просто повезло, что в языке есть стандартная функция разбиения на пары, которую достаточно для решения данной задачи. Если бы задача была бы немного другая, там бы стандартной функции не было.


K>>В большинстве языков можно объявить функцию (метод, процедуру) самому. Представляете?


U>И? Это типа очень хорошо, когда для решения тривиальных задач нужно писать специальные функции?


Это лучше чем писать циклы.

Комбинатор типа pairwise обладает в разы большим потенциалом повторного использования, чем написанный цикл.
Re[3]: [Linq] проверить последовательность
От: Пельмешко Россия blog
Дата: 31.07.10 11:10
Оценка: 8 (3) :)
Здравствуйте, 0K, Вы писали:

0K>Здравствуйте, Пельмешко, Вы писали:


П>>Неэффективно, но декларативненько:

П>>
П>>var isAscending = xs.OrderBy(x => x).SequenceEqual(xs);
П>>


0K>Прошу прощения. А не проще ли и не понятее ли написать простенкий цикл с временной переменной? Или, профессиональный программист обязательно должен втулить это уродство куда ни попади, дабы все знали что он слышал про Linq и умеет им пользоваться?


Я далеко не "профессиональный программист", но попытаюсь Вам ответить. Дело в том, что если прочитать первый пост данной темы, то можно понять, что топикстартер хотел получить решение на базе Linq и я думаю Вас не должны сильно волновать причины потребности именно Linq-решения. Если Вас раздражает наличие в языке и BCL подобных штук, то думаю это с удовольствием обсудят на холиварных форумах.

Насчёт "уродства" — императивные циклы с мутабельными переменными и break-переходом куда красивше, дааа

П>>На Rx мона чуть короче:

П>>
П>>var isAscending = xs.Replay(ys => ys.Zip(ys.Skip(1), (x, y) => x <= y), 1).All(x => x);
П>>


0K>Что такое Rx? Это какая-то библиотека, или подход к написанию этих ваших Linq?


Ну а почему бы не погуглить?
Это библиотека для работы с реактивными последовательностями (a.k.a. observer pattern), а так же некоторые дополнительные комбинаторы для работы с обычными интерактивными IEnumerable-последовательностями, которых иногда очень не хватает. Очень советую посмотреть, много интересного там

0K>Вам это правда понятее простого цикла с одной единственной временной переменной?


Это просто другой подход для решения поставленной задачи, декларативный. Не нужны никакие циклы и переменные, надо лишь собрать нужный Вам алгоритм из комбинируемых кусочков, представленных в Rx. Да, это не очень понятно выглядит на первый взгляд, но это можно даже прочитать:

Помня одно предыдущее значение, соедини последовательность с самой собой, смещённой с на один элемент вперёд, и проверь, что во всех парах левое значение меньше или равно правому.


Это просто другой "мирок", никто Вам не навязывает подобные техники и подходы. Ну не нравится — ну не пользуйтесь, проблем то
Re[2]: [Linq] проверить последовательность
От: 0K Ниоткуда  
Дата: 31.07.10 10:07
Оценка: +1 -3
Здравствуйте, Пельмешко, Вы писали:

П>Неэффективно, но декларативненько:

П>
П>var isAscending = xs.OrderBy(x => x).SequenceEqual(xs);
П>


Прошу прощения. А не проще ли и не понятее ли написать простенкий цикл с временной переменной? Или, профессиональный программист обязательно должен втулить это уродство куда ни попади, дабы все знали что он слышал про Linq и умеет им пользоваться?

П>На Rx мона чуть короче:

П>
П>var isAscending = xs.Replay(ys => ys.Zip(ys.Skip(1), (x, y) => x <= y), 1).All(x => x);
П>


Что такое Rx? Это какая-то библиотека, или подход к написанию этих ваших Linq?

Вам это правда понятее простого цикла с одной единственной временной переменной?
Re[11]: [Linq] проверить последовательность
От: Klapaucius  
Дата: 09.08.10 07:14
Оценка: +2 -1 :)
Здравствуйте, Undying, Вы писали:

U>А здесь нам просто повезло, что в языке есть стандартная функция разбиения на пары, которую достаточно для решения данной задачи. Если бы задача была бы немного другая, там бы стандартной функции не было.


В большинстве языков можно объявить функцию (метод, процедуру) самому. Представляете?
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re: [Linq] проверить последовательность
От: desco США http://v2matveev.blogspot.com
Дата: 30.07.10 18:48
Оценка: 18 (3)
Здравствуйте, Dog, Вы писали:

Dog>Есть последовательность чисел {1, 3, 5, 7, 9}

Dog>Надо проверить что числа следуют по возрастанию
Dog>Можно сделать при помощи linq?

c Rx можно?

        public static IEnumerable<int> Enumerate()
        {
            ...
        }

        public static void Main(string[] args)
        {
            var ascending = Enumerate()
                .Memoize(1)
                .Let(e => e.Zip(e.Skip(1), (a, b) => a < b))
                .All(x => x);
        }
Re: [Linq] проверить последовательность
От: Klapaucius  
Дата: 02.08.10 12:27
Оценка: 8 (2) +1
Здравствуйте, Dog, Вы писали:

Dog>Есть последовательность чисел {1, 3, 5, 7, 9}

Dog>Надо проверить что числа следуют по возрастанию
Dog>Можно сделать при помощи linq?

Это исключительно и только вопрос полноты библиотеки для работы с коллекциями.
При использовании этой библиотеки, например, решение будет выглядеть так:
var isAscending = new[]{1, 3, 5, 7, 9}.Reduce((a, b) => a <= b).And();
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[3]: [Linq] проверить последовательность
От: desco США http://v2matveev.blogspot.com
Дата: 31.07.10 12:50
Оценка: 2 (1) +2
Здравствуйте, IB, Вы писали:

IB>Здравствуйте, Пельмешко, Вы писали:


П>>
П>>var isAscending = xs.Replay(ys => ys.Zip(ys.Skip(1), (x, y) => x <= y), 1).All(x => x);
П>>


IB>Можно проще и без Rx. =) К счастью в 4FW метод Zip — часть LINQ.


IB>
IB>var isAscending = sequence.Zip(sequence.Skip(1), (x, y) => x <= y).All(x => x);
IB>



в вашем случае исходная последовательность будет перебираться дважды

            var sequence = new[] { 1, 2, 3, 4, 5, 6 }.Do(Console.Write);
            var isAscending = sequence
                .Zip(sequence.Skip(1), (x, y) => x <= y)
                .All(x => x); // 112233445566


для того, чтобы этого избежать нужно запоминать последний элемент (Memoize(1))

            var sequence = new[] { 1, 2, 3, 4, 5, 6 }.Do(Console.Write).Memoize(1);
            var isAscending = sequence
                .Zip(sequence.Skip(1), (x, y) => x <= y)
                .All(x => x); //123456



IB>А вот с Rx можно попробовать сделать так, чтобы перебор останавливался как только случится первое неудовлетворение предикату...

а это обеспечивает стандартный All

            var sequence = new[] { 1, 2, 3, 2, 4, 5, 6 }.Do(Console.Write).Memoize(1);
            var isAscending = sequence
                .Zip(sequence.Skip(1), (x, y) => x <= y)
                .All(x => x); //1232
Re[2]: [Linq] проверить последовательность
От: Jolly Roger  
Дата: 31.07.10 11:42
Оценка: 1 (1) +1 :)
Здравствуйте, Пельмешко, Вы писали:

П>
П>var isAscending = xs.OrderBy(x => x).SequenceEqual(xs);
П>

П>На Rx мона чуть короче:
П>
П>var isAscending = xs.Replay(ys => ys.Zip(ys.Skip(1), (x, y) => x <= y), 1).All(x => x);
П>


У Вас оператор "короче" перегружен?

П>

"Нормальные герои всегда идут в обход!"
Re: [Linq] проверить последовательность
От: Пельмешко Россия blog
Дата: 30.07.10 23:44
Оценка: -1 :))
Здравствуйте, Dog, Вы писали:

Dog>Есть последовательность чисел {1, 3, 5, 7, 9}

Dog>Надо проверить что числа следуют по возрастанию
Dog>Можно сделать при помощи linq?

Неэффективно, но декларативненько:
var isAscending = xs.OrderBy(x => x).SequenceEqual(xs);

На Rx мона чуть короче:
var isAscending = xs.Replay(ys => ys.Zip(ys.Skip(1), (x, y) => x <= y), 1).All(x => x);


Re[7]: [Linq] проверить последовательность
От: Jolly Roger  
Дата: 07.08.10 08:25
Оценка: +1 -2
Здравствуйте, SpaceConscience, Вы писали:

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


Рекурсия — гадость сама по себе, тем более, что без неё практически всегда можно обойтись.
"Нормальные герои всегда идут в обход!"
Re[9]: [Linq] проверить последовательность
От: Аноним  
Дата: 07.08.10 10:14
Оценка: +3
Здравствуйте, gandjustas, Вы писали:

JR>>Рекурсия — гадость сама по себе, тем более, что без неё практически всегда можно обойтись.


G>Расскажи это программистам на haskell\ocaml\lisp\f#


Явная рекурсия — гадость. Она — как 'goto' функционального программирования. Практичеси всегда ее можно заменить на комбинацию более высокоуровневых конструкций (map/fold/unfold и т.д.). За более детальным объяснением с доказательствами и примерами можно обратиться к классическому труду почитаемого тут Эрика Мейера Functional Programming with Bananas, Lenses, Envelopes, and Barbed Wire
Re[13]: [Linq] проверить последовательность
От: Пельмешко Россия blog
Дата: 07.08.10 13:26
Оценка: 2 (1) +1
Здравствуйте, Undying, Вы писали:

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


FR>>Конкретно строку a::b::_ when a > b можно прочитать примерно так "список должен содержать два идущих друг за другом элемента a и b

FR>>(и неважный нам хвост _) таких что a > b" если это условие выполняется то элементам a и b сопоставятся реальные значения из списка
FR>>и выполнится то что идет после "->" то есть вернется false.

U>Тогда этот шаг более-менее понятен, а вот в этом шаге:

U>
U>| h::t                  -> f t
U>


U>как компилятор догадывается, что у списка надо отсечь первый элемент?


:: — один из типов шаблонов, поддерживаемых OCaml, просто встроенная в компилятор поддержка.
Тут компилятор ничего не "отсекает", он просто проверяет совпадение списка с образцом h::t и в случае успеха (если список не пуст) предоставляет Вам имена h и t для доступа к совпавшим частям (голове и хвосту) списка.

U>Если бы надо было отсечь два первых элемента, то как бы эта строчка выглядела?

| h1::h2::tl -> f tl
Re[4]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 02.08.10 10:52
Оценка: 1 (1) :)
Здравствуйте, Пельмешко, Вы писали:

П>Это просто другой подход для решения поставленной задачи, декларативный. Не нужны никакие циклы и переменные, надо лишь собрать нужный Вам алгоритм из комбинируемых кусочков, представленных в Rx. Да, это не очень понятно выглядит на первый взгляд, но это можно даже прочитать:


А зачем себя ограничивать? Не проще ли императивные задачи записывать императивно, а функциональные функционально? Приведенная задача требует хранения промежуточного значения, т.е. является императивной, соответственно ее функциональное решение весьма уродливо. Так в чем смысл тащить это уродство в код?
Re[8]: [Linq] проверить последовательность
От: _FRED_ Черногория
Дата: 07.08.10 09:28
Оценка: -1 :)
Здравствуйте, Jolly Roger, Вы писали:

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


JR>Рекурсия — гадость сама по себе, тем более, что без неё практически всегда можно обойтись.


С чего бы это? Рекурсия — это большущая красота, которая позволяет делать очень изящные штучки.
Help will always be given at Hogwarts to those who ask for it.
Re[9]: Самое важное забыл
От: Undying Россия  
Дата: 07.08.10 09:42
Оценка: -1 :)
Здравствуйте, Undying, Вы писали:

FR>>С этим вариантом вариант с рекурсией одинаков по понятности. Но это для языков без паттерн матчинга, на том же


U>В принципе понятность алгоритма понятие вполне объективное, более понятным является тот алгоритм, который лучше удовлетворяет бритве Оккама, т.е. в котором вводится меньше дополнительных сущностей и производится меньше их изменений.


U>В императивном алгоритме дополнительных сущностей вводится две: это предыдущий и текущий элементы (или их индексы). В рекурсивном алгоритме дополнительных сущностей три: во-первых, усеченная коллекция, во-вторых, индексы предыдущего и текущего элемента. Т.е. избавиться от предыдущего и текущего элемента все равно не получилось, но зато пришлось ввести еще лишнюю сущность — усеченную коллекцию, соответственно алгоритм стал сложнее.


В императивном алгоритме в конкретный момент работы алгоритма дополнительные сущности существуют в одном и только в одном экземпляре, в рекурсивном алгоритме в этот же момент имеется множество экземпляров (равное глубине рекурсии) дополнительных сущностей. Удерживать в голове один экземпляр намного проще, чем множество, поэтому нерекурсивные алгоритмы понимаются намного проще рекурсивных.
Re[10]: [Linq] проверить последовательность
От: k.o. Россия  
Дата: 07.08.10 09:52
Оценка: +2
Здравствуйте, Undying, Вы писали:

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


_FR>>С чего бы это? Рекурсия — это большущая красота, которая позволяет делать очень изящные штучки.


U>Рекурсия это именно что гадость сама по себе. Т.к. в нерекурсивном алгоритме в конкретный момент работы алгоритма имеется только одно состояние, а в рекурсивном алгоритме в этот же момент висит гирлянда состояний, которую удержать в голове намного сложнее.


А зачем держать в голове весь "стек" вызовов рекурсивного алгоритма? Чисто-функциональный алгоритм зависит только от входных параметров, а был-ли он вызван рекурсивно или нет, совершенно неважно.
Re[3]: [Linq] проверить последовательность
От: ankf  
Дата: 07.08.10 10:11
Оценка: +2
Здравствуйте, Undying, Вы писали:

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


A>>В Linq для целей задачи топиккастера есть функция Any и проблема решается достаточно просто


A>>
A>>            int p = arr[0];
A>>            if (arr.Any(x => p > (p = x) ))
A>>                Console.WriteLine("Не упорядочена");
A>>


U>Ты чего? Тут же используется богопротивное изменяемое состояние. Тебя щас анафеме предадут, за такое надругательство над линком.


лучше богопротивное изменямое состояние, чем сортировка или агрегация.
да и ничего богопротивного тут нет, бог создал Linq таким , что он позволяет использовать внешнюю переменную, потому что бог не фанат и идеолог, а практик.
Я программист, я Иван Помидоров, хватить трепатся — наш козырь error.
Re[13]: [Linq] проверить последовательность
От: Klapaucius  
Дата: 09.08.10 09:11
Оценка: +2
Здравствуйте, Undying, Вы писали:

U>Это типа очень хорошо, когда для решения тривиальных задач нужно писать специальные функции?


Во-первых, функции и существуют для решения тривиальных задач. И, собственно, являются инструментом для декомпозиции нетривиальных задач на эти самые тривиальные.
Во-вторых, в этом случае, как и в большинстве остальных случаев, нужно написать не специальную функцию, а универсальную, если только она уже не была написана раньше. Количество этих универсальных функций будет сначала расти, если стандартная библиотека некудышная, ну а потом рост замедлится и ими можно будет просто пользоваться, а не изобретать велосипед в каждом цикле. То, что стандартная библиотека бедна — это плохо. То, что язык предоставляет средства для исправления этой проблемы — разумеется, хорошо.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[6]: [Linq] проверить последовательность
От: SpaceConscience  
Дата: 06.08.10 21:21
Оценка: 24 (1)
П>Например, свёртка — фундаментальная операция над списками и ещё много чем — требует как раз промежуточного значения под аккумулятор

Позвольте скромное замечание, коллега. Удивительно от апологетов мирка слышать такие некомпетентные заявление об устройстве этого же мирка. Никакого "промежуточного состояния" (фюю, гадость императивная) свертка не требует, она прекрасно выражается рекурсивной функцией.
Собрался ставить минус? Да сам иди в жопу!

































































.
Re[11]: [Linq] проверить последовательность
От: FR  
Дата: 07.08.10 11:19
Оценка: 2 (1)
Здравствуйте, Undying, Вы писали:


U>Если честно, то глядел-глядел, но логику уловить вообще не сумел, т.е. отдельные элементы вроде понятны, но почему они работают как единое целое непонятно совершенно. Как, например, компилятор догадался, что такое a и b?


Боюсь я не сумею в двух словах объяснить что такое паттерн матчинг, это надо самому грокать
Компилятор не догадывается он сверху вниз пытается сопоставить образцы которые ему дали и если получилось присвоить переменным
образца (тем самым a и b то есть это и одновременно объявление переменных) реальные значения.
Конкретно строку a::b::_ when a > b можно прочитать примерно так "список должен содержать два идущих друг за другом элемента a и b
(и неважный нам хвост _) таких что a > b" если это условие выполняется то элементам a и b сопоставятся реальные значения из списка
и выполнится то что идет после "->" то есть вернется false.
Re[17]: [Linq] проверить последовательность
От: FR  
Дата: 07.08.10 17:43
Оценка: 2 (1)
Здравствуйте, Undying, Вы писали:

U>Так match позволяет одновременно работать с несколькими списками или нет? Т.е. можно ли написать так: match xs1, xs2 with... ?


Да без проблем:

let rec iter2 f l1 l2 =
  match (l1, l2) with
    ([], []) -> ()
  | (a1::l1, a2::l2) -> f a1 a2; iter2 f l1 l2
  | (_, _) -> invalid_arg "List.iter2"
Re[10]: [Linq] проверить последовательность
От: k.o. Россия  
Дата: 07.08.10 10:03
Оценка: 1 (1)
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, k.o., Вы писали:


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


U>Каким образом можно обойти дерево произвольной глубины без рекурсии?


Я даже не знаю как отвечать на такие вопросы, взять на себя работу компилятора/интерпритатора и самому управлять стеком состояний?


class Tree
{
    public Tree Left;
    public Tree Right;
}

int RecursiveNodeCount(Tree root)
{
    if (root == null)
    {
        return 0;
    }

    return RecursiveNodeCount(root.Left) + RecursiveNodeCount(root.Right);
}

int NodeCount(Tree tree)
{
    var unvisitedNodes = new Stack<Tree>();
    unvisitedNodes.Push(root);

    var count = 0;
    while (!unvisitedNodes.IsEmpty)
    {
        var node = unvisitedNodes.Pop();
        while (node != null)
        {
            ++count;
            node = node.Left;
            unvisitedNodes.Push(node.Right);
        }
    }

    return count;
}


Как-то так, компилировать не пробовал и с нерекурсивным алгоритмом мог немного налажать, он, как ни странно, оказался сложнее рекурсивного.
Re[8]: [Linq] проверить последовательность
От: FR  
Дата: 07.08.10 10:59
Оценка: 1 (1)
Здравствуйте, Undying, Вы писали:

U>Рекурсия точно также требует промежуточных состояний, только делает это менее явным и более сложным образом (к примеру, в данной задаче вместо одного индекса приходится модифицировать и хранить аж коллекцию). Поэтому использовать рекурсию нужно только там где без этого никак не обойтись (например, при обходе деревьев), во всех остальных случаях рекурсия это резкое усложнение кода.


Тут не модифицируется и не копируется колекция, как уже писал используется срез который в машинном коде сводится к манипуляции указателями, и так как рекурсия хвостовая то она в том же машинном коде приводится к циклу:

pure auto f(int Arr[])
{
    if(Arr.length < 2)
        return true;
    
    if(Arr[0] > Arr[1])
        return false;
    
    return f(Arr[1 .. $]);
}


pure auto f(int Arr[])
{
00402010  sub         esp,20h 
00402013  mov         ecx,dword ptr [esp+28h] 
    if(Arr.length < 2)
00402017  push        ebx  
00402018  push        esi  
00402019  mov         esi,dword ptr [esp+2Ch] 
0040201D  cmp         esi,2 
00402020  push        edi  
00402021  jae         main@f+21h (402031h) 
        return true;
00402023  pop         edi  
00402024  mov         eax,1 
00402029  pop         esi  
0040202A  pop         ebx  
0040202B  add         esp,20h 
0040202E  ret         8    
    
    if(Arr[0] > Arr[1])
00402031  mov         edx,ecx 
00402033  mov         ebx,dword ptr [edx] 
00402035  mov         eax,esi 
00402037  cmp         ebx,dword ptr [edx+4] 
0040203A  jle         main@f+37h (402047h) 
        return false;
0040203C  pop         edi  
0040203D  xor         eax,eax 
0040203F  pop         esi  
00402040  pop         ebx  
00402041  add         esp,20h 
00402044  ret         8    
    
    return f(Arr[1 .. $]);
00402047  lea         edi,[esi-1] 
0040204A  add         edx,4 
0040204D  mov         ecx,edx 
0040204F  mov         dword ptr [esp+0Ch],edi 
00402053  mov         esi,edi 
00402055  mov         dword ptr [esp+10h],edx 
00402059  cmp         dword ptr [esp+0Ch],2 
0040205E  jb          main@f+13h (402023h) 
00402060  jmp         main@f+21h (402031h)
Re: [Linq] проверить последовательность
От: kkolyan  
Дата: 31.07.10 08:16
Оценка: :)
Здравствуйте, Dog, Вы писали:

Dog>Есть последовательность чисел {1, 3, 5, 7, 9}

Dog>Надо проверить что числа следуют по возрастанию
Dog>Можно сделать при помощи linq?

  static void Main(string[] args)
        {
            var a = new[] { 1, 2, 3, 4, 5 };
            int last = 0;
            var asc = a.Select(x => { if (x >= last) { last = x; return true; } else return false; }).All(x=>x);
            Console.WriteLine(asc);
            

        }
Re: [Linq] проверить последовательность
От: SpaceConscience  
Дата: 01.08.10 00:05
Оценка: +1
Dog>Есть последовательность чисел {1, 3, 5, 7, 9}
Dog>Надо проверить что числа следуют по возрастанию
Dog>Можно сделать при помощи linq?

int[] a = { 1, 2, 3, 4, 5 };

bool isAscending = !a.Skip(1).Where((x, i) => x < a[i]).Any();

bool isAscending = a.Zip(a.Skip(1), (x, y) => x <= y).All(x => x);
Собрался ставить минус? Да сам иди в жопу!

































































.
Re[5]: [Linq] проверить последовательность
От: Пельмешко Россия blog
Дата: 02.08.10 12:34
Оценка: +1
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, Пельмешко, Вы писали:


П>>Это просто другой подход для решения поставленной задачи, декларативный. Не нужны никакие циклы и переменные, надо лишь собрать нужный Вам алгоритм из комбинируемых кусочков, представленных в Rx. Да, это не очень понятно выглядит на первый взгляд, но это можно даже прочитать:


U>А зачем себя ограничивать? Не проще ли императивные задачи записывать императивно, а функциональные функционально?


Божемой, да прочитайте уже первый пост аккуратно по символам, попросили решение на LINQ!

U>Приведенная задача требует хранения промежуточного значения, т.е. является императивной, соответственно ее функциональное решение весьма уродливо.


OMG, а в функциональном программировании "промежуточных" значений не должно быть что ли?
Например, свёртка — фундаментальная операция над списками и ещё много чем — требует как раз промежуточного значения под аккумулятор
Мне кажется, или Вы полный бред сказали? Свёртка что ли уродлива???

U>Так в чем смысл тащить это уродство в код?


Да никакого смысла, просто дали топикстартеру что он хотел
Re[9]: [Linq] проверить последовательность
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.08.10 10:14
Оценка: +1
Здравствуйте, Undying, Вы писали:

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


FR>>С этим вариантом вариант с рекурсией одинаков по понятности. Но это для языков без паттерн матчинга, на том же


U>В принципе понятность алгоритма понятие вполне объективное, более понятным является тот алгоритм, который лучше удовлетворяет бритве Оккама, т.е. в котором вводится меньше дополнительных сущностей и производится меньше их изменений.


U>В императивном алгоритме дополнительных сущностей вводится две: это предыдущий и текущий элементы (или их индексы). В рекурсивном алгоритме дополнительных сущностей три: во-первых, усеченная коллекция, во-вторых, индексы предыдущего и текущего элемента. Т.е. избавиться от предыдущего и текущего элемента все равно не получилось, но зато пришлось ввести еще лишнюю сущность — усеченную коллекцию, соответственно алгоритм стал сложнее.


Естественно, массив — не рекурсивный тип данных, на нем рекурсивные алгоритмы плохо выглядят. На рекурсивных типах рекурсивные алгоритмы оказываются на порядок проще.
Re[4]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 10:31
Оценка: +1
Здравствуйте, ankf, Вы писали:

A>лучше богопротивное изменямое состояние, чем сортировка или агрегация.

A>да и ничего богопротивного тут нет, бог создал Linq таким , что он позволяет использовать внешнюю переменную, потому что бог не фанат и идеолог, а практик.

Согласен.

Касательно же приведенного алгоритма, если добавить обработку ситуации с пустой коллекцией, то чтобы сохранить лаконичность придется шаманить:

            int p = int.MinValue;
            if (arr.Any(x => p > (p = x) ))
                Console.WriteLine("Не упорядочена");


Здесь это вроде прокатывает, но на более сложных задач это чревато ошибками, соответственно превосходство над старым-добрым foreach'ем теряется.
Re[7]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 10:39
Оценка: +1
Здравствуйте, FR, Вы писали:

FR>Этот не работает

FR>Так как удаляет последний элемент.

Я так и понял. Вот этим и чревата работа с индексами, что легко ошибиться по невнимательности.

FR>Новый массив не создается, в D массивы ссылочные, создается срез который дает доступ только к нужным элементам.


С точки зрения понятности алгоритма это не важно, это важно только с точки зрения скорости и потребляемой памяти.
Re[10]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 10:59
Оценка: :)
Здравствуйте, FR, Вы писали:

FR>На OCaml рекурсивный вариант будет такой:


FR>
FR>let rec f = function 
FR>  | a::b::_  when a > b   -> false
FR>  | h::t                  -> f t
FR>  | _                     -> true
FR>


Если честно, то глядел-глядел, но логику уловить вообще не сумел, т.е. отдельные элементы вроде понятны, но почему они работают как единое целое непонятно совершенно. Как, например, компилятор догадался, что такое a и b?

FR>
FR>let f l = pairwise l |> for_all (fun (a, b) -> a <= b) 
FR>


FR>Вообще деларативное описание чего хотим.


А здесь нам просто повезло, что в языке есть стандартная функция разбиения на пары, которую достаточно для решения данной задачи. Если бы задача была бы немного другая, там бы стандартной функции не было.
Re[11]: [Linq] проверить последовательность
От: FR  
Дата: 07.08.10 11:05
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

А>>Явная рекурсия — гадость. Она — как 'goto' функционального программирования.

G>Громкие слова, а толку ноль.

В общем-то по сути правильно, если возможно лучше использовать комбинаторы.
Но даже при том что рекурсия это goto функциональщины, она все-равно проще и лучше чем императивщина
Re[14]: [Linq] проверить последовательность
От: k.o. Россия  
Дата: 07.08.10 11:51
Оценка: +1
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, k.o., Вы писали:


KO>>С такой логикой, тебе придётся держать в голове всю историю изменений состояния нерекурсивного алгоритма.


U>Зачем? Чтобы убедиться, что на текущем шаге нерекурсивный алгоритм находится в правильном состоянии мне достаточно держать в голове один текущий экземпляр состояния. Чтобы убедиться, что на текущем шаге рекурсивный алгоритм находится в правильном состоянии мне нужно держать в голове весь стек экземпляров состояний.


"Текущий шаг" чисто-функционального рекурсивного алгоритма — это применение функции к конкретному набору параметров, т.е. всё тот же один текущий экземпляр состояния, зачем тебе весь стек экземпляров состояний? И, кстати, если он тебе вдруг всё таки понадобится, тебе его покажет отладчик, в отличие от предыдущих состояний императивного кода.
Re[15]: [Linq] проверить последовательность
От: Пельмешко Россия blog
Дата: 07.08.10 16:35
Оценка: +1
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, Пельмешко, Вы писали:


U>>>Если бы надо было отсечь два первых элемента, то как бы эта строчка выглядела?

П>>
П>>| h1::h2::tl -> f tl
П>>


U>А если нужно одновременно работать с двумя списками? Как компилятор определяет о каком списке идет речь?


Приведённый выше код:
let rec f = function 
    | a::b::_  when a > b   -> false
    | h::t                  -> f t
    | _                     -> true


Является укороченной записью следующего:
let rec f xs =
    match xs with
    | a::b::_  when a > b   -> false
    | h::t                  -> f t
    | _                     -> true


Как видите, список здесь — это лишь параметр, передающийся в выражение сравнения с образцом.
Re[16]: [Linq] проверить последовательность
От: k.o. Россия  
Дата: 09.08.10 14:06
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, k.o., Вы писали:


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


G>>>Здравствуйте, k.o., Вы писали:


KO>>Как здесь поможет оптимизация хвостовой рекурсии и может-ли GC собрать root, до завершения работы RecursiveNodeCount(root.Left) и вызова RecursiveNodeCount(root.Right)?с


G>Ну покажи эквивалентный код с циклами, где собираться будет.


С какой это радости? Код с циклами я приводил выше, о том что он эквивалентен рекурсивному я никогда не говорил, как раз наоборот. Прочитай внимательней дискуссию с Undying начиная отсюда
Автор: k.o.
Дата: 07.08.10
, вот краткая выжимка:
U> Использовать рекурсию нужно только там где без этого никак не обойтись.
Я> Без рекурсии можно обойтись всегда, вот пример.
U> Хорошо, использовать рекурсию нужно только там где нет возможности избавиться от хранения стека состояний.
Я> В моём примере, у явного управления стеком есть свои преимущества.
Ты> покажи эквивалентный код с циклами.
Я>

Хотя, надо признать, тут я не подумал, сборку узлов, после незначительного изменения можно получить и для рекурсивного кода.
int RecursiveNodeCount(Tree root)
{
    if (root == null)
    {
        return 0;
    }

    var right = root.Right;
    return 1 + RecursiveNodeCount(root.Left) + RecursiveNodeCount(right);
}

Но разница всё же есть: если в рекурсивном варианте об этом нужно специально позаботиться, то в коде с циклами это результат прямолинейного подхода.


KO>>>>2) в случае слишком глубокой рекурсии мы получим OutOfMemoryException, а не StackOverflowException, при котором даже блоки finally не выполняются.

G>>>Покажи код где такое происходит.

KO>>Что происходит? OutOfMemoryException? StackOverflowException? Код настолько тривиален, что, подозреваю, я неправильно тебя понял.


G>Реальный рекурсивный код где происходит OutOfMemoryException, но не происходит StackOverflowException.

G>И как помогут циклы в этом случае?

Прошу прощения, не думал, что мои слова будут настолько неправильно поняты. Ещё раз: в тех случаях, в которых использование рекурсии приведёт к StackOverflowException, эмуляция рекурсии через циклы и ручное управление стеком, приведёт, в худшем случае, к OutOfMemoryException.
[Linq] проверить последовательность
От: Dog  
Дата: 30.07.10 15:11
Оценка:
Есть последовательность чисел {1, 3, 5, 7, 9}
Надо проверить что числа следуют по возрастанию
Можно сделать при помощи linq?
Re: [Linq] проверить последовательность
От: Аноним  
Дата: 30.07.10 16:55
Оценка:
Здравствуйте, Dog, Вы писали:

Dog>Есть последовательность чисел {1, 3, 5, 7, 9}

Dog>Надо проверить что числа следуют по возрастанию
Dog>Можно сделать при помощи linq?

var s = new[] {1, 3, 3, 7, 9};
var r = s.Aggregate(new {V=int.MinValue, C=0}, (a, val) => a.V < val ? new {V=val, C=a.C+1} : a).C == s.Length;
Re[3]: [Linq] проверить последовательность
От: kkolyan  
Дата: 31.07.10 10:30
Оценка:
Здравствуйте, 0K, Вы писали:

0K>Здравствуйте, Пельмешко, Вы писали:


П>>Неэффективно, но декларативненько:

П>>
П>>var isAscending = xs.OrderBy(x => x).SequenceEqual(xs);
П>>


0K>Прошу прощения. А не проще ли и не понятее ли написать простенкий цикл с временной переменной? Или, профессиональный программист обязательно должен втулить это уродство куда ни попади, дабы все знали что он слышал про Linq и умеет им пользоваться?


П>>На Rx мона чуть короче:

П>>
П>>var isAscending = xs.Replay(ys => ys.Zip(ys.Skip(1), (x, y) => x <= y), 1).All(x => x);
П>>


0K>Что такое Rx? Это какая-то библиотека, или подход к написанию этих ваших Linq?


0K>Вам это правда понятее простого цикла с одной единственной временной переменной?


походу вопрос с собеседования или с экзамена, Rx действительно нах нужно
Re[3]: [Linq] Всех несогласных просьба сюда
От: 0K Ниоткуда  
Дата: 31.07.10 11:02
Оценка:
Здравствуйте, 0K, Вы писали:

Кто может обосновать что я не прав: http://rsdn.ru/forum/flame.comp/3900658.flat.aspx
Автор: 0K
Дата: 31.07.10
Re[4]: [Linq] проверить последовательность
От: 0K Ниоткуда  
Дата: 31.07.10 11:03
Оценка:
Здравствуйте, kkolyan, Вы писали:

K>походу вопрос с собеседования или с экзамена, Rx действительно нах нужно


Что какое Rx?
Re[2]: [Linq] проверить последовательность
От: IB Австрия http://rsdn.ru
Дата: 31.07.10 11:31
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>
П>var isAscending = xs.Replay(ys => ys.Zip(ys.Skip(1), (x, y) => x <= y), 1).All(x => x);
П>


Можно проще и без Rx. =) К счастью в 4FW метод Zip — часть LINQ.

var isAscending = sequence.Zip(sequence.Skip(1), (x, y) => x <= y).All(x => x);


А вот с Rx можно попробовать сделать так, чтобы перебор останавливался как только случится первое неудовлетворение предикату...
Мы уже победили, просто это еще не так заметно...
Re[4]: [Linq] проверить последовательность
От: IB Австрия http://rsdn.ru
Дата: 31.07.10 13:43
Оценка:
Здравствуйте, desco, Вы писали:

D>в вашем случае исходная последовательность будет перебираться дважды

Не совсем так, не перебираться дважды, а дважды обращаться к одному и тому же элементу. =)

D>для того, чтобы этого избежать нужно запоминать последний элемент (Memoize(1))

Да, эта функция уже в Rx...

D>а это обеспечивает стандартный All

Верно =)
Мы уже победили, просто это еще не так заметно...
Re[5]: [Linq] проверить последовательность
От: desco США http://v2matveev.blogspot.com
Дата: 31.07.10 14:06
Оценка:
Здравствуйте, IB, Вы писали:

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


D>>в вашем случае исходная последовательность будет перебираться дважды

IB>Не совсем так, не перебираться дважды, а дважды обращаться к одному и тому же элементу. =)

перебирается-перебирается

    class Seq : IEnumerable<int>
    {
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public IEnumerator<int> GetEnumerator()
        {
            Console.WriteLine("GetEnumerator");

            Console.WriteLine(1);
            yield return 1;

            Console.WriteLine(2);
            yield return 2;

            Console.WriteLine(3);
            yield return 3;

        }
    } 

    class Program
    {
        static void Main(string[] args) 
        {
            var sequence = new Seq();
//            var sequence = new Seq().Memoize(1);
            var isAscending = sequence
                .Zip(sequence.Skip(1), (x, y) => x <= y)
                .All(x => x); 
        }
    }


GetEnumerator
1
GetEnumerator
1
2
2
3

3


вариант с Memoize

GetEnumerator
1
2
3

Re[6]: [Linq] проверить последовательность
От: IB Австрия http://rsdn.ru
Дата: 31.07.10 14:21
Оценка:
Здравствуйте, desco, Вы писали:

D>перебирается-перебирается

Мммм.. Сформулируем еще точнее — создаются два итератора, которые поочереди обращаются к одному и тому же элементу. =)
Подозреваю, что накладные расходы на Memoize() и дополнительный итератор в среднем одинаковы, при стандартных сценариях. Вот если бы нам пришла блажь за каждым элементом лезть, например, в базу...
Мы уже победили, просто это еще не так заметно...
Re[4]: [Linq] проверить последовательность
От: FR  
Дата: 31.07.10 17:25
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Насчёт "уродства" — императивные циклы с мутабельными переменными и break-переходом куда красивше, дааа


Я конечно лезу не в свое болото но похоже эта задача не для Linq.
Что не мешает ее написать функционально http://www.rsdn.ru/forum/flame.comp/3900693.1.aspx
Автор: FR
Дата: 31.07.10

Или даже на вполне императивном D

auto f(int Arr[])
{
    if(Arr.length < 2)
        return true;
    
    if(Arr[0] > Arr[1])
        return false;
    
    return f(Arr[0 .. $ - 1]);
}


но в функциональном стиле, с хвостовой рекурсией и эффективностью близкой к циклу.
На Шарпе или C++ будет почти также.
Re: [Linq] проверить последовательность
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 31.07.10 19:00
Оценка:
Здравствуйте, Dog, Вы писали:

Dog>Есть последовательность чисел {1, 3, 5, 7, 9}

Dog>Надо проверить что числа следуют по возрастанию
Dog>Можно сделать при помощи linq?

Скажи пожалуйста, с какой целью ты задал вопрос ?
Вроде ж до сих пор ты не был студентом, а вопрос задал студенческий
У меня есть одно предположение, какое то решение у тебя есть и тебе нужны были варианты. Но для чего это надо — не ясно. Собеседование проводишь или сам ходишь по оным ?
Re[5]: [Linq] проверить последовательность
От: Аноним  
Дата: 31.07.10 23:24
Оценка:
Здравствуйте, SpaceConscience, Вы писали:

SC>Я уже послал Андерсу Хейлсбергу письмо c предложением включить в C# два кейворда для разделения императивного и декларативного кода:


SC>
SC>// Кейворд bydlokod помечает императивный код.
SC>bydlokod
SC>{
SC>    bool isAscending = true;
SC>    for (int i = 1; i < numbers.Length; i++)
SC>    {
SC>        if (numbers[i - 1] > numbers[i])
SC>        {
SC>            isAscending = false;
SC>            break;
SC>        }
SC>    }
SC>}
SC>


Ну киворд — это полумера...
let isAscending xs = xs |> Seq.pairwise |> Seq.forall (fun (a,b) -> a <= b)
Re[5]: [Linq] проверить последовательность
От: FR  
Дата: 01.08.10 06:34
Оценка:
Здравствуйте, SpaceConscience, Вы писали:

SC>Я уже послал Андерсу Хейлсбергу письмо c предложением включить в C# два кейворда для разделения императивного и декларативного кода:


Хорошее предложение, в D уже сделали http://www.digitalmars.com/d/2.0/function.html#pure-functions
И ключевое слово даже покруче pure
Re[4]: [Linq] Всех несогласных просьба сюда
От: Dog  
Дата: 02.08.10 08:36
Оценка:
0K>Кто может обосновать что я не прав: http://rsdn.ru/forum/flame.comp/3900658.flat.aspx
Автор: 0K
Дата: 31.07.10

Я, как автор топика, могу тебе ответить лишь твоими же словами.
Мальчик. Объясняю пока жив: главное внимательно читать что написано и не выдумывать лишнего.
Re[2]: [Linq] проверить последовательность
От: Dog  
Дата: 02.08.10 08:36
Оценка:
I>Скажи пожалуйста, с какой целью ты задал вопрос ?
I>Вроде ж до сих пор ты не был студентом, а вопрос задал студенческий
I>У меня есть одно предположение, какое то решение у тебя есть и тебе нужны были варианты. Но для чего это надо — не ясно. Собеседование проводишь или сам ходишь по оным ?
Да нет, стало интересно, может я чего не знаю
Вот, оказывается на Rx можно написать. Да и про Zip я не знал.
Re: [Linq] проверить последовательность
От: Undying Россия  
Дата: 02.08.10 10:45
Оценка:
Здравствуйте, Dog, Вы писали:

Dog>Есть последовательность чисел {1, 3, 5, 7, 9}

Dog>Надо проверить что числа следуют по возрастанию
Dog>Можно сделать при помощи linq?

Можно вот таким уродством:

  bool isAscending = vars.Aggregate<int, int?>(0, (prev, item) => prev == null || item <= prev ? null : (int?)item) != null;


Нормальной функции для работы с промежуточными данными в линке нет и как такая функция должна выглядеть в общем виде не понятно.
Re[2]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 02.08.10 11:01
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Неэффективно, но декларативненько:

П>
П>var isAscending = xs.OrderBy(x => x).SequenceEqual(xs);
П>

П>На Rx мона чуть короче:
П>
П>var isAscending = xs.Replay(ys => ys.Zip(ys.Skip(1), (x, y) => x <= y), 1).All(x => x);
П>


Помня одно предыдущее значение, соедини последовательность с самой собой, смещённой с на один элемент вперёд, и проверь, что во всех парах левое значение меньше или равно правому.


И с каких это пор эта заумь стала декларативным описанием задачи "проверить, что числа следуют по возрастанию"?

Тут указаний как делать намного больше, чем указаний что делать. А в декларативном описании все должно быть наоборот.
Re[5]: [Linq] проверить последовательность
От: FR  
Дата: 02.08.10 12:57
Оценка:
Здравствуйте, Undying, Вы писали:

U>А зачем себя ограничивать? Не проще ли императивные задачи записывать императивно, а функциональные функционально? Приведенная задача требует хранения промежуточного значения, т.е. является императивной, соответственно ее функциональное решение весьма уродливо. Так в чем смысл тащить это уродство в код?


Эта задача отлично ложится на функциональщину, но не на linq.
И она совсем не требует сохранения промежуточных значений, достаточно доступа к двум первым элементам и рекурсии:

pure auto f(int Arr[])
{
    if(Arr.length < 2)
        return true;
    
    if(Arr[0] > Arr[1])
        return false;
    
    return f(Arr[1 .. $]);
}


(код на D)
Re[2]: [Linq] проверить последовательность
От: Dog  
Дата: 02.08.10 14:16
Оценка:
K>Это исключительно и только вопрос полноты библиотеки для работы с коллекциями.
K>При использовании этой библиотеки, например, решение будет выглядеть так:
K>
K>var isAscending = new[]{1, 3, 5, 7, 9}.Reduce((a, b) => a <= b).And();
K>


Я как чувствовал, что всё уже украдено до нас
Re[6]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 03.08.10 05:00
Оценка:
Здравствуйте, FR, Вы писали:

FR>Эта задача отлично ложится на функциональщину, но не на linq.

FR>И она совсем не требует сохранения промежуточных значений, достаточно доступа к двум первым элементам и рекурсии:

FR>
FR>pure auto f(int Arr[])
FR>{
FR>    if(Arr.length < 2)
FR>        return true;
    
FR>    if(Arr[0] > Arr[1])
FR>        return false;
    
FR>    return f(Arr[1 .. $]);
FR>}
FR>



Т.е. ты хочешь сказать, что в функциональном стиле обращение к элементам массива по индексу считается хорошим тоном?

Допустим, но тогда не понятно, чем это лучше в сравнении:

for (int i = 1; i < arr.Length; ++i)
{
   if (arr[i] <= arr[i-1])
     return false;
}
return true;


Неужели вариант с рекурсией можно считать более понятным?
Re[7]: [Linq] проверить последовательность
От: FR  
Дата: 03.08.10 05:33
Оценка:
Здравствуйте, Undying, Вы писали:

U>Т.е. ты хочешь сказать, что в функциональном стиле обращение к элементам массива по индексу считается хорошим тоном?


В нормальных ФЯ есть паттерн матчинг, который позволяет без проблем выбрать первые два элемента.

U>Допустим, но тогда не понятно, чем это лучше в сравнении:


U>
U>for (int i = 1; i < arr.Length; ++i)
U>{
U>   if (arr[i] <= arr[i-1])
U>     return false;
U>}
U>return true;
U>


U>Неужели вариант с рекурсией можно считать более понятным?


С этим вариантом вариант с рекурсией одинаков по понятности. Но это для языков без паттерн матчинга, на том же
Ocaml'е например вариант с рекурсией намного более декларативен чем вариант с циклом.
Re[7]: [Linq] проверить последовательность
От: Пельмешко Россия blog
Дата: 06.08.10 21:56
Оценка:
Здравствуйте, SpaceConscience, Вы писали:

П>>Например, свёртка — фундаментальная операция над списками и ещё много чем — требует как раз промежуточного значения под аккумулятор


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


Господи, да что же Вы до бедной императивной студоты докопались-то так
Неужели я настолько бред написал, что Вы никак успокоиться не можете уже который день?

Да, свёртка выражается рекурсивной функцией, состояния у неё никакого нету.
Я отвечал на сообщение:

Приведенная задача требует хранения промежуточного значения, т.е. является императивной

так как не согласен с этим утверждением. Я имел ввиду, что за счёт постоянного вычисления нового значения аккамулятора из предыдущего, свёрткой достигается такое же поведение, как если бы было мутабельное "промежуточное" значение. То есть вполне можно выражать задачи, требующие "хранения промежуточного значения" и в функциональном стиле.

Выразился неудачно и некорректно, да. Прошу прощения.
Re[8]: [Linq] проверить последовательность
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.08.10 08:30
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

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


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


JR>Рекурсия — гадость сама по себе, тем более, что без неё практически всегда можно обойтись.


Расскажи это программистам на haskell\ocaml\lisp\f#
Re[7]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 08:43
Оценка:
Здравствуйте, SpaceConscience, Вы писали:

SC>Никакого "промежуточного состояния" (фюю, гадость императивная) свертка не требует, она прекрасно выражается рекурсивной функцией.


auto f(int Arr[])
{
    if(Arr.length < 2)
        return true;
    
    if(Arr[0] > Arr[1])
        return false;
    
    return f(Arr[0 .. $ - 1]);
}




Это типа здесь Arr не промежуточное состояние? И чем же оно не промежуточное и не состояние?

Рекурсия точно также требует промежуточных состояний, только делает это менее явным и более сложным образом (к примеру, в данной задаче вместо одного индекса приходится модифицировать и хранить аж коллекцию). Поэтому использовать рекурсию нужно только там где без этого никак не обойтись (например, при обходе деревьев), во всех остальных случаях рекурсия это резкое усложнение кода.
Re[5]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 08:46
Оценка:
Здравствуйте, FR, Вы писали:

FR>
FR>auto f(int Arr[])
FR>{
FR>    if(Arr.length < 2)
FR>        return true;
    
FR>    if(Arr[0] > Arr[1])
FR>        return false;
    
FR>    return f(Arr[0 .. $ - 1]);
FR>}
FR>


А, кстати, этот код вообще работает? Операция Arr[0 .. $ — 1] что делает? Создает новый массив, в котором нет последнего элемента? А нам разве не первый элемент удалить надо?
Re[8]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 09:11
Оценка:
Здравствуйте, FR, Вы писали:

FR>С этим вариантом вариант с рекурсией одинаков по понятности. Но это для языков без паттерн матчинга, на том же


В принципе понятность алгоритма понятие вполне объективное, более понятным является тот алгоритм, который лучше удовлетворяет бритве Оккама, т.е. в котором вводится меньше дополнительных сущностей и производится меньше их изменений.

В императивном алгоритме дополнительных сущностей вводится две: это предыдущий и текущий элементы (или их индексы). В рекурсивном алгоритме дополнительных сущностей три: во-первых, усеченная коллекция, во-вторых, индексы предыдущего и текущего элемента. Т.е. избавиться от предыдущего и текущего элемента все равно не получилось, но зато пришлось ввести еще лишнюю сущность — усеченную коллекцию, соответственно алгоритм стал сложнее.
Re: [Linq] проверить последовательность
От: ankf  
Дата: 07.08.10 09:28
Оценка:
Здравствуйте, Dog, Вы писали:

Dog>Есть последовательность чисел {1, 3, 5, 7, 9}

Dog>Надо проверить что числа следуют по возрастанию
Dog>Можно сделать при помощи linq?

Странно зачем народ использует OrderBy, Sort, Aggregate, все эти функции перебирают все множество элементов. Даже если условие не сработало на самом первом.
В Linq для целей задачи топиккастера есть функция Any и проблема решается достаточно просто


            var arr = new int[] { 1, 6, 7, 8, 9, 7 };

            int p = arr[0];
            if (arr.Any(x => p > (p = x) ))
                Console.WriteLine("Не упорядочена");
            else
                Console.WriteLine("Упорядочена");


при этом сложность алгоритма наименьшая — ищется первое несовпадение с предикатом и сразу выход из цикла.
Я программист, я Иван Помидоров, хватить трепатся — наш козырь error.
Re[9]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 09:35
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>С чего бы это? Рекурсия — это большущая красота, которая позволяет делать очень изящные штучки.


Рекурсия это именно что гадость сама по себе. Т.к. в нерекурсивном алгоритме в конкретный момент работы алгоритма имеется только одно состояние, а в рекурсивном алгоритме в этот же момент висит гирлянда состояний, которую удержать в голове намного сложнее.
Re[8]: [Linq] проверить последовательность
От: k.o. Россия  
Дата: 07.08.10 09:48
Оценка:
Здравствуйте, Undying, Вы писали:

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


SC>>Никакого "промежуточного состояния" (фюю, гадость императивная) свертка не требует, она прекрасно выражается рекурсивной функцией.


U>Это типа здесь Arr не промежуточное состояние? И чем же оно не промежуточное и не состояние?


U>Рекурсия точно также требует промежуточных состояний, только делает это менее явным и более сложным образом (к примеру, в данной задаче вместо одного индекса приходится модифицировать и хранить аж коллекцию). Поэтому использовать рекурсию нужно только там где без этого никак не обойтись (например, при обходе деревьев), во всех остальных случаях рекурсия это резкое усложнение кода.


Ты сам себе противоречишь. Без рекурсии в обычных императивных языках можно обойтись всегда, в том числе и при обходе деревьев. Тем не менее, я вижу, ты не собираешься спорить с тем, что, например, обход деревьев при помощи рекурсии выглядит понятнее и не является усложнением кода (иными словами в ряде случаев "импользовать рекурсию там где без этого можно обойтись" не только можно, но и нужно)? Более того, не потому-ли обход деревьев с помощью рекурсии проще, что такое состояние, как положение в дереве, неявным образом представлено стеком вызовов?
Re[9]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 09:51
Оценка:
Здравствуйте, k.o., Вы писали:

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


Каким образом можно обойти дерево произвольной глубины без рекурсии?
Re[10]: [Linq] проверить последовательность
От: _FRED_ Черногория
Дата: 07.08.10 09:52
Оценка:
Здравствуйте, Undying, Вы писали:

_FR>>С чего бы это? Рекурсия — это большущая красота, которая позволяет делать очень изящные штучки.


U>Рекурсия это именно что гадость сама по себе.


Такого не бывает. Даже "гады морские" не сами по себе гады, а по дремучести и суеверию мужиков.

U>Т.к. в нерекурсивном алгоритме в конкретный момент работы алгоритма имеется только одно состояние,


Одно _изменяемое_ состояние.

U>а в рекурсивном алгоритме в этот же момент висит гирлянда состояний, которую удержать в голове намного сложнее.


Зачем её [всю] в голове держать? Тем более, если это так "сложно"
Help will always be given at Hogwarts to those who ask for it.
Re[11]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 10:00
Оценка:
Здравствуйте, k.o., Вы писали:

KO>А зачем держать в голове весь "стек" вызовов рекурсивного алгоритма? Чисто-функциональный алгоритм зависит только от входных параметров, а был-ли он вызван рекурсивно или нет, совершенно неважно.


Е-мое. Естественно если алгоритм работает правильно, то совершенно по барабану как он там вызывается. А ошибок у вас в коде не бывает, стадии отладки тоже?
Re[2]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 10:05
Оценка:
Здравствуйте, ankf, Вы писали:

A>В Linq для целей задачи топиккастера есть функция Any и проблема решается достаточно просто


A>
A>            int p = arr[0];
A>            if (arr.Any(x => p > (p = x) ))
A>                Console.WriteLine("Не упорядочена");
A>


Ты чего? Тут же используется богопротивное изменяемое состояние. Тебя щас анафеме предадут, за такое надругательство над линком.
Re[12]: [Linq] проверить последовательность
От: k.o. Россия  
Дата: 07.08.10 10:12
Оценка:
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, k.o., Вы писали:


KO>>А зачем держать в голове весь "стек" вызовов рекурсивного алгоритма? Чисто-функциональный алгоритм зависит только от входных параметров, а был-ли он вызван рекурсивно или нет, совершенно неважно.


U>Е-мое. Естественно если алгоритм работает правильно, то совершенно по барабану как он там вызывается. А ошибок у вас в коде не бывает, стадии отладки тоже?


С такой логикой, тебе придётся держать в голове всю историю изменений состояния нерекурсивного алгоритма. И, кстати, для чисто-функционального алгоритма всегда по барабану как он там вызывается, если ошибка есть, она воспроизведётся и без рекурсии.
Re[11]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 10:18
Оценка:
Здравствуйте, k.o., Вы писали:

KO>Как-то так, компилировать не пробовал и с нерекурсивным алгоритмом мог немного налажать, он, как ни странно, оказался сложнее рекурсивного.


Если ты так любишь строгость определений, то нужно заменить:

U>Поэтому использовать рекурсию нужно только там где без этого никак не обойтись


на

U>Поэтому использовать рекурсию нужно только там где нет возможности избавиться от хранения стека состояний


А вот вводить хранение стека состояний в задачах, которые можно решить без этого, это усложнение кода и гадость сама по себе.
Re[13]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 10:22
Оценка:
Здравствуйте, k.o., Вы писали:

KO>С такой логикой, тебе придётся держать в голове всю историю изменений состояния нерекурсивного алгоритма.


Зачем? Чтобы убедиться, что на текущем шаге нерекурсивный алгоритм находится в правильном состоянии мне достаточно держать в голове один текущий экземпляр состояния. Чтобы убедиться, что на текущем шаге рекурсивный алгоритм находится в правильном состоянии мне нужно держать в голове весь стек экземпляров состояний.
Re[10]: Самое важное забыл
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.08.10 10:25
Оценка:
Здравствуйте, Undying, Вы писали:

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


FR>>>С этим вариантом вариант с рекурсией одинаков по понятности. Но это для языков без паттерн матчинга, на том же


U>>В принципе понятность алгоритма понятие вполне объективное, более понятным является тот алгоритм, который лучше удовлетворяет бритве Оккама, т.е. в котором вводится меньше дополнительных сущностей и производится меньше их изменений.


U>>В императивном алгоритме дополнительных сущностей вводится две: это предыдущий и текущий элементы (или их индексы). В рекурсивном алгоритме дополнительных сущностей три: во-первых, усеченная коллекция, во-вторых, индексы предыдущего и текущего элемента. Т.е. избавиться от предыдущего и текущего элемента все равно не получилось, но зато пришлось ввести еще лишнюю сущность — усеченную коллекцию, соответственно алгоритм стал сложнее.


U>В императивном алгоритме в конкретный момент работы алгоритма дополнительные сущности существуют в одном и только в одном экземпляре, в рекурсивном алгоритме в этот же момент имеется множество экземпляров (равное глубине рекурсии) дополнительных сущностей.

Бредятина.
1) Есть оптимизация хвостовой рекурсии, есть ленивость.
2) Если объекты неизменяемые, то в большинстве случаев не надо создавать новые экземпляры, только ссылки на них

U>Удерживать в голове один экземпляр намного проще, чем множество, поэтому нерекурсивные алгоритмы понимаются намного проще рекурсивных.

Почти все рекурсивные алгоритмы проще при применении правильных структур данных.
Re[6]: [Linq] проверить последовательность
От: FR  
Дата: 07.08.10 10:26
Оценка:
Здравствуйте, Undying, Вы писали:


U>А, кстати, этот код вообще работает? Операция Arr[0 .. $ — 1] что делает? Создает новый массив, в котором нет последнего элемента? А нам разве не первый элемент удалить надо?


Этот не работает
Так как удаляет последний элемент. Вот этот

pure auto f(int Arr[])
{
    if(Arr.length < 2)
        return true;
    
    if(Arr[0] > Arr[1])
        return false;
    
    return f(Arr[1 .. $]);
}


работает, я его даже запускал

Новый массив не создается, в D массивы ссылочные, создается срез который дает доступ только к нужным элементам.
Re[10]: [Linq] проверить последовательность
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.08.10 10:30
Оценка:
Здравствуйте, Аноним, Вы писали:

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


JR>>>Рекурсия — гадость сама по себе, тем более, что без неё практически всегда можно обойтись.


G>>Расскажи это программистам на haskell\ocaml\lisp\f#


А>Явная рекурсия — гадость. Она — как 'goto' функционального программирования.

Громкие слова, а толку ноль.

А>Практичеси всегда ее можно заменить на комбинацию более высокоуровневых конструкций (map/fold/unfold и т.д.).

Сделай-ка dropWhile без рекурсии. Или хотя бы эту самую проверку на упорядоченность.

А>За более детальным объяснением с доказательствами и примерами можно обратиться к классическому труду почитаемого тут Эрика Мейера Functional Programming with Bananas, Lenses, Envelopes, and Barbed Wire

Я много умного прочитал, в том числе и эту статью. Но у меня хватает мозга не кидаться громкими заявлениями.
Re[11]: Самое важное забыл
От: Undying Россия  
Дата: 07.08.10 10:34
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>2) Если объекты неизменяемые, то в большинстве случаев не надо создавать новые экземпляры, только ссылки на них


И какая разница? Еще одна сущность-то все равно возникает, и с точки зрения сложности алгоритма неважно представлена ли она физически в виде нового экземпляра или обертки над старым.
Re[9]: [Linq] проверить последовательность
От: FR  
Дата: 07.08.10 10:46
Оценка:
Здравствуйте, Undying, Вы писали:

U>В принципе понятность алгоритма понятие вполне объективное, более понятным является тот алгоритм, который лучше удовлетворяет бритве Оккама, т.е. в котором вводится меньше дополнительных сущностей и производится меньше их изменений.


При этом все эти оценки субъективны.

U>В императивном алгоритме дополнительных сущностей вводится две: это предыдущий и текущий элементы (или их индексы). В рекурсивном алгоритме дополнительных сущностей три: во-первых, усеченная коллекция, во-вторых, индексы предыдущего и текущего элемента. Т.е. избавиться от предыдущего и текущего элемента все равно не получилось, но зато пришлось ввести еще лишнюю сущность — усеченную коллекцию, соответственно алгоритм стал сложнее.


В рекурсивном алгоритме нет никаких индексов, и никаких усеченных коллекций все это чисто из-за бедности использованного языка, нет в D паттерн матчинга.
На OCaml рекурсивный вариант будет такой:

let rec f = function 
  | a::b::_  when a > b   -> false
  | h::t                  -> f t
  | _                     -> true


Тут все сущности уровня for или if в сиобразных.
А если на том же OCaml взять комбинаторный вариант:

let f l = pairwise l |> for_all (fun (a, b) -> a <= b)


Вообще деларативное описание чего хотим.
Re[9]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 11:03
Оценка:
Здравствуйте, FR, Вы писали:

FR>Тут не модифицируется и не копируется колекция, как уже писал используется срез который в машинном коде сводится к манипуляции указателями, и так как рекурсия хвостовая то она в том же машинном коде приводится к циклу:


Еще раз повторяю, что с точки зрения понятности алгоритма совершенно не важно создается ли физически новый экземпляр или только обертка над старым. Для программиста это все равно выглядит как появление в алгоритме еще одной сущности.
Re[11]: [Linq] проверить последовательность
От: Аноним  
Дата: 07.08.10 11:32
Оценка:
Здравствуйте, gandjustas, Вы писали:

А>>Явная рекурсия — гадость. Она — как 'goto' функционального программирования.

G>Громкие слова, а толку ноль.

Слова-то не мои. Все притенции — к Эрику.

G>Сделай-ка dropWhile без рекурсии. Или хотя бы эту самую проверку на упорядоченность.

Ну многие вещи через goto тоже проще и короче сделать Стоило ли городить весь этот огород из Foldable да Traversable если те же деревья можно рекурсивно обойти?
Ну впрочем
myDropWhile p = foldr (++) [] . unfoldr st
    where
      st []     = Nothing
      st (x:xs) = if p x then Just ([],xs) else Just ((x:xs),[])

А упорядочность тут вроде почти все без рекурсий решили.
Re[12]: [Linq] проверить последовательность
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.08.10 11:44
Оценка:
Здравствуйте, Аноним, Вы писали:

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


А>>>Явная рекурсия — гадость. Она — как 'goto' функционального программирования.

G>>Громкие слова, а толку ноль.
А>Слова-то не мои. Все притенции — к Эрику.
Так не надо их повторять, головой думай.

G>>Сделай-ка dropWhile без рекурсии. Или хотя бы эту самую проверку на упорядоченность.

А>Ну многие вещи через goto тоже проще и короче сделать
Какие например? Я знаю только одну — выход их вложенных циклов, она собственно так и делается при необходимости.

А>Стоило ли городить весь этот огород из Foldable да Traversable если те же деревья можно рекурсивно обойти?

Не выкручивайся теперь.

А>Ну впрочем

А>
А>myDropWhile p = foldr (++) [] . unfoldr st
А>    where
А>      st []     = Nothing
А>      st (x:xs) = if p x then Just ([],xs) else Just ((x:xs),[])
А>

Жесть

А>А упорядочность тут вроде почти все без рекурсий решили.

Только убого получилось, почти как у тебя.

dropWhile p [] = []
dropWhile p x:xs = if p x then dropWhile p xs else (x:xs)

isOrdered [] = true
isOrdered [_] = true
isOrdered a:b:xs = (a<b) && isOrdered (b:xs)


Вот так очень даже ниче смотрится.
Re[12]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 12:00
Оценка:
Здравствуйте, FR, Вы писали:

FR>Конкретно строку a::b::_ when a > b можно прочитать примерно так "список должен содержать два идущих друг за другом элемента a и b

FR>(и неважный нам хвост _) таких что a > b" если это условие выполняется то элементам a и b сопоставятся реальные значения из списка
FR>и выполнится то что идет после "->" то есть вернется false.

Тогда этот шаг более-менее понятен, а вот в этом шаге:

| h::t                  -> f t


как компилятор догадывается, что у списка надо отсечь первый элемент? Если бы надо было отсечь два первых элемента, то как бы эта строчка выглядела?
Re[13]: [Linq] проверить последовательность
От: Аноним  
Дата: 07.08.10 12:10
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Только убого получилось, почти как у тебя.

G>
G>isOrdered [] = true
G>isOrdered [_] = true
G>isOrdered a:b:xs = (a<b) && isOrdered (b:xs)
G>

G>Вот так очень даже ниче смотрится.

Мне кстати ваш предыдущий вариант
Автор: gandjustas
Дата: 04.08.10
даже больше понравился
Re[12]: [Linq] проверить последовательность
От: k.o. Россия  
Дата: 07.08.10 12:14
Оценка:
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, k.o., Вы писали:


KO>>Как-то так, компилировать не пробовал и с нерекурсивным алгоритмом мог немного налажать, он, как ни странно, оказался сложнее рекурсивного.


U>Если ты так любишь строгость определений, то нужно заменить:


U>>Поэтому использовать рекурсию нужно только там где без этого никак не обойтись


U>на


U>>Поэтому использовать рекурсию нужно только там где нет возможности избавиться от хранения стека состояний


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


На самом деле у нерекурсивного варианта, несмотря на всю его неприглядность, есть пара важных особенностей: 1) узлы могут быть собраны сборщиком мусора сразу после их обработки и 2) в случае слишком глубокой рекурсии мы получим OutOfMemoryException, а не StackOverflowException, при котором даже блоки finally не выполняются. Эквивалентный (при наличии оптимизации хвостовых вызовов) рекурсивный код, использующий CPS, будет выгледть уже не так хорошо:

int RecursiveNodeCount(Tree root, Func<int, int> continuation)
{
    if (root == null)
    {
        return continuation(0);
    }

    return RecursiveNodeCount(
        root.Left,
        leftCount =>
            RecursiveNodeCount(
                root.Right,
                rightCount => continuation(1 + leftCount + rightCount)));
}

int RecursiveNodeCount(Tree root)
{
    return RecursiveNodeCount(root, x => x);
}


В итоге, придём к тому, что строгого определения когда можно, а когда нельзя использовать рекурсию нет, а нужно, как и всегда, думать головой и использовать тот инструмент, который лучше всего решает задачу.
Re[13]: [Linq] проверить последовательность
От: FR  
Дата: 07.08.10 13:53
Оценка:
Здравствуйте, Undying, Вы писали:

U>Тогда этот шаг более-менее понятен, а вот в этом шаге:


U>
U>| h::t                  -> f t
U>


U>как компилятор догадывается, что у списка надо отсечь первый элемент? Если бы надо было отсечь два первых элемента, то как бы эта строчка выглядела?


Так тут и не надо догадываться, в ФЯ список это конструкция вида <элемент>::<хвост>, например в OCaml список можно задать таким псевдокодом

type 'a list = [] | :: of 'a * 'a list


То есть список или пустой или состоит из элемента и хвоста который сам является списком.
Двоеточие это оператор конструирующий список он принимает слева элемент справа список.

Для двух элементов будет так:
 a::b::tail -> ...


Ну и учти что сопоставление идет сверху вниз, и срабатывает первое удачное.
Re[14]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 16:11
Оценка:
Здравствуйте, Пельмешко, Вы писали:

U>>Если бы надо было отсечь два первых элемента, то как бы эта строчка выглядела?

П>
П>| h1::h2::tl -> f tl
П>


А если нужно одновременно работать с двумя списками? Как компилятор определяет о каком списке идет речь?
Re[16]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 07.08.10 17:29
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Является укороченной записью следующего:

П>
П>let rec f xs =
П>    match xs with
П>    | a::b::_  when a > b   -> false
П>    | h::t                  -> f t
П>    | _                     -> true
П>


П>Как видите, список здесь — это лишь параметр, передающийся в выражение сравнения с образцом.


Так match позволяет одновременно работать с несколькими списками или нет? Т.е. можно ли написать так: match xs1, xs2 with... ?
Re[8]: [Linq] проверить последовательность
От: SpaceConscience  
Дата: 07.08.10 18:09
Оценка:
JR>Рекурсия — гадость сама по себе, тем более, что без неё практически всегда можно обойтись.

Ничесе, какие у вас в мирке разночтения. Я думал, рекурсия — это вообще основа функционального программирования.

И можно поподробней, как в случае свертки обойтись без рекурсии, не пользуясь другими высокоуровневыми примитивами?
Собрался ставить минус? Да сам иди в жопу!

































































.
Re[9]: [Linq] проверить последовательность
От: FR  
Дата: 07.08.10 18:13
Оценка:
Здравствуйте, SpaceConscience, Вы писали:

SC>Ничесе, какие у вас в мирке разночтения. Я думал, рекурсия — это вообще основа функционального программирования.


Рекурсия это база и является самой низкоуровневой конструкцией, без нее конечно обойтись нельзя, но по возможности
нужно уменьшать ее использование так как комбинаторы выразительней и надежней.
Re[10]: [Linq] проверить последовательность
От: SpaceConscience  
Дата: 07.08.10 18:19
Оценка:
FR>Рекурсия это база и является самой низкоуровневой конструкцией, без нее конечно обойтись нельзя, но по возможности
FR>нужно уменьшать ее использование так как комбинаторы выразительней и надежней.

Ну это понятно, что нет смысла лепить низкоуровневую конструкцию, если у тебя есть высокоуровневая. Это вообще не ФП-специфичная вещь, а универсальная.
Собрался ставить минус? Да сам иди в жопу!

































































.
Re[8]: [Linq] проверить последовательность
От: SpaceConscience  
Дата: 07.08.10 18:20
Оценка:
Спасибо за вежливый и содержательный ответ. Приятно общаться с вежливым человеком. Жаль, на RSDN не все такие.
Собрался ставить минус? Да сам иди в жопу!

































































.
Re[8]: [Linq] проверить последовательность
От: SpaceConscience  
Дата: 07.08.10 18:57
Оценка:
U>Это типа здесь Arr не промежуточное состояние? И чем же оно не промежуточное и не состояние?

Типа нет, это (неизменяемые) аргументы функции. Промежуточное состояние — это когда ты создаешь переменную и ее изменяешь.

U>Рекурсия точно также требует промежуточных состояний, только делает это менее явным и более сложным образом (к примеру, в данной задаче вместо одного индекса приходится модифицировать и хранить аж коллекцию). Поэтому использовать рекурсию нужно только там где без этого никак не обойтись (например, при обходе деревьев), во всех остальных случаях рекурсия это резкое усложнение кода.


Потрясающий текст. "Делает это менее явным и более сложным образом" по сравнению с чем? По сравнению с комбинаторами? Но ведь комбинаторы, по крайней мере логически, могут быть реализованы только через рекурсию.

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

Рекурсия — это основная конструкция функционального программирования, обеспечивающая в нем полноту Тьюринга. Как можно говорить, что без нее можно обойтись? О чем речь вообще?

Чета, ребята, я смотрю у вас у всех разное понимание функционального программирования.
Собрался ставить минус? Да сам иди в жопу!

































































.
Re[9]: [Linq] проверить последовательность
От: FR  
Дата: 08.08.10 10:00
Оценка:
Здравствуйте, SpaceConscience, Вы писали:


SC>Рекурсия — это основная конструкция функционального программирования, обеспечивающая в нем полноту Тьюринга. Как можно говорить, что без нее можно обойтись? О чем речь вообще?


Если брать математический базис ФП — лямбда исчисление, то рекурсия не является основной конструкцией, и определяется через Y — комбинатор.

SC>Чета, ребята, я смотрю у вас у всех разное понимание функционального программирования.


Так корней много у функциональщины:

1) Классическое лямбда исчисление.

2) Теория категорий.

3) Нормальные алгорифмы Маркова.

... Склероз но точно что-то еще было
Re[5]: [Linq] проверить последовательность
От: Dog  
Дата: 09.08.10 08:28
Оценка:
U>
U>            int p = int.MinValue;
U>            if (arr.Any(x => p > (p = x) ))
U>                Console.WriteLine("Не упорядочена");
U>

U>Здесь это вроде прокатывает, но на более сложных задач это чревато ошибками, соответственно превосходство над старым-добрым foreach'ем теряется.
Что вы имеете ввиду?
Re[12]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 09.08.10 08:37
Оценка:
Здравствуйте, Klapaucius, Вы писали:

U>>А здесь нам просто повезло, что в языке есть стандартная функция разбиения на пары, которую достаточно для решения данной задачи. Если бы задача была бы немного другая, там бы стандартной функции не было.


K>В большинстве языков можно объявить функцию (метод, процедуру) самому. Представляете?


И? Это типа очень хорошо, когда для решения тривиальных задач нужно писать специальные функции?
Re[6]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 09.08.10 08:43
Оценка:
Здравствуйте, Dog, Вы писали:

U>>
U>>            int p = int.MinValue;
U>>            if (arr.Any(x => p > (p = x) ))
U>>                Console.WriteLine("Не упорядочена");
U>>

U>>Здесь это вроде прокатывает, но на более сложных задач это чревато ошибками, соответственно превосходство над старым-добрым foreach'ем теряется.
Dog>Что вы имеете ввиду?

То что неинициализированное с точки зрения алгоритма p уже получило значение корректное с точки зрения компилятора и рантайма. В некоторых случаях (например, при ошибках в реализации алгоритма) это чревато неочевидными ошибками (т.е. такими на которые ни компилятор не ругается, ни рантайм не падает).
Re[6]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 09.08.10 08:47
Оценка:
Здравствуйте, Dog, Вы писали:

U>>
U>>            int p = int.MinValue;
U>>            if (arr.Any(x => p > (p = x) ))
U>>                Console.WriteLine("Не упорядочена");
U>>

U>>Здесь это вроде прокатывает, но на более сложных задач это чревато ошибками, соответственно превосходство над старым-добрым foreach'ем теряется.
Dog>Что вы имеете ввиду?

Да и вообще это просто хак, который в другом случае бы не прокатил, например, если бы условие было не строгое больше, а больше-равно, то int.MinValue уже использовать было бы нельзя.
Re[13]: [Linq] проверить последовательность
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 09.08.10 09:01
Оценка:
Здравствуйте, k.o., Вы писали:

KO>На самом деле у нерекурсивного варианта, несмотря на всю его неприглядность, есть пара важных особенностей:

KO>1) узлы могут быть собраны сборщиком мусора сразу после их обработки
Это в случае использования генератора, а не материализованной коллекции.
А если есть оптимизация хвостовой рекурсии, то совершенно идентично работает.

KO>2) в случае слишком глубокой рекурсии мы получим OutOfMemoryException, а не StackOverflowException, при котором даже блоки finally не выполняются.

Покажи код где такое происходит.
Re[14]: [Linq] проверить последовательность
От: Undying Россия  
Дата: 09.08.10 09:54
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Во-первых, функции и существуют для решения тривиальных задач. И, собственно, являются инструментом для декомпозиции нетривиальных задач на эти самые тривиальные.


Хорошим инструментов является тот, в котором нужно производить декомпозицию тогда, когда это действительно нужно, а инструмент, в котором декомпозицию нужно производить на каждый чих, это плохой инструмент.
Re[14]: [Linq] проверить последовательность
От: k.o. Россия  
Дата: 09.08.10 09:59
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, k.o., Вы писали:


KO>>На самом деле у нерекурсивного варианта, несмотря на всю его неприглядность, есть пара важных особенностей:

KO>>1) узлы могут быть собраны сборщиком мусора сразу после их обработки
G>Это в случае использования генератора, а не материализованной коллекции.

Разумеется, GC не будет собирать объекты если они ещё где-то используются.

G>А если есть оптимизация хвостовой рекурсии, то совершенно идентично работает.


int RecursiveNodeCount(Tree root)
{
    if (root == null)
    {
        return 0;
    }

    return 1 + RecursiveNodeCount(root.Left) + RecursiveNodeCount(root.Right);
}


Как здесь поможет оптимизация хвостовой рекурсии и может-ли GC собрать root, до завершения работы RecursiveNodeCount(root.Left) и вызова RecursiveNodeCount(root.Right)?

KO>>2) в случае слишком глубокой рекурсии мы получим OutOfMemoryException, а не StackOverflowException, при котором даже блоки finally не выполняются.

G>Покажи код где такое происходит.

Что происходит? OutOfMemoryException? StackOverflowException? Код настолько тривиален, что, подозреваю, я неправильно тебя понял.
Re[15]: [Linq] проверить последовательность
От: Klapaucius  
Дата: 09.08.10 10:16
Оценка:
Здравствуйте, Undying, Вы писали:

U>Хорошим инструментов является тот, в котором нужно производить декомпозицию тогда, когда это действительно нужно


Ну так декомпозиция и производится потому, что она действительно нужна. Чтобы исключить дублирование кода и улучшить его читабельность, например. Так что все в порядке.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[15]: [Linq] проверить последовательность
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 09.08.10 10:42
Оценка:
Здравствуйте, k.o., Вы писали:

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


G>>Здравствуйте, k.o., Вы писали:


KO>>>На самом деле у нерекурсивного варианта, несмотря на всю его неприглядность, есть пара важных особенностей:

KO>>>1) узлы могут быть собраны сборщиком мусора сразу после их обработки
G>>Это в случае использования генератора, а не материализованной коллекции.

KO>Разумеется, GC не будет собирать объекты если они ещё где-то используются.


G>>А если есть оптимизация хвостовой рекурсии, то совершенно идентично работает.


KO>
KO>int RecursiveNodeCount(Tree root)
KO>{
KO>    if (root == null)
KO>    {
KO>        return 0;
KO>    }

KO>    return 1 + RecursiveNodeCount(root.Left) + RecursiveNodeCount(root.Right);
KO>}
KO>


KO>Как здесь поможет оптимизация хвостовой рекурсии и может-ли GC собрать root, до завершения работы RecursiveNodeCount(root.Left) и вызова RecursiveNodeCount(root.Right)?с


Ну покажи эквивалентный код с циклами, где собираться будет.

KO>>>2) в случае слишком глубокой рекурсии мы получим OutOfMemoryException, а не StackOverflowException, при котором даже блоки finally не выполняются.

G>>Покажи код где такое происходит.

KO>Что происходит? OutOfMemoryException? StackOverflowException? Код настолько тривиален, что, подозреваю, я неправильно тебя понял.


Реальный рекурсивный код где происходит OutOfMemoryException, но не происходит StackOverflowException.
И как помогут циклы в этом случае?
Re[7]: [Linq] проверить последовательность
От: Dog  
Дата: 09.08.10 11:03
Оценка:
Здравствуйте, Undying, Вы писали:

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


U>>>
U>>>            int p = int.MinValue;
U>>>            if (arr.Any(x => p > (p = x) ))
U>>>                Console.WriteLine("Не упорядочена");
U>>>

U>>>Здесь это вроде прокатывает, но на более сложных задач это чревато ошибками, соответственно превосходство над старым-добрым foreach'ем теряется.
Dog>>Что вы имеете ввиду?
U>Да и вообще это просто хак, который в другом случае бы не прокатил, например, если бы условие было не строгое больше, а больше-равно, то int.MinValue уже использовать было бы нельзя.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.