Re[28]: И снова Дельфи против СИ++
От: kochetkov.vladimir Россия https://kochetkov.github.io
Дата: 25.01.11 16:49
Оценка: :))
Здравствуйте, Ikemefula, Вы писали:

J>>>Боже... Дай, думаю, посмотрю, что пишут в "Дельфи против СИ++"...

I>Минусы за немерле, а примеры — хорошие.

Минусы за немерле — это как? Я же не виноват, что именно на примере этого языка статика рвет динамику, с чем не согласен-то?

[Интервью] .NET Security — это просто
Автор: kochetkov.vladimir
Дата: 07.11.17
Re[2]: И снова Дельфи против СИ++
От: Lloyd Россия  
Дата: 25.01.11 16:54
Оценка: :))
Здравствуйте, Dym On, Вы писали:

DO>"Дельфи против СИ++" — очень слабый вброс, старо и не актуально.


119 сообщений
Re[29]: И снова Дельфи против СИ++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 25.01.11 16:59
Оценка:
Здравствуйте, kochetkov.vladimir, Вы писали:

J>>>>Боже... Дай, думаю, посмотрю, что пишут в "Дельфи против СИ++"...

I>>Минусы за немерле, а примеры — хорошие.

KV>Минусы за немерле — это как? Я же не виноват, что именно на примере этого языка статика рвет динамику, с чем не согласен-то?


Я ж сказал, что примеры хорошие.

P.S. Щас вот подпись обновится и всё станет ясно
Re[26]: И снова Дельфи против СИ++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 25.01.11 17:01
Оценка:
Здравствуйте, kochetkov.vladimir, Вы писали:

KV>Можешь описать как в точности работает subroutine dispatcher или привести эквивалентный код на питоне?


Самому интересно
Re[30]: И снова Дельфи против СИ++
От: kochetkov.vladimir Россия https://kochetkov.github.io
Дата: 25.01.11 17:05
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>P.S. Щас вот подпись обновится и всё станет ясно


Ааааа. Я нахожу эту подпись несколько утопичной

[Интервью] .NET Security — это просто
Автор: kochetkov.vladimir
Дата: 07.11.17
Re[31]: И снова Дельфи против СИ++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 25.01.11 17:30
Оценка:
Здравствуйте, kochetkov.vladimir, Вы писали:

I>>P.S. Щас вот подпись обновится и всё станет ясно


KV>Ааааа. Я нахожу эту подпись несколько утопичной


Опасно ходишь !
Re[32]: И снова Дельфи против СИ++
От: kochetkov.vladimir Россия https://kochetkov.github.io
Дата: 25.01.11 17:36
Оценка:
Здравствуйте, Ikemefula, Вы писали:

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


I>>>P.S. Щас вот подпись обновится и всё станет ясно


KV>>Ааааа. Я нахожу эту подпись несколько утопичной


I>Опасно ходишь !


Опасно пишешь

[Интервью] .NET Security — это просто
Автор: kochetkov.vladimir
Дата: 07.11.17
Re[33]: И снова Дельфи против СИ++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 25.01.11 17:41
Оценка:
Здравствуйте, kochetkov.vladimir, Вы писали:

KV>>>Ааааа. Я нахожу эту подпись несколько утопичной


I>>Опасно ходишь !


KV>Опасно пишешь


А кому легко ?
Re[24]: И снова Дельфи против СИ++
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 25.01.11 18:21
Оценка:
Здравствуйте, Ikemefula, Вы писали:

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


I>>>Запрограммируй на С#/С++ конечный автомат какой. Сравни с его реализацией скажем на Питоне или Руби. Сделай выводы.

G>>А в чем проблема на C# сделать функцию из IEnumerable<T> в IEnumerable<V> на yield return?

I>Покажи пример автомата.


Я даже проще покажу, в духе твоего примера.

public class SampleMachine: StateMachine<State, Event>
{
    public SampleMachine()
    {
        StateTransition(State.A, Event.X, State.C);
        StateTransition(State.A, Event.Y, State.A);
        StateTransition(State.A, Event.Z, State.B);

        StateTransition(State.B, Event.W, State.B);
        StateTransition(State.B, Event.Y, State.C);
        StateTransition(State.B, Event.Z, State.A);

        StateTransition(State.C, Event.X, State.B);
    }
}


В принципе и на C++ можно такое же сделать.


G>>>>Если уж на то пошло, то большая часть того что пишется в динамике может быть выражена и в статике. Ну конечно зависит от языка.

I>>>Может и что ?
G>>То что утверждение про "писать в разы больше кода" несостоятельно.
I>В разы. Относительно С++ с его указателями так и вовсе в десятки раз.
Ну ты еще с ассемблером сравни.


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

G>>>>Чтобы получить надежность кода на уровне статического варианта тебе нужно написать для этого дела тест.
I>>>Зато в с#, C++ придется городить всякие визиторы.
G>>И часто тебе приходится их городить? Я визиторы писал пару раз в жизни всего. Еще несколько раз пользовался готовыми.
I>мне вот обходы всякие приходится писать чуть не постоянно
Обходы и визиторы — не одно и то же.
Я тоже часто пишу обходы, мне хватает IEnumerable<T> и Linq.

I>>>В итоге и там и там придется тесты писать

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

I>>>а основная логика в динамическом языке будет гораздо проще читаться.

G>>Опять-таки большая часть логики будет практически одинаково выражаться что в статике, что в динамике.
I>теоретически
Также как и увеличение кода, про которое ты рассказываешь.
Re[25]: И снова Дельфи против СИ++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 25.01.11 18:42
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Я даже проще покажу, в духе твоего примера.


G>
G>public class SampleMachine: StateMachine<State, Event>
G>{
G>    public SampleMachine()
G>    {
G>        StateTransition(State.A, Event.X, State.C);
G>        StateTransition(State.A, Event.Y, State.A);
G>        StateTransition(State.A, Event.Z, State.B);

G>        StateTransition(State.B, Event.W, State.B);
G>        StateTransition(State.B, Event.Y, State.C);
G>        StateTransition(State.B, Event.Z, State.A);

G>        StateTransition(State.C, Event.X, State.B);
G>    }
G>}
G>


G>В принципе и на C++ можно такое же сделать.


Можно, но твой код даже не скомпилится, т.к. надо пообъявлять State.A и тд.

Т.е. пока что ты сел в лужу

I>>>>Зато в с#, C++ придется городить всякие визиторы.

G>>>И часто тебе приходится их городить? Я визиторы писал пару раз в жизни всего. Еще несколько раз пользовался готовыми.
I>>мне вот обходы всякие приходится писать чуть не постоянно
G>Обходы и визиторы — не одно и то же.
G>Я тоже часто пишу обходы, мне хватает IEnumerable<T> и Linq.

Вот,сильно упрощенный пример. Покажи, как тут Linq поможет
IEnumerable<Vertex> Verteces(Vertex root)
{
   var hash = new HashSet<Vertex>();
   ListVisitor<Vertex> visitList = null; 
   Visitor<Vertex> visit = (v) => { hash.Add(v); visitList(v.Childs); };
   visitList = (l) => { foreach(var v in l ?? new Vertex[0] ) visit(v); }

   visit(root);

   return hash;
}


I>>теоретически

G>Также как и увеличение кода, про которое ты рассказываешь.

см выше.

I>>>>а основная логика в динамическом языке будет гораздо проще читаться.

G>>>Опять-таки большая часть логики будет практически одинаково выражаться что в статике, что в динамике.
I>>теоретически
G>Также как и увеличение кода, про которое ты рассказываешь.

в полном варианте кроме Vertex еще куча всяких классов. Как с ними быть — не ясно. А вот в динамие — одна рекурсивная фунцыя.
Re[26]: И снова Дельфи против СИ++
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 25.01.11 19:47
Оценка:
Здравствуйте, Ikemefula, Вы писали:

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


G>>Я даже проще покажу, в духе твоего примера.


G>>
G>>public class SampleMachine: StateMachine<State, Event>
G>>{
G>>    public SampleMachine()
G>>    {
G>>        StateTransition(State.A, Event.X, State.C);
G>>        StateTransition(State.A, Event.Y, State.A);
G>>        StateTransition(State.A, Event.Z, State.B);

G>>        StateTransition(State.B, Event.W, State.B);
G>>        StateTransition(State.B, Event.Y, State.C);
G>>        StateTransition(State.B, Event.Z, State.A);

G>>        StateTransition(State.C, Event.X, State.B);
G>>    }
G>>}
G>>


G>>В принципе и на C++ можно такое же сделать.


I>Можно, но твой код даже не скомпилится, т.к. надо пообъявлять State.A и тд.

I>Т.е. пока что ты сел в лужу
не включай дурачка, типа сам не догадаешься:

public enum State {A,B,C,D}
public enum Event {W,X,Y,Z}


По объему кода 1-в-1 соответствует тому что ты написан на Ruby.
В принципе и на C++ можно написать с тем же объемом.


I>>>>>Зато в с#, C++ придется городить всякие визиторы.

G>>>>И часто тебе приходится их городить? Я визиторы писал пару раз в жизни всего. Еще несколько раз пользовался готовыми.
I>>>мне вот обходы всякие приходится писать чуть не постоянно
G>>Обходы и визиторы — не одно и то же.
G>>Я тоже часто пишу обходы, мне хватает IEnumerable<T> и Linq.

I>Вот,сильно упрощенный пример. Покажи, как тут Linq поможет

I>
I>IEnumerable<Vertex> Verteces(Vertex root)
I>{
I>   var hash = new HashSet<Vertex>();
I>   ListVisitor<Vertex> visitList = null; 
I>   Visitor<Vertex> visit = (v) => { hash.Add(v); visitList(v.Childs); };
I>   visitList = (l) => { foreach(var v in l ?? new Vertex[0] ) visit(v); }

I>   visit(root);

I>   return hash;
I>}
I>



Держи
public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> childrenSelector)
{
    return source.SelectMany(e => Traverse(e, childrenSelector));
}

public static IEnumerable<T> Traverse<T>(T item, Func<T, IEnumerable<T>> childrenSelector)
{
    yield return item;
    foreach (var subItem in childrenSelector(item).Traverse(childrenSelector))
    {
        yield return subItem;
    }
}


И твой код сокращается до
TreeNumerable.Traverse(root, v => v.Childs ?? new Vertex[0]).Distinct()


Вообще визитор оправдан когда у тебя:
1)очень развесистая иерархия классов
2)она со временем не меняется
3)классы образуют дерево
4)алгоритмы обхода дерева часто меняются

В других случаях есть более простые способы.

Вообще странно что я тебе такое рассказываю.

I>в полном варианте кроме Vertex еще куча всяких классов. Как с ними быть — не ясно. А вот в динамие — одна рекурсивная фунцыя.

Используй комбинаторы.
Re[29]: И снова Дельфи против СИ++
От: FR  
Дата: 25.01.11 20:24
Оценка: :)
Здравствуйте, kochetkov.vladimir, Вы писали:

KV>Минусы за немерле — это как? Я же не виноват, что именно на примере этого языка статика рвет динамику, с чем не согласен-то?


Виноват, учи Хаскель или Pure
Re[26]: И снова Дельфи против СИ++
От: Ночной Смотрящий Россия  
Дата: 25.01.11 20:25
Оценка: +2 -1
Здравствуйте, Ikemefula, Вы писали:

I>Вот,сильно упрощенный пример. Покажи, как тут Linq поможет

I>
I>IEnumerable<Vertex> Verteces(Vertex root)
I>{
I>   var hash = new HashSet<Vertex>();
I>   ListVisitor<Vertex> visitList = null; 
I>   Visitor<Vertex> visit = (v) => { hash.Add(v); visitList(v.Childs); };
I>   visitList = (l) => { foreach(var v in l ?? new Vertex[0] ) visit(v); }

I>   visit(root);

I>   return hash;
I>}
I>


Это не паттерн Visitor, а какая то фигня. Паттерн используется, когда нужна диспетчеризация по типам с общим корнем.
Re[12]: И снова Дельфи против СИ++
От: std.denis Россия  
Дата: 25.01.11 21:06
Оценка: :))) :))
I>Если STL это обобщенное, то растет это из Ада
Скандалы-интриги-расследования: "корни STL найдены в Аду"
Сорри, не смог удержаться
Re[27]: И снова Дельфи против СИ++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.01.11 11:51
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

I>>Вот,сильно упрощенный пример. Покажи, как тут Linq поможет

I>>
I>>IEnumerable<Vertex> Verteces(Vertex root)
I>>{
I>>   var hash = new HashSet<Vertex>();
I>>   ListVisitor<Vertex> visitList = null; 
I>>   Visitor<Vertex> visit = (v) => { hash.Add(v); visitList(v.Childs); };
I>>   visitList = (l) => { foreach(var v in l ?? new Vertex[0] ) visit(v); }

I>>   visit(root);

I>>   return hash;
I>>}
I>>


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


Вообще говоря визитор это не только когда диспетчеризация по типам с общим корнем.

Эта же задача решается и с помощью визитора.
Re[27]: И снова Дельфи против СИ++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.01.11 12:09
Оценка:
Здравствуйте, gandjustas, Вы писали:

>>Держи

public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> childrenSelector)
{
    return source.SelectMany(e => Traverse(e, childrenSelector));
}

public static IEnumerable<T> Traverse<T>(T item, Func<T, IEnumerable<T>> childrenSelector)
{
    yield return item;
    foreach (var subItem in childrenSelector(item).Traverse(childrenSelector))
    {
        yield return subItem;
    }
}


Linq здесь ровно один вызов А кода уже больше, чем у меня Вот уж помощь так помощь

G>И твой код сокращается до

G>
G>TreeNumerable.Traverse(root, v => v.Childs ?? new Vertex[0]).Distinct() 
G>


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

G>Вообще визитор оправдан когда у тебя:


Спасибо за информацию, КО. Только если бы ты не торопился, то не стал бы пороть очевидную чушь.

I>>в полном варианте кроме Vertex еще куча всяких классов. Как с ними быть — не ясно. А вот в динамие — одна рекурсивная фунцыя.

G>Используй комбинаторы.

Шо ж ты сам их не показл преимущества этих комбинаторов ? Увлёкся, вероятно

P.S. Похоже, у меня в коде фатальный недостаток — мой код пиcан не тобой
Re[28]: И снова Дельфи против СИ++
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 26.01.11 12:19
Оценка:
Здравствуйте, Ikemefula, Вы писали:

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


>>>Держи

I>
I>public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> childrenSelector)
I>{
I>    return source.SelectMany(e => Traverse(e, childrenSelector));
I>}

I>public static IEnumerable<T> Traverse<T>(T item, Func<T, IEnumerable<T>> childrenSelector)
I>{
I>    yield return item;
I>    foreach (var subItem in childrenSelector(item).Traverse(childrenSelector))
I>    {
I>        yield return subItem;
I>    }
I>}
I>


I>Linq здесь ровно один вызов А кода уже больше, чем у меня Вот уж помощь так помощь

1)Это универсальный код, в отличие от твоего, написан один раз и используется всегда
2)Этот код работает лениво, в отличие от твоего

G>>И твой код сокращается до

G>>
G>>TreeNumerable.Traverse(root, v => v.Childs ?? new Vertex[0]).Distinct() 
G>>


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


Приведи пример, тогда посмотрим.


G>>Вообще визитор оправдан когда у тебя:

I>Спасибо за информацию, КО. Только если бы ты не торопился, то не стал бы пороть очевидную чушь.
Так ты спрашиваешь очевидные вещи и совершаешь банальные ошибки.

I>>>в полном варианте кроме Vertex еще куча всяких классов. Как с ними быть — не ясно. А вот в динамие — одна рекурсивная фунцыя.

G>>Используй комбинаторы.
I>Шо ж ты сам их не показл преимущества этих комбинаторов ? Увлёкся, вероятно
А Traverse это что по твоему?

I>P.S. Похоже, у меня в коде фатальный недостаток — мой код пиcан не тобой

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

PS. Пойди еще скажи тем кто Rx написал, что они неправы, потому что они написали очень много кода, который позволит сократить твой код на 2 строчки.
Re[29]: И снова Дельфи против СИ++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.01.11 13:04
Оценка:
Здравствуйте, gandjustas, Вы писали:

I>>Linq здесь ровно один вызов А кода уже больше, чем у меня Вот уж помощь так помощь

G>1)Это универсальный код, в отличие от твоего, написан один раз и используется всегда

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

G>2)Этот код работает лениво, в отличие от твоего


И ты уверен, что всегда нужна эта ленивость ?

G>>>И твой код сокращается до

G>>>
G>>>TreeNumerable.Traverse(root, v => v.Childs ?? new Vertex[0]).Distinct() 
G>>>


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


G>Приведи пример, тогда посмотрим.


Слишком большой пример получается а ты постоянно спрыгиваешь на свои задачи. В общих чертах примерно так — иерархическая структура, которую нужно обойти при чем некоторые объекты нужно обходить по нескольку раз. Как выделить более менее адекватный пример — пока не знаю и времени на это нет.

I>>>>в полном варианте кроме Vertex еще куча всяких классов. Как с ними быть — не ясно. А вот в динамие — одна рекурсивная фунцыя.

G>>>Используй комбинаторы.
I>>Шо ж ты сам их не показл преимущества этих комбинаторов ? Увлёкся, вероятно
G>А Traverse это что по твоему?

Это частный случай который больше никуде не приспособить

G>PS. Пойди еще скажи тем кто Rx написал, что они неправы, потому что они написали очень много кода, который позволит сократить твой код на 2 строчки.


C RX все в порядке, только он здесь ни при чем.
Re[30]: И снова Дельфи против СИ++
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 26.01.11 13:35
Оценка:
Здравствуйте, Ikemefula, Вы писали:

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


I>>>Linq здесь ровно один вызов А кода уже больше, чем у меня Вот уж помощь так помощь

G>>1)Это универсальный код, в отличие от твоего, написан один раз и используется всегда

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

Ок, приведи код с визитором, в котором надо как-то по-другому бегать.

G>>2)Этот код работает лениво, в отличие от твоего

I>И ты уверен, что всегда нужна эта ленивость ?
Там где не нужна будет я напишу ToList, а ты что сделаешь чтобы получить ленивость в своем коде?

G>>>>И твой код сокращается до

G>>>>
G>>>>TreeNumerable.Traverse(root, v => v.Childs ?? new Vertex[0]).Distinct() 
G>>>>


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


G>>Приведи пример, тогда посмотрим.


I>Слишком большой пример получается а ты постоянно спрыгиваешь на свои задачи.

Да ну?

Ты привел код, а когда я привел свой вариант, делающий ровно тоже самое, но с большим потенциалом повторного использования и композиции ты сказал:

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



А до этого пытался оправдать непонятно зачем написанный недовизитор тем что у тебя "еще куча всего".

I>в полном варианте кроме Vertex еще куча всяких классов.


Более того, ты завел разговор о визиторах, хотя зачем там визиторы — так и не смог показать.

I>Зато в с#, C++ придется городить всякие визиторы.


I>В общих чертах примерно так — иерархическая структура которую нужно обойти при чем некоторые объекты нужно обходить по нескольку раз. Как выделить более менее адекватный пример — пока не знаю и времени на это нет.

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

I>>>>>в полном варианте кроме Vertex еще куча всяких классов. Как с ними быть — не ясно. А вот в динамие — одна рекурсивная фунцыя.

G>>>>Используй комбинаторы.
I>>>Шо ж ты сам их не показл преимущества этих комбинаторов ? Увлёкся, вероятно
G>>А Traverse это что по твоему?
I>Это частный случай который больше никуде не приспособить
1)Не уходи от вопроса. Ты не считаешь Visitor комбинатором?
2)Он позволяет обойти любое дерево, где узел хранит ссылки на потомков
3)Так как обход делается лениво, то это позволяет без проблем комбинировать его с другими
Re[31]: И снова Дельфи против СИ++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.01.11 14:19
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>>>2)Этот код работает лениво, в отличие от твоего

I>>И ты уверен, что всегда нужна эта ленивость ?
G>Там где не нужна будет я напишу ToList, а ты что сделаешь чтобы получить ленивость в своем коде ?

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

G>>>Приведи пример, тогда посмотрим.


I>>Слишком большой пример получается а ты постоянно спрыгиваешь на свои задачи.

G>Да ну?

Ну да.

G>Ты привел код, а когда я привел свой вариант, делающий ровно тоже самое, но с большим потенциалом повторного использования и композиции ты сказал:


А для чего в частном случае целая куча кода как у тебя да еще с сайд-эффектами в виде недоленивости и проседания перформанса ?

G>А до этого пытался оправдать непонятно зачем написанный недовизитор тем что у тебя "еще куча всего".


И что тебя смущает ? Код завязан на определенную специфику и нет времени адаптировать его персонально для тебя.

G>Более того, ты завел разговор о визиторах, хотя зачем там визиторы — так и не смог показать.


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

I>>Это частный случай который больше никуде не приспособить

G>2)Он позволяет обойти любое дерево, где узел хранит ссылки на потомков

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

G>3)Так как обход делается лениво, то это позволяет без проблем комбинировать его с другими


Во первых, ленивость у тебя кастрированая. Во вторых, у тебя частный случай. В третьих проблемы в виде проседания перформанса в несколько раз. В четвертых, гнусная отладка получается с твоими "комбинаторами".
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.