Re: C++/CLI умеет все
От: Klapaucius  
Дата: 26.10.07 07:58
Оценка: +2 :)))
Здравствуйте, vdimas, Вы писали:

V>С++/CLR умеет всё, что умеет C#, и еще в несколько раз больше.


Мммм... Наверное я что-то упустил.
Как будет выглядеть на C++/CLI такой вот код:
public IEnumerable<RT> Map<T, RT>(this IEnumerable<T> seq, Func<T, RT> f)
{
    foreach(T elem in seq) yield return f(elem)
}

<...>

var inclist = list => list.Map(i => i+1);

не подскажете?
... << RSDN@Home 1.2.0 alpha rev. 774>>
'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[4]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 06:37
Оценка: -4 :)
Здравствуйте, Klapaucius, Вы писали:

K>Я просто в затруднении, не знаю как это понимать. Толи я живу какой-то нереальной жизнью (в этом я очень сомниваюсь, мне все-таки кажется, что я вполне реально существующий программист, а не мифическое существо вроде эльфа или филиппинского хирурга) толи под реальной жизнью вы понимаете свою собственную практику. Допустим, мне гораздо чаще приходиться встречать пользователей IEnumerable, чем пользователей C++/CLI, но к предмету разговора это никакого отношения не имеет.


С чего ты решил, что это пользователи IEnumerable. В 99% случаев, даже если в коде используется только методы IEnumerable-интерфейса, то под ним сидит ICollection как минимум, так что позволь мне считать их пользователями ICollection. Программисты почти всегда стараются писать "более общо", даже если это не требуется согласно сценариев. Опять же, какая кому разница, как внутри проекта через internal передаются данные, ты их считаешь "пользователями"? Я вот сужу по публичным интерфейсам классов. Возьми рефлектор и подсчитай кол-во наследников IEnumerable<T> и IEnumerable в публичных классах фреймворка, которые при этом не реализуют ICollection?. Там всего десяток (ДЕСЯТОК!!!) таких классов на 16 загруженных в рефлектор основных фреймворковых либ со многими тысячами классов.

Ну а теперь открой наследников ICollection (ICollection<T>)...
Всё ясно, малость поторопился отвечать, не вникнув в сказанное и не проверив лично...

Не, ну действительно, сколько мест в проекте, где реально требуются ленивые вычисления списков? Я в каждом из больших проектов если и припомню, то пару-тройку, не более. В остальных тысячах ситуаций данные откуда-то берутся, обрабатываются, и результат куда-то девается. И алгоритмы обработки обычно находятся в разделе "обрабатываются", а не в разделе "берутся". Для таких обычных сценариев просто пишут i=i+1 (или i=func(i) в том месте, где данные обрабатываются, а не тот наворот что ты представил вокруг банального i=i+1, и всё это с целью инжектить обработку данных в их источник. Увидев подобное в проекте, я бы спросил тихо автора: "не стыдно?"...

K>С низкой эффективностью тоже не совсем понятно. Что, вот так бывало напишете что-нибудь на IEnumerable, а потом попрофилируете и приходиться все-все IEnumerable заменять на ICollection? Лично для меня все это звучит как "в реальной жизни виртуальные функции практически не используются, ввиду низкой эффективности получаемых решений".


При чём тут виртуальные ф-ии? В обоих случаях мы имеем виртуальные ф-ии, не суть. Принципиальное отличие ICollection — в св-ве Count, что позволяет избегать Log2(N) перераспределений памяти, имелась ввиду именно эта эффективность. Я как-то и не предполагал, что кому-то может быть непонятна причина ориентации CLI/STL на ICollection.

Обсуждаемая CLI/STL заточена на эффективную обработку массивов данных (не в смысле одноименной конструкции Array, а в смысле большого кол-ва самих данных). Я потому и упёрся в пред. посте, что приведённый тобой пример для этих целей совершенно неуместен. Ну это же свинство городить такой огород из 2-х объектов (реально) и 2-х делегатов ради банального маппинга. Маппинг должен выглядеть так a = map(b);

В С++/CLI я могу оперировать как дотнетными делегатами, так непосредственно ф-иями, последнее увеличивает быстродействие в разы именно на алгоритмах обработки большого кол-ва данных (скажем, в области обработки сигналов).


K>Это не мой пример. В моем примере inclist это функция.


ну и? ф-ия, полученная путём карринга, которая возвращает объект IEnumerable, у которого надо позвать еще метод, чтобы получить другой объект — непосредственно целевой итератор... А почему не сразу целевой итератор возвращается? Не издержки ли выразительности...

Аналогичное (и гораздо более широко применимое в плане типов) замыкание в С++:

template<typename T, typename IteratorT>
struct MapIterator : IteratorT {
  typedef T FuncT(IteratorT::element_type);

  FuncT map;
  MapIterator(const IteratorT& it, FuncT f) : __super(it), map(f) {}
  T operator*() { return map(__super::operator*()); }
}

//tempate<typename T>
//T Inc(T arg) { return T+1; }

template<typename IteratorT>
MapIterator<IteratorT::element_type, IteratorT> inclist(IteratorT it)
{ return MapIterator<IteratorT::element_type, IteratorT>(it, _1+1); } // либо раскомментировать выше и вставить "Inc" вместо "_1+1"



K>Я так понимаю, что мы приходим к противоречию. С одной стороны, на C++ конечно можно написать то же, что и на C#, если иметь в виду полноту языка по Тьюрингу, но тогда слова "и еще в несколько раз больше" не верны. С другой стороны, если говорить о выразительности языка нельзя игнорировать итераторы


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

K> и лямбды,


при условии невозможности определять в C# типы по месту — это единственный выход не превращать код в лапшу. Но опять же, писать тела алгоритмов в лямбдах — так никто не делает, лямбды чаще служат для параметризации, карринга, комбинации и т.д. уже готовых алгоритмов. А вот написание этих самых алгоритмов в C# — Большая Проблема, достаточно невозможности использования банальных арифметических операций для генериков, и огромная доля алгоритмов становятся не обощаемыми. Compile-time генерация в C++ вкупе с возможностью перегрузки операторов позволяет действительно обобщать алгоритмы, и тут без реальных замеров где и кто больше выиграл рассуждать бесполезно. Могу лишь сказать от себя, т.к. очень долго сижу на дотнете (с самого начала), в общем, если идет речь о суммарной выразительности, то C# 2.0 сильно отстаёт от C++/CLI, даже с учетом конструкций yield return и delegate { типа_полузамыкание_тута}. Не берусь судить о 3.0, ибо ещё не работал толком, да и студия еще не вышла, т.е. сравнивать рановато.

K> которыми, по большому счету выразительность C# и определяется.


Смешно, однако. Сколько строчек с yield return в твоём текущем проекте? Сколько всего строчек в проекте? В сотнях тысяч строк сэкономили всего несколько сотен на yield return, но просрали около четверти от общего объема из-за ограниченых возможностей генериков... Я когда-то делал мини-систему обработки сигналов на дотнете, так запарился со всей этой выразительностью копипейстить, плюнул и сделал на обычном С++ в несколько раз короче. Очень сожалею, что не сразу обратил внимание на C++/CLI, мне бы это сэкономило еще половину времени (т.к. к выразительности кодогенерации добавилась бы моща фреймворка )


K>Если я, в ответ на простой вопрос, который я написал за 15 секунд, получаю пространные рассуждения о том, что это все никому не нужно,


В представленом виде — никому не нужно, извини. Это я тебе с позиций пользователя твоего кода.

K>нужно ли это понимать так, что написать в точности то же самое на C++/CLI нельзя?


Мощное заявление, однако, насчёт нельзя

K>из чего следует, что C# подмножеством C++/CLI не является, из чего в свою очередь следует, что в аспекте выразительности языка утверждение "С++/CLR умеет всё, что умеет C#" не является истинным. Ага?


Не ага. Кое-чего нет, но всё, что может C# можно сделать и в C++/CLI, некоторые конструкции требуют больше приседаний, например, замыкания в практике С++ описывают явно в виде объектов по месту вызова. Несколько лишних строк обычно, есть такое. Однако, верно обратное, C# не может многое из того, что может C++/CLI даже без учёта более общих возможностей комбинаций шаблонов и генериков, речь об возможностях самой платформы.

Вот тебе более интересная задача: есть некий серверный процесс, в нём по требованию создаётся домен и хостится некий сервис. Как всем остальным доменам процесса узнать, что сервисный домен уже существует, не пытаться создать его, и как получить MBR оного сервиса? попробуй на C#
Re[2]: C++/CLI умеет все
От: vdimas Россия  
Дата: 26.10.07 14:36
Оценка: 19 (1) -2 :)
Здравствуйте, Klapaucius, Вы писали:

V>>С++/CLR умеет всё, что умеет C#, и еще в несколько раз больше.


K>Мммм... Наверное я что-то упустил.

K>Как будет выглядеть на C++/CLI такой вот код:
...
K>не подскажете?

Для обычных коллекций я бы применил этот Func<> напрямую, причем, необязательно Func должен быть данный generic, это может быть любой подходящий делегат или просто ф-ия, т.е. там задействована compile-time кодогенерация (!!!). В реальной жизни голый IEnumerable практически не используется, ввиду низкой эффективности получаемых решений (кроме случаев потоковой обработки, чем практически никто не занимается да и не умеет толком). А для обычных коллекций мы вовсю можем юзать CLI/STL, конкретно для твоего случая это просто вызов ф-ии transform из библиотеки, т.е. даже короче запись получается. (думаю, не зря CLI/STL работает c ICollection<>, а не c IEnumerable<>, ведь задачей было реализовать эффективное решение, и они хвастаются, что им это удалось, т.е. обработка коллекций с помощью CLI/STL в общем случае эффективней, чем через стандартные Collection::Generic, foreach и прочие yield return, которые в итоге вырождаются в цепочку виртуальных вызовов методов промежуточных классов, т.к. есть куча готовых высокоэффективных алгоритмов и просто адаптеров).

Для этих особых потоковых случаев (т.е., где речь идет дейтсвительно о потоках, а не о сахаре синтаксиса) я бы написал потоковую реализацию transform и сделал твой пример где-то так:

int inc_item(int i) { return i+1; }
IEnumerable<int> inclist = transform(list, inc_item);


В общем, надо разбирать реальные случаи с самого верха, потому что в C++/CLI несколько другая идеология, конечную цель мы можем получить порой весьма экономным способом, ввиду развитой кодогенерации.

Когда-то пару лет назад я спорил с Владом насчет этих yield return, приводил возможные замены. В общем, на мой взгляд пара базовых хелперов-трансформаторов потока покрывают львиную долю сценариев использования yield return. Опять же, всякие for each в языке уже есть, не факт, что не будет добавлен и этот сахар.

В общем, это фигня, по сравнению с тем, что мы можем:
— без всяких using(){} использовать ограничение жизни — Dispose вызовется сам, если семантика обращения будет не ссылочная, а как для value-type
— располагать value-type в куче, без приведения к object, т.е. боксирование-то типизированное, как оно реально есть в CLR
int^ k = gcnew int(10);
int^ i = k;
*i=5;
Console::WriteLine(i);

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

Получается очень прикольная стратегия написания программ с использованием CLR/C++ — все небольшие классы надо описывать как value-type, но при необходимости использовать их как ссылочные.

— получать делегаты на геттеры и сеттеры св-в (!!!)

— есть статические переменные уровня домена, но можно сделать статические переменные уровня процесса (!!)

— можно делать непосредственную реализацию сразу нескольких интерфейсов:
ref struct X : public I1, I2 {
   virtual void f() = I1::f, I2::f {
      System::Console::WriteLine("X::f override of I1::f and I2::f");
   }
};

а вот еще прикольнее:
ref class X : public I1 {
public:
   virtual void g() = I1::f {
      System::Console::WriteLine("X::g");
   }
};


Раздражает только то, что managed-классов не поддерживается ковариация, иначе бы не было более удобной системы переопределений и имплементаций.


— использовать сочетание generic и template, что позволяет, в отличие от C# проводить декомпозицию по стратегиям, при имплементации generic-интерфесов.

последний пункт — реально бомба, т.е. вся мощь нормальной кодогенерации, которой мне не хватало в C# у нас есть опять. Тем более, что есть compile-time traits, типа: __is_enum( type ), __is_delegate( type ), __is_ref_array( type ), __is_base_of( base , derived), __is_abstract( type ) и т.д.


Ну и при этом порождается не нативный image как ранее, а обычный переносимый VM byte-code.
Re[7]: C++/CLI умеет все
От: VoidEx  
Дата: 22.11.07 17:00
Оценка: 1 (1) +3
Здравствуйте, VladD2, Вы писали:

VE>>Я его не без толку засоряю, а выражаю свое мнение.

VD>Это тебе так кажется. А на поверку твои минусы, расставленные по всем подряд сообщениям, никакой информации окружающим не дают.
А я и не ставил целью дать людям какую-то информацию. Для этого сообщения есть.

VE>> Если мне этого делать нельзя, я не буду.

VD>Ставь сколько угодно. Только спамить ими не надо. Если уж ты не согласен с чем-то, то надо хоть изредка аргументировать свое несогласие.
Хорошо, надо так надо. Знать бы критерии, когда надо, а когда нет.

VE>>Я бы объяснял, и могу объяснить тем, кто это воспримает именно как мнение, а не как на покушение не знаю на что, с последующим спором. А уж как некоторые проводят споры, так даже перепалки "Delphi vs C++" на gamedev.ru кажется дискуссией ученых мужей.

VD>Хм. Пока что я вижу, что ты банально неумеешь обосновывать свое мнение и прикрываешься гипотетическими рассуждениями о чужой реакции.
Вот понимаешь ли, у людей разные мнения, и твое видение может расходиться с видением окружающих. Это, конечно, не значит, что твое видение неверно, но как минимум это повод задуматься.
Я, конечно, понимаю, что это банальная истина про разные мнения, но то ли ты ее не понимаешь, то ли по каким-то еще причинам хочешь мне-таки свое мнение навязать, которого я, заметь, не спрашивал.
И уж я наверное получше тебя знаю, прикрываюсь я или нет.
Забавно, что ты видишь, что я банально не умею обосновывать свое мнение.
Вот вроде бы я пока мнений своих письменно не выражал, однако выводы ты уже сделал. Наверное, по аналогии с детским лепетом типа такого:
-А ты можешь в лужу лечь?
-Могу!
-Ляг!
-Не хочу
-Аааа! Значит не можешь!

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

VE>>Но в любом случае, если кому-то будет интересно, почему я согласен/не согласен, может спросить.

VD>Другими словами, твое мнение пока что никому не интересно? Так? Ну, а что тогда его выпячивать?
Вот смотри. Есть система оценок, которая, как ни странно, не подразумевает непосредственного ответа сообщением. Логично, что она предназначена, чтобы выразить согласие/несогласие без написания сообщений? Вот я ее так и использую. В противном случае тут была бы кнопка "не согласиться", после нажатия на которую пришлось бы писать сообщение с обоснованием. Увы, такого нет.
Более того, ты же моим мнением поинтересовался? Значит, все-таки, интересно. Вот, поэтому я сейчас и распинаюсь. Мне было бы проще несогласиться специально предназначенным для этого средством, но тебе это, видимо, слишком не нравится.
А вот кто из нас двоих и выпячивает мнение, так точно не я. Я уж не беру в расчет другие темы, а-ля
-Смотрите, A = B!
-Ну и? Зато N > A && N > B.
-А причем тут N?
-А причем тут A и B? Почему ты тогда не посвятил свою тему проблемам с кучей C/C++

А хотя бы касательно данного обсуждения.
Ведь я твоего мнения не спрашивал. Поставил бы мне минус и все, я бы не заметил даже.
Кстати, очень прошу, не отвечай на сообщение, меня твое мнение по этому вопросу совсем не интересует, поставь минус.
Мое предыдущее сообщение так же было законченным, не требующим пояснений.
Если ты думаешь, что другим шибко интересно твое мнение о моем отношении к системе оценок RSDN, то и обращайся к другим, мол, давайте закопаем мракобеса ВойдЕкса за учиненные беспорядки.
А то получается, что ты пока потверждаешь мои слова, что выражение мнения рождает никому не нужный спор, а также противоречишь сам себе. Раз мое мнение никому не интересно, проигнорируй.
Re[6]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.11.07 09:37
Оценка: -2 :)
Здравствуйте, VoidEx, Вы писали:

VE>Я его не без толку засоряю, а выражаю свое мнение.


Это тебе так кажется. А на поверку твои минису расставленные по всем подряд сообщения никакой информации окружающим не дают.

VE> Если мне этого делать нельзя, я не буду.


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

VE>Я бы объяснял, и могу объяснить тем, кто это воспримает именно как мнение, а не как на покушение не знаю на что, с последующим спором. А уж как некоторые проводят споры, так даже перепалки "Delphi vs C++" на gamedev.ru кажется дискуссией ученых мужей.


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

VE>Но в любом случае, если кому-то будет интересно, почему я согласен/не согласен, может спросить.


Другими словами, твое мнение пока что никому не интересно? Так? Ну, а что тогда его выпячивать?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 11:12
Оценка: +3
Здравствуйте, vdimas, Вы писали:

V>Охотно верю, но коль пошло сравнение выразительности именно шарпа, то интересует голая статистика по выделенному.

Вот только из одного проекта:
NemerleIntellisenseProvider.cs
NemerleLanguageService.cs
SnippetsEnumerator.cs
ProjectInfo.cs
CodeModel/CompileUnitCollection.n
Project.n
Runner.n
NemerleCodeParser.n

Особо интересен вот этот фалик: NemerleLanguageService.cs. Там на yield реализована (причем очень прозрачно) логика с которой иначе пришлось бы помучиться. Главено понять, что yield дает не только отложенное выполнение, но и инверсию исполнения. Многие алгоритмы становятся плоскими и очевидными с применением yield, когда как без него они получаются запутанными.

Использование итераторов (по сути ограниченных континюэшонов) ограничивается скорее не их особенностями, а умением их применять. Многие люди просто не способны отойти от мышления массивами и коллекциями.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: C++/CLI умеет все
От: Кодёнок  
Дата: 22.11.07 16:54
Оценка: +3
Здравствуйте, vdimas, Вы писали:

VD>>Тебе, между прочем, тоже показали, что С++ не может, что может C#.


V>Ну тогда сформулирую прямо: С++/CLI может всё что C#, но некоторые вещи за счёт оверхеда и приседаний. C# в свою очередь не имеет доступа ко всем возможностям CLR, в отличие от C++/CLR. Так пойдёт?


Старая как мир ошибка технарей. Язык ничего не может. Творить может связка человек+программист. Теоретически, hex-редактор может больше всех, но никакой человек не захочет писать в нём, поэтому реально он может меньше всех.
Re[3]: C++/CLI умеет все
От: Klapaucius  
Дата: 29.10.07 14:26
Оценка: +2
Здравствуйте, vdimas, Вы писали:

V>В реальной жизни голый IEnumerable практически не используется, ввиду низкой эффективности получаемых решений (кроме случаев потоковой обработки, чем практически никто не занимается да и не умеет толком).


Я просто в затруднении, не знаю как это понимать. Толи я живу какой-то нереальной жизнью (в этом я очень сомниваюсь, мне все-таки кажется, что я вполне реально существующий программист, а не мифическое существо вроде эльфа или филиппинского хирурга) толи под реальной жизнью вы понимаете свою собственную практику. Допустим, мне гораздо чаще приходиться встречать пользователей IEnumerable, чем пользователей C++/CLI, но к предмету разговора это никакого отношения не имеет. С низкой эффективностью тоже не совсем понятно. Что, вот так бывало напишете что-нибудь на IEnumerable, а потом попрофилируете и приходиться все-все IEnumerable заменять на ICollection? Лично для меня все это звучит как "в реальной жизни виртуальные функции практически не используются, ввиду низкой эффективности получаемых решений".

V>А для обычных коллекций мы вовсю можем юзать CLI/STL, конкретно для твоего случая это просто вызов ф-ии transform из библиотеки, т.е. даже короче запись получается.


В огороде бузина, а в Киеве дядька. Это конечно здорово, что для чего-то о чем я не спрашивал можно использовать что-то о чем я не спрашивал, но ведь я об этом не спрашивал!

V>Для этих особых потоковых случаев (т.е., где речь идет дейтсвительно о потоках, а не о сахаре синтаксиса) я бы написал потоковую реализацию transform


Вообще-то я и просил в том числе и написать потоковую реализацию map на C++ — на C# я написал ее за несколько секунд, правда с ошибкой — забыл указать, что метод-расширение статический.

V>и сделал твой пример где-то так:

V>
V>int inc_item(int i) { return i+1; }
V>IEnumerable<int> inclist = transform(list, inc_item);
V>


Это не мой пример. В моем примере inclist это функция.

V>В общем, надо разбирать реальные случаи с самого верха, потому что в C++/CLI несколько другая идеология, конечную цель мы можем получить порой весьма экономным способом, ввиду развитой кодогенерации.


Я так понимаю, что мы приходим к противоречию. С одной стороны, на C++ конечно можно написать то же, что и на C#, если иметь в виду полноту языка по Тьюрингу, но тогда слова "и еще в несколько раз больше" не верны. С другой стороны, если говорить о выразительности языка нельзя игнорировать итераторы и лямбды, которыми, по большому счету выразительность C# и определяется. Если я, в ответ на простой вопрос, который я написал за 15 секунд, получаю пространные рассуждения о том, что это все никому не нужно, нужно ли это понимать так, что написать в точности то же самое на C++/CLI нельзя? из чего следует, что C# подмножеством C++/CLI не является, из чего в свою очередь следует, что в аспекте выразительности языка утверждение "С++/CLR умеет всё, что умеет C#" не является истинным. Ага?

V>Когда-то пару лет назад я спорил с Владом насчет этих yield return, приводил возможные замены. В общем, на мой взгляд пара базовых хелперов-трансформаторов потока покрывают львиную долю сценариев использования yield return. Опять же, всякие for each в языке уже есть, не факт, что не будет добавлен и этот сахар.


Я эту тему, в свое время, даже читал. Внятного обоснования данного утверждения я там не нашел, да и то, что непонятная "лвиная доля" это не 100% никто и не оспаривает, так? А то что, возможно, будет когда-то добавлено (я даже слухов таких не слышал, впрочем) к состоянию дел сегодня отношения не имеет, не так ли?

V>В общем, это фигня, по сравнению с тем, что мы можем:


Это вопрос дискуссионный, для кого-то фигня это — а для кого-то то.
... << RSDN@Home 1.2.0 alpha rev. 774>>
'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[5]: C++/CLI умеет все
От: Sinclair Россия https://github.com/evilguest/
Дата: 22.11.07 08:18
Оценка: +2
Здравствуйте, vdimas, Вы писали:

V>С чего ты решил, что это пользователи IEnumerable. В 99% случаев, даже если в коде используется только методы IEnumerable-интерфейса, то под ним сидит ICollection как минимум, так что позволь мне считать их пользователями ICollection.

Я — не позволю. Неважно, что там под ним "сидит". Пользователи этим никак не пользуются.

V>Программисты почти всегда стараются писать "более общо", даже если это не требуется согласно сценариев. Опять же, какая кому разница, как внутри проекта через internal передаются данные, ты их считаешь "пользователями"? Я вот сужу по публичным интерфейсам классов. Возьми рефлектор и подсчитай кол-во наследников IEnumerable<T> и IEnumerable в публичных классах фреймворка, которые при этом не реализуют ICollection?. Там всего десяток (ДЕСЯТОК!!!) таких классов на 16 загруженных в рефлектор основных фреймворковых либ со многими тысячами классов.

Поэтому совершенно неважно, кто кого наследует.
Важно количество foreach по сравнению с [].


V>При чём тут виртуальные ф-ии? В обоих случаях мы имеем виртуальные ф-ии, не суть. Принципиальное отличие ICollection — в св-ве Count, что позволяет избегать Log2(N) перераспределений памяти, имелась ввиду именно эта эффективность.

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

V>ну и? ф-ия, полученная путём карринга, которая возвращает объект IEnumerable, у которого надо позвать еще метод, чтобы получить другой объект — непосредственно целевой итератор... А почему не сразу целевой итератор возвращается? Не издержки ли выразительности...

Спички экономим? Один виртуальный вызов на фоне миллионов вызовов MoveNext?

V>при условии невозможности определять в C# типы по месту — это единственный выход не превращать код в лапшу. Но опять же, писать тела алгоритмов в лямбдах — так никто не делает, лямбды чаще служат для параметризации, карринга, комбинации и т.д. уже готовых алгоритмов.

Почему это не делает? Еще как делает.
V>А вот написание этих самых алгоритмов в C# — Большая Проблема, достаточно невозможности использования банальных арифметических операций для генериков, и огромная доля алгоритмов становятся не обощаемыми. Compile-time генерация в C++ вкупе с возможностью перегрузки операторов позволяет действительно обобщать алгоритмы, и тут без реальных замеров где и кто больше выиграл рассуждать бесполезно. Могу лишь сказать от себя, т.к. очень долго сижу на дотнете (с самого начала), в общем, если идет речь о суммарной выразительности, то C# 2.0 сильно отстаёт от C++/CLI, даже с учетом конструкций yield return и delegate { типа_полузамыкание_тута}. Не берусь судить о 3.0, ибо ещё не работал толком, да и студия еще не вышла, т.е. сравнивать рановато.
Вышла. Можешь начинать сравнивать.


V>Смешно, однако. Сколько строчек с yield return в твоём текущем проекте?

Строчек — немного, поскольку они в основном расположены в хэлперном классе. Зато используются они очень интенсивно.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 19:01
Оценка: +1 -1
Здравствуйте, Кодёнок, Вы писали:


V>>Ну тогда сформулирую прямо: С++/CLI может всё что C#, но некоторые вещи за счёт оверхеда и приседаний. C# в свою очередь не имеет доступа ко всем возможностям CLR, в отличие от C++/CLR. Так пойдёт?


Кё>Старая как мир ошибка технарей. Язык ничего не может. Творить может связка человек+программист. Теоретически, hex-редактор может больше всех, но никакой человек не захочет писать в нём, поэтому реально он может меньше всех.


Ну если ты мне дашь такой hex-редактор, который позволит прикручивать аспекты и вообще производить за меня кодогенерацию для .Net малым числом строк, то я согласен. А иначе сравнение малость неккоректно. Я вполне трезво оценил потери в одном месте и выигрыш в другом, и в отличие от моих оппонентов одинаково неплохо владею обоими обсуждаемыми вещами, чтобы позволить себе сравнивать.

Это не значит, что я полностью перееду на C++/CLI, т.к. на самом деле для C# есть еще одна фича, которая весьма прибавляет ему веса — это развитый рефакторинг. Но вот писать отдельные либы для проектов на нём — запросто и аж бегом, всё-равно в итоге получаем не нативный image, а такой же точно byte-code.
Re[7]: C++/CLI умеет все
От: palm mute  
Дата: 22.11.07 17:04
Оценка: 14 (1)
Здравствуйте, Klapaucius, Вы писали:

FR>>В питоне с помощью yield (правда он помощнее шарповского) красиво делается много вещей


K>Можно подробнее про выделенное? Желательно с примерами.

http://docs.python.org/whatsnew/pep-342.html
http://www.python.org/dev/peps/pep-0342/
Re[7]: C++/CLI умеет все
От: FR  
Дата: 22.11.07 17:25
Оценка: 14 (1)
Здравствуйте, Klapaucius, Вы писали:

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


FR>>В питоне с помощью yield (правда он помощнее шарповского) красиво делается много вещей


K>Можно подробнее про выделенное? Желательно с примерами.


За счет того что питон динамический и следовательно все функции обобщенные, yield просто удобней применять например как тут:

http://www.iso.ru/journal/articles/print/155.html
http://www.iso.ru/journal/articles/189.html
http://www.iso.ru/journal/articles/print/190.html

Та же обобщеность помогает построить итераторы во многом эквивалентные основным фвп используемым в функциональных языках:

http://docs.python.org/lib/itertools-functions.html
http://docs.python.org/lib/itertools-example.html
http://www.iso.ru/journal/articles/print/284.html

Ну и начиная с python2.5 yield стал двухстороним и может передавать даные в обе стороны:

http://docs.python.org/whatsnew/pep-342.html
http://www.python.org/dev/peps/pep-0342/

Что позволяет делать всякие вкусности типа http://en.wikipedia.org/wiki/Coroutine
Re[7]: C++/CLI умеет все
От: FR  
Дата: 22.11.07 12:37
Оценка: 9 (1)
Здравствуйте, vdimas, Вы писали:

V>yield на самом деле штука очень мощная, жаль что нет его в D. Хотя, правда в том, что за последние 3 года мощща этого yield по-настоящему пригодилась пару раз всего, остальные случаи были тривиальны, и не сильно отличались бы в исполнении от MoveNext().


Ну в том же питоне даже сопрограммы на этом делаются.


FR>>Не замыкания плюс auto очень удобно, я на D по мелочи пописываю, сильно местами жизнь облегчает.


V>Зато в С++, ввиду ручной эмуляции замыканий, ты можешь вручную же разруливать одну из проблем замыканий — степени устойчивости данных.


Так в D никто ни запрещает точно так же сделать

V>Вот обрати внимание, что в эмулируемом замыкании одна переменная хранится по-значению, другая по ссылке. Когда-то я был ошарашен тем, что разные реализации LISP и Scheme используют разную степень фиксации, в терминах С++ некоторые по ссылке, а некоторые по-значению, отсюда некоторые алгоритмы работают совершенно по-разному в разных реализациях. И это в прородителях всех существующих замыканий.


В схеме по моему всегда по ссылке.

V>Кстати, а как фиксируются данные в замыканиях D?


По ссылке:
import std.stdio;

void  make(ref int delegate() get, ref void delegate(int)  set)
{    
    int x = 0;
    
    get = {return x;};
    set = (int y){x = y;};
}

void main()
{
    int delegate() get;    
    void delegate(int)  set;

    make(get, set);   
    
    writefln(get());
    set(123);
    writefln(get());
}


напечатает

0
123
Re[2]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.10.07 13:33
Оценка: +1
2 VoidEx.

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

Пояснил бы для разнообразия с чем ты не согласен?

А то итераторов среди дотнетных языков нигде кроме C# 2+ и Немерле вроде нет. И C++ тут не исключение.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: C++/CLI умеет все
От: VoidEx  
Дата: 02.11.07 16:02
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Понимаешь ли в чем дело. Оценки — это такой же контент сайта и тех кто засоряет его без толку тут не любят. Терпят какое-то время, а потом не не любят активно.

Я его не без толку засоряю, а выражаю свое мнение. Если мне этого делать нельзя, я не буду.
Или если за каждый минус/плюс надо обязательно отчитываться перед автором, то в правилах форума это не обнаружил

VD>А то со стороны это уже выглядит как полнейшая неадекватность. Неужели сложно объяснить свое несогласие с чем-то?

Я бы объяснял, и могу объяснить тем, кто это воспримает именно как мнение, а не как на покушение не знаю на что, с последующим спором. А уж как некоторые проводят споры, так даже перепалки "Delphi vs C++" на gamedev.ru кажется дискуссией ученых мужей.
Но в любом случае, если кому-то будет интересно, почему я согласен/не согласен, может спросить.
Re[5]: C++/CLI умеет все
От: FR  
Дата: 22.11.07 06:55
Оценка: -1
Здравствуйте, vdimas, Вы писали:


V>при условии невозможности определять в C# типы по месту — это единственный выход не превращать код в лапшу. Но опять же, писать тела алгоритмов в лямбдах — так никто не делает, лямбды чаще служат для параметризации, карринга, комбинации и т.д. уже готовых алгоритмов. А вот написание этих самых алгоритмов в C# — Большая Проблема, достаточно невозможности использования банальных арифметических операций для генериков, и огромная доля алгоритмов становятся не обощаемыми. Compile-time генерация в C++ вкупе с возможностью перегрузки операторов позволяет действительно обобщать алгоритмы, и тут без реальных замеров где и кто больше выиграл рассуждать бесполезно. Могу лишь сказать от себя, т.к. очень долго сижу на дотнете (с самого начала), в общем, если идет речь о суммарной выразительности, то C# 2.0 сильно отстаёт от C++/CLI, даже с учетом конструкций yield return и delegate { типа_полузамыкание_тута}. Не берусь судить о 3.0, ибо ещё не работал толком, да и студия еще не вышла, т.е. сравнивать рановато.


Неправильно холиварите, D все равно лучше
yield у него нет, но вместо него есть ленивые параметры, ну и замыкания (наконец то полноценные) есть.

V>Не ага. Кое-чего нет, но всё, что может C# можно сделать и в C++/CLI, некоторые конструкции требуют больше приседаний, например, замыкания в практике С++ описывают явно в виде объектов по месту вызова. Несколько лишних строк обычно, есть такое. Однако, верно обратное, C# не может многое из того, что может C++/CLI даже без учёта более общих возможностей комбинаций шаблонов и генериков, речь об возможностях самой платформы.


Не замыкания плюс auto очень удобно, я на D по мелочи пописываю, сильно местами жизнь облегчает.
Re[6]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 11:31
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

На самом деле ситуация такова. На VS2005 мы перешли сразу как только она вышла. Генерики, delegate{} и yield попользовали вволю и остались весьма и весьма довольны... в сравнении с .Net 1.x. Но вот недавно пришлось вплотную поработать в C++/CLI и я пожалел, что потерял эти 3 года. Для managed классов С++/CLI генерит обычный byte-код, и рефлектором его можно посмотреть в режиме декомпиляции для синтаксиса C#, например. Т.е. по-сути, это еще один язык программирования для .Net, как C# или VB.Net. Но вот возможность описать тип, который будет одновременно и генерик и compile-time шаблон — это бомба, которая даёт выигрыш в выразительности куда как больше, чем все yield и delegate {} вместе взятые, благо я на них собаку уже съел и как бы сравниваю в здравом уме и светлой памяти. Т.е. одни и те же задачи начинаешь решать просто ПО-ДРУГОМУ, получая гораздо более короткий код.

Например, возможны аспекты:
template<class TBase, class TKey, class TValue>
ref class LogAspect : public TBase {
public:
    void Add(TKey key, TValue value) new {
        Log("Add {0}, {1}", key, value);
        __super::Add(key, value);
    }
};

template<class TKey, class TValue>
ref class LoggedDictionary : LogAspect<Dictionary<TKey, TValue>, TKey, TValue> {};

template<class TKey, class TValue>
ref class LoggedSortedList : LogAspect<SortedList<TKey, TValue>, TKey, TValue> {};


Так же можно декомпозировать код на traits и properties (!!!), и нудная имплиментация интерфейсов (sic!) превращается в детскую забаву по комбинированию в декларативном стиле этих traits, properties и аспектов. Короче, обычная сипипишная compile-time кодогенерация, но уже для безопасной и мощной платформы. Вот где реальный приличный выигрыш в выразительности и строках кода, который для меня затмевает периодический выигрыш от yield return. Хотя... жаль конечно, что не добавили и эту фичу в язык, добавили же for each, вокруг которого, помнится, тоже было сломано немало копий по выходу C#.
Re[8]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 12:02
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

V>>Сдается мне, что эта конструкция была создана так же ради экономии спичек, т.е. 2-3 строки целевого кода, при условии многократной задачи на маппинг списков (многократной не по вызову, а по разнообразию, ниже у тебя огрешность в логике по этому моменту).

S>Тут налицо какое-то непонимание.

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

S>yield return сам по себе используется действительно редко (хотя у нас есть в проекте пара мест, где yield return используется именно в прикладном коде).

S>Зато он позволяет строить ленивые вычисления.
S>То, что кто-то пользуется энергичными — флаг в руки. Когда стукнутся лбом в Peak RAM Consumption, станет понятно, чем ленивые алгоритмы лучше жадных.

Вообще-то, ленивые вычисления прекрасно строятся и без yield return, т.е. камень преткновения не в этом. Для меня польза yield return состоит именно в возможности трансформации автоматной природы алгоритма в императивную. А те случаи, которые банальным образом можно свести к копированию кода в MoveNext() меня не интересуют, ибо для этих случаев yield return лишь сахарок, который и обсуждать-то несколько несерьезно. Например, приведённый здесь пример http://www.rsdn.ru/forum/message/2707527.1.aspx
Автор: Klapaucius
Дата: 26.10.07
приводим к MoveNext() тривиальным образом, и потому неинтересен.


S>Причем, что характерно, конструкции уровня foreach/yield return являются высокоуровневыми, и конкретный код, в который они компилируются, не специфицирован. Это открывает простор по доработке компилятора/JIT для оптимизации именно потоковых вычислений.


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

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


Дудки, в общем случае невозможно, но это тема для отдельного серьезного разговора. Просто намекну, что для случаев yield return внутри foreach автомат может оперировать сколь-угодно сложным итератором (и кстати, необязательно наследником IEnumerator, если помнишь). К тому же встаёт обычная проблема видимости и локальности ссылок. Ты же не знаешь, каким образом этот итератор получается внутри метода GetEnumerator(), логично? Может на него есть куча ссылок извне и им тоже параллельно управляют, не обязательно из другого потока, может где-то в недрах вызываемых методов прямо по ходу алгоритма. А значит некую ссылочную сущность-итератор нельзя "полностью" заинлайнить, перенеся на стек его состояние. Ты наверно намёкал на то, что нечто похожее удалось решить для концевой рекурсии? Но там для этих дел есть детерминированный мат-аппарат для определения возможности трансформации рекурсивных состояний в "плоские", ибо размерность задачи там — конечная. А твоя постановка в общем случае имеет бесконечную размерность.
Re[8]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 12:53
Оценка: :)
Здравствуйте, FR, Вы писали:

import std.stdio;

void  make(ref int delegate() get, ref void delegate(int)  set)
{    
    int x = 0;
    
    get = {return x;};
    set = (int y){x = y;};
}


Синтаксис руль, без вопросов.
C++/CLI умеет все
От: vdimas Россия  
Дата: 25.10.07 14:43
Оценка:
Здравствуйте, VladD2, Вы писали:

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


FR>>Странно как ты мог раньше восхищаться таким убогим и не сделанным на четких научных принципах C#?


VD>Он был лучше С++ и остается лучше Ди во многом. Так что не странно, что пока на горизонте не было чего-то более стоящего (по совокупности причин) Шарп был моим фаворитом.


С++/CLR умеет всё, что умеет C#, и еще в несколько раз больше.

04.05.08 15:34: Ветка выделена из темы Ой, чо с D деется-то!?
Автор: eao197
Дата: 16.11.06
— AndrewVK
Re: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.10.07 13:17
Оценка:
Здравствуйте, vdimas, Вы писали:

V>С++/CLR умеет всё, что умеет C#, и еще в несколько раз больше.


Ну, изобрази ради хохмы итераторы из второго Шарпа. Про ЛИНК я вообще молчу.

А вообще, С++/CLI хорошо показал, что можно уметь почти все, но при этом угребищем.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: C++/CLI умеет все
От: VoidEx  
Дата: 26.10.07 14:55
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>2 VoidEx.


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

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

VD>Пояснил бы для разнообразия с чем ты не согласен?

С мнением
— Да не согласен я...
— С кем? С Марксом или с Кауцким?
— Да с обоими...
Я, пардон, не туда ткнул просто
Re[4]: C++/CLI умеет все
От: Константин Л. Франция  
Дата: 29.10.07 16:18
Оценка:
Здравствуйте, VoidEx, Вы писали:

[]

VD>>Пояснил бы для разнообразия с чем ты не согласен?

VE>С мнением
VE>- Да не согласен я...
VE>- С кем? С Марксом или с Кауцким?
VE>- Да с обоими...

Там вроде Ленин был

VE>Я, пардон, не туда ткнул просто
Re[4]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.10.07 18:00
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Я еще и плюсы рассыпаю, а объяснять всем подряд, почему я согласен с тем или иным мнением, не особо считаю нужным, особенно если об этом не просят.

VE>А еще забавно наблюдать, как некоторые взрослые люди из-за плюсов-минусов волнуются, как дети от оценок

Понимаешь ли в чем дело. Оценки — это такой же контент сайта и тех кто засоряет его без толку тут не любят. Терпят какое-то время, а потом не не любят активно.

VE>Я, пардон, не туда ткнул просто


Вот так надо было и сказать, а Булгакова цитировать.
А то со стороны это уже выглядит как полнейшая неадекватность. Неужели сложно объяснить свое несогласие с чем-то?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: C++/CLI умеет все
От: no4  
Дата: 14.11.07 08:05
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, VoidEx, Вы писали:


КЛ>[]


VD>>>Пояснил бы для разнообразия с чем ты не согласен?

VE>>С мнением
VE>>- Да не согласен я...
VE>>- С кем? С Марксом или с Кауцким?
VE>>- Да с обоими...

КЛ> Там вроде Ленин был


Энгельсь
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: C++/CLI умеет все
От: FR  
Дата: 22.11.07 06:45
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Смешно, однако. Сколько строчек с yield return в твоём текущем проекте? Сколько всего строчек в проекте? В сотнях тысяч строк сэкономили всего несколько сотен на yield return, но просрали около четверти от общего объема из-за ограниченых возможностей генериков... Я когда-то делал мини-систему обработки сигналов на дотнете, так запарился со всей этой выразительностью копипейстить, плюнул и сделал на обычном С++ в несколько раз короче. Очень сожалею, что не сразу обратил внимание на C++/CLI, мне бы это сэкономило еще половину времени (т.к. к выразительности кодогенерации добавилась бы моща фреймворка )


В питоне с помощью yield (правда он помощнее шарповского) красиво делается много вещей, то же программирование на итераторах — генераторах по выразительности мало уступает функциональщине.
Re[6]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 09:28
Оценка:
Здравствуйте, FR, Вы писали:

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


V>>Смешно, однако. Сколько строчек с yield return в твоём текущем проекте? Сколько всего строчек в проекте?


FR>В питоне с помощью yield (правда он помощнее шарповского) красиво делается много вещей, то же программирование на итераторах — генераторах по выразительности мало уступает функциональщине.


Охотно верю, но коль пошло сравнение выразительности именно шарпа, то интересует голая статистика по выделенному.
Re[6]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 10:12
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Я — не позволю. Неважно, что там под ним "сидит". Пользователи этим никак не пользуются.

...
S>Поэтому совершенно неважно, кто кого наследует.
S>Важно количество foreach по сравнению с [].

Э-э-э-э... Конструкция for each() есть в новом C++ так же (вот так и пишется с пробелом и имеeт ровно такую же семантику как в C#), зацепка пошла не об foreach, а об yield return. А вернее — о том, как данные собсно обрабатываются. Я именно и уверен, что на C# данные в подавляющем большинстве случаев обрабатываются в "энергичном" варианте, например в том же цикле foreach, или вызываются групповые операции в контейнерах. Для С++/CLI, если речь не идёт именно об IEnumerable, то приведенный пример вырождается в одну строку вызова стандартной ф-ии transform (помнишь еще С++ немного?), которая производит энергичную обработку данных через итераторы.


V>>При чём тут виртуальные ф-ии? В обоих случаях мы имеем виртуальные ф-ии, не суть. Принципиальное отличие ICollection — в св-ве Count, что позволяет избегать Log2(N) перераспределений памяти, имелась ввиду именно эта эффективность.

S>Принципиальное отличие yield return — в том, что можно вообще избегать выделений памяти. Имеется в виду именно эта эффективность.

S>Спички экономим? Один виртуальный вызов на фоне миллионов вызовов MoveNext?


Но ведь всё-равно 2 вызова делегата друг в друге в каждом MoveNext.

Сдается мне, что эта конструкция была создана так же ради экономии спичек, т.е. 2-3 строки целевого кода, при условии многократной задачи на маппинг списков (многократной не по вызову, а по разнообразию, ниже у тебя огрешность в логике по этому моменту).

V>>при условии невозможности определять в C# типы по месту — это единственный выход не превращать код в лапшу. Но опять же, писать тела алгоритмов в лямбдах — так никто не делает, лямбды чаще служат для параметризации, карринга, комбинации и т.д. уже готовых алгоритмов.

S>Почему это не делает? Еще как делает.

В C# 2.0? Можно код в студию, где алгоритм целиком на этих полу-лямбдах был бы реализован? А то половина реальных применений, которые я видел — это Invoke в GUI-тред в Windows.Forms, половина от оставшихся — маленькие хендлеры событий (которые почти все не являются строго замыканиями де-факто, т.к. обычно не захватывают окружение, довольствуются параметрами события, т.е. просто являются синтаксическим сахарком, и даже в рефлекторе видно, что скомпилированы в анонимные методы, а не лямбды), более половины от оставшегося — непоcредственно лямбды, подаваемые в групповые методы Array и List<T> или в свои похожие, собс-но об этой доле я и говорил, коль речь про лямбды, вернее про то, как её де-факто юзают в C#. К тому же, я сталкивался с какими-то побочными эффектами, когда была некая переменная цикла, и она входила в порождаемые в цикле замыкания, поэтому считаю конструкцию delegate {} полу-лямбдой.

V>>Смешно, однако. Сколько строчек с yield return в твоём текущем проекте?

S>Строчек — немного, поскольку они в основном расположены в хэлперном классе. Зато используются они очень интенсивно.

Ну теперь прочти еще раз, что написал.
У меня точно так же, в основном в хелперных низкоуровневых классах они сидят, и реально таких строчек во всём огромном проекте — пару десятков, и эти классы очень интенсивно используются. Но факт в том, что в проекте длинною почти в год, этот yield return сэкономил мне гораздо менее 1-го рабочего дня. А если внимательно пройтись даже по этим несчастным двум десятков yield, то заметно, что более половины из них были чисто ради "красного словца" или синтакцсического сахарка, а не исходила из реальных требований автоматной природы целевого алгоритма. Вот тебе и цена восхваляемой "выразительности": 1/360=0.27% положительного эффекта.
Re[6]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 10:35
Оценка:
Здравствуйте, FR, Вы писали:

FR>Неправильно холиварите, D все равно лучше

FR>yield у него нет, но вместо него есть ленивые параметры, ну и замыкания (наконец то полноценные) есть.

yield на самом деле штука очень мощная, жаль что нет его в D. Хотя, правда в том, что за последние 3 года мощща этого yield по-настоящему пригодилась пару раз всего, остальные случаи были тривиальны, и не сильно отличались бы в исполнении от MoveNext().

V>>Не ага. Кое-чего нет, но всё, что может C# можно сделать и в C++/CLI, некоторые конструкции требуют больше приседаний, например, замыкания в практике С++ описывают явно в виде объектов по месту вызова. Несколько лишних строк обычно, есть такое. Однако, верно обратное, C# не может многое из того, что может C++/CLI даже без учёта более общих возможностей комбинаций шаблонов и генериков, речь об возможностях самой платформы.


FR>Не замыкания плюс auto очень удобно, я на D по мелочи пописываю, сильно местами жизнь облегчает.


Зато в С++, ввиду ручной эмуляции замыканий, ты можешь вручную же разруливать одну из проблем замыканий — степени устойчивости данных.
Сейчас поясню:
void SomeMethod() {
  int a, b;
  ...
  struct {
    int a, &b;
    lambda(int a, int &b) : a(a), b(b) {}
    // весь огород ради operator()
    int operator()(int x) { return SomeCalculation(a, b, x); }
  } lambda(a, b);
  
  someContainer.SomeGroupOperation(lambda);
  a++; b++;
  someContainer.SomeGroupOperation(lambda);
  ...
}


Вот обрати внимание, что в эмулируемом замыкании одна переменная хранится по-значению, другая по ссылке. Когда-то я был ошарашен тем, что разные реализации LISP и Scheme используют разную степень фиксации, в терминах С++ некоторые по ссылке, а некоторые по-значению, отсюда некоторые алгоритмы работают совершенно по-разному в разных реализациях. И это в прородителях всех существующих замыканий.

Кстати, а как фиксируются данные в замыканиях D?
Re[7]: C++/CLI умеет все
От: Sinclair Россия https://github.com/evilguest/
Дата: 22.11.07 11:10
Оценка:
Здравствуйте, vdimas, Вы писали:
V>Сдается мне, что эта конструкция была создана так же ради экономии спичек, т.е. 2-3 строки целевого кода, при условии многократной задачи на маппинг списков (многократной не по вызову, а по разнообразию, ниже у тебя огрешность в логике по этому моменту).
Тут налицо какое-то непонимание.
yield return сам по себе используется действительно редко (хотя у нас есть в проекте пара мест, где yield return используется именно в прикладном коде).
Зато он позволяет строить ленивые вычисления.
То, что кто-то пользуется энергичными — флаг в руки. Когда стукнутся лбом в Peak RAM Consumption, станет понятно, чем ленивые алгоритмы лучше жадных.


Причем, что характерно, конструкции уровня foreach/yield return являются высокоуровневыми, и конкретный код, в который они компилируются, не специфицирован. Это открывает простор по доработке компилятора/JIT для оптимизации именно потоковых вычислений. Поэтому все эти рассуждения про "ой, там же два вызова делегата" не слишком-то важны. Даже на втором фреймворке можно написать библиотечку, которая будет инлайнить цепочку ленивых трансформаций в единый код по месту использования. На коротких последовательностях это неважно, а вот на длинных потоках даст большой выишрыш (примерно как компиляция RegEx).
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 11:58
Оценка:
Здравствуйте, vdimas, Вы писали:

V>В C# 2.0? Можно код в студию, где алгоритм целиком на этих полу-лямбдах был бы реализован?


Целиком, не цликом, а вот здесь есть кое что.

Еще раз повторюсь, что применение фич типа итераторов и лябд упирается не в их возможности, а скорее в знания людей их использующих. Пописав на Немерле пол годика, я начал использовать лямбды на право и на лево. Когда сожусь за Шарп, то тоже все время тянет их исползовать.

Единственное с чем соглашусь — это с тем, что синтаксис анонимных методов в C# 2.0 уродлив и избыточен. Надеюсь, что в таки вышедшем на днях C# 3.0 лямбды будут использоваться чаще, так как с одной стороны их синтаксис стал почти идеальным, а с другой ЛИНК будет стимулировать их использование и многие проникнутся ими.

V> А то половина реальных применений, которые я видел — это Invoke в GUI-тред в Windows.Forms, половина от оставшихся — маленькие хендлеры событий...


Ну, а я видел море С++-ного индокода в котором вообще от С++ было меньше чем КПК по отношению к первым ЭВМ. И что?

Фичи есть в Шарпе и нет в С++. Они безсомнения полезны и мощьны. Так что говорить, что С++ умеет все что умеет Шарп значит лукавить. О чем тут идет спор?

V>У меня точно так же, в основном в хелперных низкоуровневых классах они сидят, и реально таких строчек во всём огромном проекте — пару десятков, и эти классы очень интенсивно используются. Но факт в том, что в проекте длинною почти в год, этот yield return сэкономил мне гораздо менее 1-го рабочего дня.


Ну, значит ты так умешь его применять. Я вот на одном только его применении сэкономил себе тучу времени (неделю где-то). Выписывать конечные автоматы ручками я бы не стал.

V> А если внимательно пройтись даже по этим несчастным двум десятков yield, то заметно, что более половины из них были чисто ради "красного словца" или синтакцсического сахарка, а не исходила из реальных требований автоматной природы целевого алгоритма. Вот тебе и цена восхваляемой "выразительности": 1/360=0.27% положительного эффекта.


Ага. Я как на С++-ный проект не погляжу, так сразу вижу, что в нем все так здорово и гладко. Почти без оверхэда. А на практике Шарповский код оказывается минимум в 3 раза короче, а это значит, что экономия времени минимум троекратная. А учитывая, что код чаще читается, то зависимость получается не линейная.

Пописав же на языках типа Немерле или Скала возвращаться к С++ нет никакого желания. C# 3.0 подкупает хотя бы ЛИНК-ом. А С++? Даже в 0х ничего подобного не появится.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 12:27
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Ну, изобрази ради хохмы итераторы из второго Шарпа.


Какие именно итераторы интересуют?

List<String^> list;
list.Add("one");
list.Add("two");
for each(String^ item in list)
  Console::WriteLine(item);

vector<String^> vec;
vec.push_back("one");
vec.push_back("two");
for each(String^ item in vec)
  Console::WriteLine(item);

// C++ way
for_each(vec.begin(), vec.end(), Console::WriteLine);
Re[8]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 12:43
Оценка:
Здравствуйте, VladD2, Вы писали:

V>>В C# 2.0? Можно код в студию, где алгоритм целиком на этих полу-лямбдах был бы реализован?


VD>Целиком, не цликом, а вот здесь есть кое что.


Собсно, что я и говорил:
    int index = FindIndex(lineToks,
        delegate(ScanTokenInfo x)
        { return x.Token.Location.Contains(startLine, startCol); });


V>>при условии невозможности определять в C# типы по месту — это единственный выход не превращать код в лапшу. Но опять же, писать тела алгоритмов в лямбдах — так никто не делает, лямбды чаще служат для параметризации, карринга, комбинации и т.д. уже готовых алгоритмов.



VD>Еще раз повторюсь, что применение фич типа итераторов и лябд упирается не в их возможности, а скорее в знания людей их использующих. Пописав на Немерле пол годика, я начал использовать лямбды на право и на лево. Когда сожусь за Шарп, то тоже все время тянет их исползовать.


Например вот так:
        private static Predicate<Token> GetMatchBracePredicate(Token token)
        {
            if (token is Token.BeginBrace)
                return delegate(Token t) { return t is Token.BeginBrace; };
            if (token is Token.BeginQuote)
                return delegate(Token t) { return t is Token.BeginQuote; };
            if (token is Token.BeginRound)
                return delegate(Token t) { return t is Token.BeginRound; };
            if (token is Token.BeginSquare)
                return delegate(Token t) { return t is Token.BeginSquare; };
        ...



VD>Ага. Я как на С++-ный проект не погляжу, так сразу вижу, что в нем все так здорово и гладко. Почти без оверхэда. А на практике Шарповский код оказывается минимум в 3 раза короче, а это значит, что экономия времени минимум троекратная. А учитывая, что код чаще читается, то зависимость получается не линейная.


Я говорил не о просто С++, а о С++/CLI. Шарповский код короче обычного С++ кода по причине взаимодействия с мощной платформой. Для С++/CLI этого преимущества нет.

VD>Пописав же на языках типа Немерле или Скала возвращаться к С++ нет никакого желания. C# 3.0 подкупает хотя бы ЛИНК-ом. А С++? Даже в 0х ничего подобного не появится.


Для нового С++/CLI есть ЛИНК.
Re[3]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 13:06
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Какие именно итераторы интересуют?


Те что в спецификации C# 2.0 описаны. Ты о них тут долго спорил и утверждал, что они как-бы никому не нужны.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 13:06
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Так же можно декомпозировать код на traits и properties (!!!), и нудная имплиментация интерфейсов (sic!) превращается в детскую забаву по комбинированию в декларативном стиле этих traits, properties и аспектов. Короче, обычная сипипишная compile-time кодогенерация, но уже для безопасной и мощной платформы. Вот где реальный приличный выигрыш в выразительности и строках кода, который для меня затмевает периодический выигрыш от yield return.


Держите меня семеро.
Если вам нужна кодогенерация и действительно удобный язык, то про С++ нужно забыть как про смертный грех и срочно бежать сюда.

V>Хотя... жаль конечно, что не добавили и эту фичу в язык, добавили же for each, вокруг которого, помнится, тоже было сломано немало копий по выходу C#.


Вот вот. Тут вообще-то кроме тебя никто и не завлял, что C++ < C#. Это ты утверждал, что C++ > C#.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 13:14
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Особо интересен вот этот фалик: NemerleLanguageService.cs. Там на yield реализована (причем очень прозрачно) логика с которой иначе пришлось бы помучиться.


Угу, 3 вложенных состояния. Влад, но давай серьезно, за 2 часа максимум эту логику можно переделать без всяких yield на явных состояниях (для того кто первый раз видит весь этот код, для меня, например). А учитывая крайнюю редкость подобных задач в суммарном объеме кода, я и позволил себе участие в этом топике со своим поинтом, собсно.

По сути, начинать мне надо было этим: http://www.rsdn.ru/forum/message/2738741.aspx
Автор: vdimas
Дата: 22.11.07

Всё остальное сказанное мною — вода вокруг сказанного там. (Ты там улыбнулся наверно с высоты своего Nemerle? Ну а мы, презренные, с низов своих коммерческих проектов должны выбирать 100%-но готовые для применения тулзы, такие дела).

VD>Главено понять, что yield дает не только отложенное выполнение, но и инверсию исполнения.


Это все поняли еще 3 года назад, я лишь позволил себе заметить, что вкупе с редким использованием yield симим по себе, еще более редко он используется для реализации автоматов (инверсии в твоей терминологии), а по большей частью просто как сахар, чтобы самому не писать наследников IEnumerator и метод MoveNext().

VD>Многие алгоритмы становятся плоскими и очевидными с применением yield, когда как без него они получаются запутанными.


Угу, быстро разобраться в автоматном алгоритме может далеко не каждый, согласен.

VD>Использование итераторов (по сути ограниченных континюэшонов) ограничивается скорее не их особенностями, а умением их применять. Многие люди просто не способны отойти от мышления массивами и коллекциями.


Может быть и многие, хотя из моей команды суть yield разработчки схватили сразу после объяснения и пары примеров.
Re[8]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 14:39
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>Держите меня семеро.

VD>Если вам нужна кодогенерация и действительно удобный язык, то про С++ нужно забыть как про смертный грех и срочно бежать сюда.

А напомни плиз, в Nemerle есть аналог yield return?


VD>Вот вот. Тут вообще-то кроме тебя никто и не завлял, что C++ < C#. Это ты утверждал, что C++ > C#.


Я вообще-то подробно перечислил чего он может такого, что не может C#, и в основном это касается платформы CLR, а не фич языка.
Re[9]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 14:49
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Например вот так:

V>
V>        private static Predicate<Token> GetMatchBracePredicate(Token token)
V>        {
V>            if (token is Token.BeginBrace)
V>                return delegate(Token t) { return t is Token.BeginBrace; };
V>            if (token is Token.BeginQuote)
V>                return delegate(Token t) { return t is Token.BeginQuote; };
V>            if (token is Token.BeginRound)
V>                return delegate(Token t) { return t is Token.BeginRound; };
V>            if (token is Token.BeginSquare)
V>                return delegate(Token t) { return t is Token.BeginSquare; };
V>        ...
V>

V>

И что тебе тут не рнавится? Не привык к подобному?

V>Для нового С++/CLI есть ЛИНК.


Серьзно? И как же им воспользоваться?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 15:30
Оценка:
Здравствуйте, vdimas, Вы писали:

V>А напомни плиз, в Nemerle есть аналог yield return?


Ага. Не певеришь... называется yield.

V>Я вообще-то подробно перечислил чего он может такого, что не может C#, и в основном это касается платформы CLR, а не фич языка.


Тебе, между прочем, тоже показали, что С++ не может, что может C#.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 15:30
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Угу, 3 вложенных состояния. Влад, но давай серьезно, за 2 часа максимум эту логику можно переделать без всяких yield на явных состояниях (для того кто первый раз видит весь этот код, для меня, например). А учитывая крайнюю редкость подобных задач в суммарном объеме кода, я и позволил себе участие в этом топике со своим поинтом, собсно.


Ага. Давай серьезно. Я убил на эту реализацию где-то 2 часа. Причем это от замысла, до работающего кода. Потом IT там одну мелкую ошибку пофиксил.

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

V>Это все поняли еще 3 года назад, я лишь позволил себе заметить, что вкупе с редким использованием yield симим по себе, еще более редко он используется для реализации автоматов (инверсии в твоей терминологии), а по большей частью просто как сахар, чтобы самому не писать наследников IEnumerator и метод MoveNext().


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

V>Угу, быстро разобраться в автоматном алгоритме может далеко не каждый, согласен.


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

V>Может быть и многие, хотя из моей команды суть yield разработчки схватили сразу после объяснения и пары примеров.


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

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

Ну, вот сраври ту же задачу поиска скобок. Думаю, что многие увидив автомат сразу бы бросли в нем разбираться, так как предствить себе многомирую картину ДКА не так то просто. Он выглядит как шаманство с состояниями. А прочесть мой код они могут очень даже легко.

Однако когда речь заходит о проектировании, то большинству будет проще спроектирвоать автомат (если они знакомы с теорией) или вообще написать все влоб. А вот переключить свой мозг в режим мышления списками им будет не просто. А меж тем все просто. Наша задача получить список токенов, перебрать его подсчитывая вложенность собко и найти ответную с той же вложенностью. Просто сбросить токены в List<Token> не эффективно и черевато тем, что Token возвращемый лексером (в данной реализации) переписывается (меняется состояние одного токена). Городить автомат? На С++ другого выхода нет. На C#/Nemerle мы просто описываем алгоритм генерации линивого списка токенов в виде итератора и далее пользуемся этим итератором точно так же как если бы он был материализованным в List<Token>.

Откровенно говоря на Немерле я бы написал этот код еще проще и красивее. Но к сожалению мне пришлось бы слишком много тащить в другой проект. Так что я счет, что и средств Шарпа хватит.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 15:57
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>И что тебе тут не рнавится? Не привык к подобному?


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

Вариант 1:
        static Predicate<Token> CheckTocken<T>()
        {
            return delegate(Token t) { return t is T; };
        }
        
        // кеш делегатов
        private static Predicate<Token>
            _checkBeginBrace = CheckTocken<Token.BeginBrace>(),
            _checkBeginQuote = CheckTocken<Token.BeginQuote>();


Но по логике токен сам в состоянии проверить тип на выводимость из своего, поэтому
Вариант 2:
    class Token
    {
        public abstract Predicate<Token> CheckType { get; }

        public class TokenImpl<T> : Token
        {
            public static readonly Predicate<Token> s_check =
                delegate(Token token) { return token is T; };

           public override Predicate<Token> CheckType { get { return s_check; } }
        }

        public class BeginBrace : TokenImpl<BeginBrace> { }
        public class BeginQuote : TokenImpl<BeginQuote> { }
    }

...

    private static Predicate<Token> GetMatchBracePredicate(Token token)
    {
        if (token is Token.BeginBrace || 
            token is Token.BeginQuote || ... ) 
            return token.CheckType;
        ...
    }



V>>Для нового С++/CLI есть ЛИНК.


VD>Серьзно? И как же им воспользоваться?


А ты думаешь я прикалываюсь? Это я в MSDN от VS2008 прочел, надеюсь у тебя он есть. Синтаксис там, конечно, не столь прикольный как для C# 3.0, тем не менее...
Re[10]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 16:05
Оценка:
Здравствуйте, VladD2, Вы писали:

V>>А напомни плиз, в Nemerle есть аналог yield return?


VD>Ага. Не певеришь... называется yield.


повезло

V>>Я вообще-то подробно перечислил чего он может такого, что не может C#, и в основном это касается платформы CLR, а не фич языка.


VD>Тебе, между прочем, тоже показали, что С++ не может, что может C#.


Ну тогда сформулирую прямо: С++/CLI может всё что C#, но некоторые вещи за счёт оверхеда и приседаний. C# в свою очередь не имеет доступа ко всем возможностям CLR, в отличие от C++/CLR. Так пойдёт?
Re[10]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 16:21
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Просто думать об алгоритме как о чем-то что можно тупо прервать в любой точке и продложить с того же места уже не просто.


А как же многопоточное ПО?

Кстати да, напомнило, есть же еще технология фиберов. Небольшое (одноразовое) приседание для С++ для достижение аналогичного эффекта общающихся процессов в рамках одного потока. Блокирующий канал связи сделать с интерфейсом IEnumerator и вуа ля.

VD>Однако когда речь заходит о проектировании, то большинству будет проще спроектирвоать автомат (если они знакомы с теорией) или вообще написать все влоб. А вот переключить свой мозг в режим мышления списками им будет не просто.


Для ленивых вычислений это скорее думать процессами, а не списками. IEnumerator в данном случае — канал связи, stream, связывающий два независимых процесса. И почему ты считаешь, что другим разработчикам трудно думать в подобной манере?
Re[11]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 16:32
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Ну тогда сформулирую прямо: С++/CLI может всё что C#, но некоторые вещи за счёт оверхеда и приседаний.


Ну тогда сформулирую прямо: ассемблер может всё что С++, но некоторые вещи за счёт оверхеда и приседаний.

... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: C++/CLI умеет все
От: Klapaucius  
Дата: 22.11.07 16:52
Оценка:
Здравствуйте, FR, Вы писали:

FR>В питоне с помощью yield (правда он помощнее шарповского) красиво делается много вещей


Можно подробнее про выделенное? Желательно с примерами.
... << RSDN@Home 1.2.0 alpha rev. 726>>
'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[5]: C++/CLI умеет все
От: Klapaucius  
Дата: 22.11.07 16:52
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Возьми рефлектор и подсчитай кол-во наследников IEnumerable<T> и IEnumerable в публичных классах фреймворка, которые при этом не реализуют ICollection?. Там всего десяток (ДЕСЯТОК!!!) таких классов на 16 загруженных в рефлектор основных фреймворковых либ со многими тысячами классов.


А библиотеки FW 2 вообще очень слабо заточены под программирование с использованием итераторов и лямбд. Но даже это особенно не мешает получать преимущество от их использования.

V>Ну а теперь открой наследников ICollection (ICollection<T>)...


В библиотеках FW2 вообще много странностей — вроде всяких GetDirectories, которые возвращают массив строк. Зачем на них равняться?

V>Всё ясно, малость поторопился отвечать, не вникнув в сказанное и не проверив лично...


Самокритично.

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


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

V>Для таких обычных сценариев просто пишут i=i+1 (или i=func(i) в том месте, где данные обрабатываются, а не тот наворот что ты представил вокруг банального i=i+1, и всё это с целью инжектить обработку данных в их источник.


"Наворот" был представлен в таком виде, чтобы его легче было понять — как оказалось напрасно.

V>Принципиальное отличие ICollection — в св-ве Count, что позволяет избегать Log2(N) перераспределений памяти, имелась ввиду именно эта эффективность.


Принципиальное отличие IEnumerable в том, что память можно вовсе не перераспределять.

V>Ну это же свинство городить такой огород из 2-х объектов (реально) и 2-х делегатов ради банального маппинга.


Это в языке без данных средств придется все это городить вручную. Особенности реализации к выразительности языка никакого отношения не имеют.

V>Маппинг должен выглядеть так a = map(b);


Маппинг так выглядеть не должен. Где само отображение, а?

V>В С++/CLI я могу оперировать как дотнетными делегатами, так непосредственно ф-иями, последнее увеличивает быстродействие в разы именно на алгоритмах обработки большого кол-ва данных (скажем, в области обработки сигналов).


Особенности реализации делегатов к выразительности языка не имеют отношения. В том же Nemerle в аналогичном коде никаких делегатов не будет.

K>>Это не мой пример. В моем примере inclist это функция.

V>ну и? ф-ия, полученная путём карринга, которая возвращает объект IEnumerable, у которого надо позвать еще метод, чтобы получить другой объект — непосредственно целевой итератор... А почему не сразу целевой итератор возвращается? Не издержки ли выразительности...

Не нужно притворяться, что это просто пример в концентрированной форме представляющий выразительные средства C# отсутствующие в C++ и демонстрирующие, что C# не подмножество C++. Вы высказались поспешно, с кем не бывает. Нужно иметь мужество свою ошибку признать.

V>Аналогичное (и гораздо более широко применимое в плане типов) замыкание в С++:

V>
V>template<typename T, typename IteratorT>
V>struct MapIterator : IteratorT {
V>  typedef T FuncT(IteratorT::element_type);

V>  FuncT map;
V>  MapIterator(const IteratorT& it, FuncT f) : __super(it), map(f) {}
V>  T operator*() { return map(__super::operator*()); }
V>}

V>//tempate<typename T>
V>//T Inc(T arg) { return T+1; }

V>template<typename IteratorT>
V>MapIterator<IteratorT::element_type, IteratorT> inclist(IteratorT it)
V>{ return MapIterator<IteratorT::element_type, IteratorT>(it, _1+1); } // либо раскомментировать выше и вставить "Inc" вместо "_1+1"
V>


Отличная демонстрация разницы в выразительности, спасибо, как раз то что нужно.

K>>Я так понимаю, что мы приходим к противоречию. С одной стороны, на C++ конечно можно написать то же, что и на C#, если иметь в виду полноту языка по Тьюрингу, но тогда слова "и еще в несколько раз больше" не верны. С другой стороны, если говорить о выразительности языка нельзя игнорировать итераторы

V>итераторы на любой вкус, а учитывая возможность переопределения синтаксиса — так еще и на любой синтаксис итерирования.

Строго говоря, то что в STL — вообще не итераторы. Просто их так называют.

K>> и лямбды,

V>при условии невозможности определять в C# типы по месту — это единственный выход не превращать код в лапшу.

При условии невозможности использовать нормальные полноценные лямбды с замыканиями в C++ выход не превращать код в лапшу приходиться искать где-то в другом месте.

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


Алгоритмы в C# как раз и обобщаются с помощью функций высшего порядка. Да, параметрический полиморфизм в C# кривой (в C++, впрочем, это вообще полиморфизм ad hoc, вроде перегрузки), из-за того, что нельзя делать реализации интерфейсов для типов, не изменяя их. Другими словами, классов типов нет. Но классы типов — это, вообще говоря, сахар — и можно их эмулировать передавая словарь класса через дополнительный дженерик-параметр. Я, в свое время, даже обобщенный солвер на C# написал с такой эмуляцией классов типов. Но понятно, что это извращение.

V>Compile-time генерация в C++ вкупе с возможностью перегрузки операторов позволяет действительно обобщать алгоритмы, и тут без реальных замеров где и кто больше выиграл рассуждать бесполезно.


Конечно бесполезно. Мы и не рассуждаем о том, кто и где больше выиграл — я никогда не утверждал, что в C# есть все, что есть в C++ — это Вы утверждали, что в C++ есть все, что есть в C# — а это очевидная неправда.

V>Смешно, однако. Сколько строчек с yield return в твоём текущем проекте?


89

V>Сколько всего строчек в проекте?


30K с пробелами и комментариями.

V>В сотнях тысяч строк сэкономили всего несколько сотен на yield return, но просрали около четверти от общего объема из-за ограниченых возможностей генериков...


В C++/CLI они ограничены в такой же степени.

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


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

K>>Если я, в ответ на простой вопрос, который я написал за 15 секунд, получаю пространные рассуждения о том, что это все никому не нужно,

V>В представленом виде — никому не нужно, извини. Это я тебе с позиций пользователя твоего кода.

Даже если учеть, что мой пример, как и подобает примеру — сферический конь в вакууме — утверждение о том, что ленивый map никому не нужен — достаточно смелое. Хотя конечно, тому, кто не видит смысла в ленивой обработке списков он не нужен.

K>>нужно ли это понимать так, что написать в точности то же самое на C++/CLI нельзя?

V>Мощное заявление, однако, насчёт нельзя

Это был вопрос; больше, впрочем, вопросов нет.

V>Кое-чего нет, но всё, что может C# можно сделать и в C++/CLI, некоторые конструкции требуют больше приседаний, например, замыкания в практике С++ описывают явно в виде объектов по месту вызова. Несколько лишних строк обычно, есть такое.


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

V>Вот тебе более интересная задача: есть некий серверный процесс, в нём по требованию создаётся домен и хостится некий сервис. Как всем остальным доменам процесса узнать, что сервисный домен уже существует, не пытаться создать его, и как получить MBR оного сервиса? попробуй на C#


Для меня — не интересная.
... << RSDN@Home 1.2.0 alpha rev. 726>>
'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]: C++/CLI умеет все
От: vdimas Россия  
Дата: 22.11.07 19:42
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Принципиальное отличие IEnumerable в том, что память можно вовсе не перераспределять.


И тем не менее именно это и происходит с при использовании банального DbDataReader.


K>Даже если учеть, что мой пример, как и подобает примеру — сферический конь в вакууме — утверждение о том, что ленивый map никому не нужен — достаточно смелое. Хотя конечно, тому, кто не видит смысла в ленивой обработке списков он не нужен.


Ну во-первых я уже говорил где-то в этой ветке, что ленивость алгоритма не обязательно должна строиться на итераторах, эти вещи слабо связаны м/у собой. А во-вторых, событийная модель — это ленивая модель или нет? И требует ли она больше памяти, чем ленивая (прозвучало тут мнение от Синклера)? И как в такой модели происходит маппинг без итераторов и тем не менее тоже без перераспределения памяти?

Вроде бы трансформация данных — вотчина ленивых алгоритмов, однако почему-то большей популярностью пользуются XML-парсеры, работающие по событийной модели, и я даже знаю — почему. Диспечеризация данных в случае ленивых алгоритмов должна быть внешней by design, отсюда неудобство практического использования. Т.е. имеем банальную диллему выбора — простота интерфейса или простота реализации.
Re[6]: C++/CLI умеет все
От: vdimas Россия  
Дата: 23.11.07 09:28
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


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


K>Разумеется, с точки зрения человека, который не умеет пользоваться X, мест в проекте, где требуется X равно нулю.


1. Не ты один тут путаешь ленивые вычисления как таковые с ленивыми вычислениями списков, я обратил на это внимание и потому в исходном предложении ключевое слово выделил. Везде, где объекты создаются только по требованию — это ленивость. Создали лишь часть объекта, напр. ключ и текстовое описание для отображения в списке в GUI объектов из базы данных — это тоже ленивые вычисления. Любая современная "правильная" программа сплошь ленивая. В то же самое время ленивость — не панацея, она нужна только там, где нужна (сорри за каламбур), иначе можно получить проседание эффективности без серьезных на то причин. Но это всё банальности, они утомительны но не раздражительны. Раздражает ситуация, когда кто-то относится к банальностям серьезно, провоцируя такое же отношения к ним со стороны оппонента.

2. Говорить "списки" применительно к IEnumerable — это безграмотно само по себе. В Хаскеле, например, действительно речь идет о ленивых вычисляемых списках, когда на каждый следующий порождаемый элемент ссылается предыдущий. Это фича и одновременно ограничение языка. IEnumerable в отрыве от итерируемого объекта — это просто бесконечный (в общем случае) поток данных. И если я пояснил свою позицию (надеюсь) то теперь ответь еще раз на заданный вопрос, где речь идет именно о списках, как о связанных линейных структурах данных. (массив, ArrayList, LinkedList, Queue, Stack, кастомные какие-нить, попадающие под определение "список" — пофиг).

3. У потока есть 2 конца, я ведь тебе намекнул, что ты инжектил обработку (маппинг) в источник, но ты явно не понял намёка. Вместо того, чтобы попытаться понять сказанное, ты разразился тирадой: "ах, вы не понимаете надобность ленивого маппинга". Смешно, однако. Тем не менее, напряги фантазию и представь как будет выглядеть маппинг на противоположной стороне, стороне приёмника. А потом попытайся объяснить, где мы здесь потеряли твою ленивость и что собственно не понимает оппонент.

4. Нет у C++ этого yield, и я уже наверно с десяток раз сказал здесь, что реальная мощь yield состоит в трансформации автоматных алгоритмов в императивные. Но твой пример — далёк от того, что я понимаю под "мошью" yield, т.к сводится к копированию кода в MoveNext. На С++ можно было бы сделать маппинг на стороне приёмника в одну строчку, без заморочек с промежуточными объектами и цепочек делегатов. Но даже посмотрев на в точности аналогичный твоему вариант, ты, сознательно или нет, пропустил мимо ушей замечание, что представленный пример подходящ для огромного класса типов, в отличие от твоего варианта, который оперирует только int. ИМХО, бестолково мерить выразительность отдельно взятых строчек кода в отрыве от мест применения. Следуя твоей логике, любой генерик-тип менее выразителен, чем точно такой же обычный тип, ведь при описании генерика мы потратили больше символов исходного кода, хотя бы на те же угловые скобки и декларацию ограничений.
Re[11]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.11.07 12:04
Оценка:
Здравствуйте, vdimas, Вы писали:

VD>>Просто думать об алгоритме как о чем-то что можно тупо прервать в любой точке и продложить с того же места уже не просто.


V>А как же многопоточное ПО?


А вот потому его практически никто и не пишет. Точнее то что пишут в итоге получается мало пригодным. Еденицам удается написать что-то путное.

V>Кстати да, напомнило, есть же еще технология фиберов. Небольшое (одноразовое) приседание для С++ для достижение аналогичного эффекта общающихся процессов в рамках одного потока. Блокирующий канал связи сделать с интерфейсом IEnumerator и вуа ля.


Там оверхэд такой, что ты вряд ли его захочешь поиметь. Да и это стрельба из пушки по воробъьям.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.11.07 12:04
Оценка:
Здравствуйте, palm mute, Вы писали:

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


FR>>>В питоне с помощью yield (правда он помощнее шарповского) красиво делается много вещей


K>>Можно подробнее про выделенное? Желательно с примерами.

PM>http://docs.python.org/whatsnew/pep-342.html
PM>http://www.python.org/dev/peps/pep-0342/

Если речь о возрате значений, то можно просто возвращать в итераторе ссылочный объект с изменяемыми полями.

Можно, все же более подобное объеснение приемуществ?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: C++/CLI умеет все
От: FR  
Дата: 23.11.07 13:24
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>Если речь о возрате значений, то можно просто возвращать в итераторе ссылочный объект с изменяемыми полями.


Угу и вместо замыканий тоже можно подобный же объект возвращать

VD>Можно, все же более подобное объеснение приемуществ?


Нововведения в питон 2.5 (там не только двухстороность, а что более важно полный контроль потока управления) превращают генераторы в полноценные сопрограммы.
Re[7]: C++/CLI умеет все
От: Klapaucius  
Дата: 23.11.07 13:50
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Вот момент, на который сначала не хотел отвечать, но всё же. Просто иногда задалбывает этот юношеский максимализм, проскакиваеющий даже у "ветеранов" RSDN, когда они пытаются судить об образе мышления оппонентов.


Это Вы просто не в бровь а в глаз.

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

K>>Разумеется, с точки зрения человека, который не умеет пользоваться X, мест в проекте, где требуется X равно нулю.

Непонятное обвинение в непонимании разницы между lazy и non strict, ликбез и трюизмы поскипаны.

V>2. Говорить "списки" применительно к IEnumerable — это безграмотно само по себе.


Я знаю. Соответственно, впервые о списках заговорили как раз Вы, задав риторический вопрос о том, что, дескать, где же они нужны? А на любой риторический вопрос "Много ль мест, где нужен X?" у меня ответ один "С точки зрения человека, который не умеет пользолваться X, число мест в проекте, где требуется X равно нулю". Раз уж я не говорил, что шарповские итераторы — это ленивые списки, то смысл всей этой тирады от меня ускользает — особенно если учесть, что о ленивых списках Вы же первым и заговорили. Действительно, семантика у них не lazy, а non strict — т.е. это действительно потоки.

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


Какое отношение вопрос об односвязных ленивых списках имеет к обсуждению выразительности C#? Их поддержка ни в C# ни в C++ не встроена, и, как мне кажется использование таких списков это не C# way.

V>3. У потока есть 2 конца, я ведь тебе намекнул, что ты инжектил обработку (маппинг) в источник, но ты явно не понял намёка. Вместо того, чтобы попытаться понять сказанное, ты разразился тирадой: "ах, вы не понимаете надобность ленивого маппинга". Смешно, однако. Тем не менее, напряги фантазию и представь как будет выглядеть маппинг на противоположной стороне, стороне приёмника. А потом попытайся объяснить, где мы здесь потеряли твою ленивость и что собственно не понимает оппонент.


Еще раз. Какое это имеет отношение к теме?

V>4. Нет у C++ этого yield,


Уже целых 5 слов по теме. Поразительное достижение!

V> и я уже наверно с десяток раз сказал здесь, что реальная мощь yield состоит в трансформации автоматных алгоритмов в императивные.


Да, и что?

V>Но твой пример — далёк от того, что я понимаю под "мошью" yield, т.к сводится к копированию кода в MoveNext.


Да, и что?

V>На С++ можно было бы сделать маппинг на стороне приёмника в одну строчку, без заморочек с промежуточными объектами и цепочек делегатов. Но даже посмотрев на в точности аналогичный твоему вариант,


Вовсе не аналогичный.

V>ты, сознательно или нет, пропустил мимо ушей замечание, что представленный пример подходящ для огромного класса типов, в отличие от твоего варианта, который оперирует только int. ИМХО, бестолково мерить выразительность отдельно взятых строчек кода в отрыве от мест применения.


Это не имеет отношение к теме. От моего примера требовалась только невоспроизводимость на C++. На C++ он не воспроизводиться.

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


Ваши домыслы о моей логике, мне, откровенно говоря, мало интересны.
... << RSDN@Home 1.2.0 alpha rev. 774>>
'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[7]: C++/CLI умеет все
От: Klapaucius  
Дата: 23.11.07 13:50
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Т.е. имеем банальную диллему выбора — простота интерфейса или простота реализации.


Ну да, конечно, когда нет выбора — нет и дилеммы. Банальной.
... << RSDN@Home 1.2.0 alpha rev. 774>>
'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[8]: C++/CLI умеет все
От: vdimas Россия  
Дата: 23.11.07 23:18
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Вовсе не аналогичный.


Аналогичный, посмотри еще раз. Отличие лишь в используемом типе енумератора, т.к. пример сделан для итераторов STL/CLI, но работает пример точно так же, маппинг происходит только тогда, когда кто-то пытается получить у итератора объект.
Re[11]: C++/CLI умеет все
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.11.07 14:59
Оценка:
Здравствуйте, vdimas, Вы писали:

V>А ты думаешь я прикалываюсь? Это я в MSDN от VS2008 прочел, надеюсь у тебя он есть. Синтаксис там, конечно, не столь прикольный как для C# 3.0, тем не менее...


Есть. Дай ссылку, прочту и я. А то я только извращения на кодпрожект ведел. Поддержкой — это назвать нельзя.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.