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 умеет все
От: 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: 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[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[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[3]: C++/CLI умеет все
От: VoidEx  
Дата: 26.10.07 14:55
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>2 VoidEx.


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

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

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

С мнением
— Да не согласен я...
— С кем? С Марксом или с Кауцким?
— Да с обоими...
Я, пардон, не туда ткнул просто
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[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 умеет все
От: VoidEx  
Дата: 02.11.07 16:02
Оценка: +1
Здравствуйте, VladD2, Вы писали:

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

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

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

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

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


В питоне с помощью yield (правда он помощнее шарповского) красиво делается много вещей, то же программирование на итераторах — генераторах по выразительности мало уступает функциональщине.
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[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[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>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.