LINQ как шаг к функциональному программированию
От: Чистяков Влад (VladD2) Российская Империя www.nemerle.org
Дата: 28.08.08 14:11
Оценка: 1581 (55) +2
Статья:
LINQ как шаг к функциональному программированию
Автор(ы): Чистяков Влад (VladD2)
Дата: 26.01.2009
Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
Кроме того, эта статья дает некоторое понимание того, как работает «LONQ to Object» и на каких принципах он основан.


Авторы:
Чистяков Влад (VladD2)

Аннотация:
Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
Кроме того, эта статья дает некоторое понимание того, как работает «LINQ to Object» и на каких принципах он основан.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 16.01.09 10:48
Оценка: 1 (1) +4 :))) :)
Здравствуйте, Undying, Вы писали:

U>Обычно упрощает. Человеческое мышление же заточено на оперирование типами объектов, а не экземплярами объектов. Ведь большинство существительных в человеческих языках обозначают типы (стол, человек, собака), а экземпляр обозначают только имена собственные (Петя, Шарик), которые в основном используются в хорошо знакомом контексте.


Отличная аналогия, в предложении "Собака Шарик виляет хвостом" слово собака несет избыточную информацию. Человек Петя устроился на работу .
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[2]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.01.09 18:50
Оценка: 24 (1) +2 -2 :))
Здравствуйте, elmal, Вы писали:

ЧВV>>Статья:

ЧВV>>LINQ как шаг к функциональному программированию
Автор(ы): Чистяков Влад (VladD2)
Дата: 26.01.2009
Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
Кроме того, эта статья дает некоторое понимание того, как работает «LONQ to Object» и на каких принципах он основан.

E>Кстати, хочется спросить, а почему возвращаемые значения все время присваиваются как var, в результате я о типе могу лишь догадываться (компилятор то тип знает, а вот я не знаю)? Имхо очертененно уменьшает читаемость текста. Я один такой, кто б предпочел это ключевое слово не использовать без крайней необходимости (и если б использовал, то добавлял бы префиксы или постфиксы к имени, что приходится делать в языках с динамической типизацией чтоб не огрести потом проблем)? Может мне объяснить сакральный смысл использования var везде где только можно?

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

Если вопрос тебя действительно интересует, то давай начнем с вопросов к тебе.
1. Попробуй пройтись по статье и найти все места где тип переменных не очевиден?
2. Задумывался ли ты над тем, что вывод типов есть не только для переменных объявленных с использованием var, но и при вызове методов (особенно обобщенных)? Чем, скажем вот этот код:
PrintSeq(array1.Reverse().Where((name, i) => i % 2 == 0));

лучше чем вот этоти:
var result = array1.Reverse().Where((name, i) => i % 2 == 0);
PrintSeq(result);

?
3. Почему поборники типизации переменных спокойно пишут SQL-запросы не указывая типов для возвращаемых колонок и при этом не возмущаются по поводу потери информации?

Если ты попытаешся найти ответы на эти вопросы, то скорее всего усомнишся в своем мнении.

От себя могу сказать только одно. По программировав с годик на языке программирования поддерживающем вывод типов, начинаешь относиться к аннотации типов значительно спокойнее и возвещение. Со временем приходит понимание, что главное, чтобы код был понятным тебе и окружающим. А всякие мелочи вроде аннотации типов и даже кошерность названий переменных — это все пуританство и борьба с ветряными мельницами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: LINQ как шаг к функциональному программированию
От: Cyberax Марс  
Дата: 01.09.08 02:28
Оценка: -1 :))) :))
Здравствуйте, McSim, Вы писали:

MS>Но очень огорчает большое количество орфографических ошибок в тексте.

Это чтоб сразу было видно, что Влад пишет
Sapienti sat!
Re[9]: LINQ как шаг к функциональному программированию
От: Ziggi111 Россия  
Дата: 19.01.09 13:08
Оценка: +3 :)))
Здравствуйте, Undying, Вы писали:

U>2) Переменная получена из функции по месту использования:


U>
U>SomeFunction(GetSomeClass());
U>


U>Здесь взглядом определить тип переменной нельзя, всегда нужно использовать intellisense.


Можно. Ибо как уже писали выше, если функции обзывать не как попало, то всё понятно и без intellisense. Ну если конечно функция Дай_Хлеб() не возвращает колесо_от_самолёта.
Re[7]: LINQ как шаг к функциональному программированию
От: Qbit86 Кипр
Дата: 15.01.09 12:30
Оценка: 1 (1) +3
Здравствуйте, Undying, Вы писали:

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


Вообще-то, абстракция — это отказ от несущественных деталей. И во многом благодаря абстракции читабельность улучшается.
Глаза у меня добрые, но рубашка — смирительная!
Re[11]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.01.09 07:14
Оценка: 1 (1) +1 :))
Здравствуйте, Undying, Вы писали:

U>LightSynchronizer<int> sync


А как их поиведенного кода можно узнать, что параметр типа — это именно возвращаемый тип делегата?

CRA>>Следуя вашим рассуждениям данный код должне быть написан так:

CRA>>
CRA>>delegate
CRA>>{
CRA>>     int result = modifyDeviceGridSynch.VisibleDataRegion.Height;
CRA>>     return result;
CRA>>}
CRA>>


U>Заставь дурака богу молиться, он и лоб расшибет (с) народная мудрость


Не знаю как на счет дураков. Но твой код надо писать уж тогда еще прикольнее:
delegate
{
  t1 x1 = modifyDeviceGridSynch;
  t2 x2 = x1.VisibleDataRegion;
  int result = x2.Height;
  return result;
}

Потому как типы всех промежуточных значений так же не известны из контекста.
Паранойя? Однозначно! Но это ваша, сударь, паранойя.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 16.01.09 11:53
Оценка: +3 :)
Здравствуйте, Undying, Вы писали:

U>Откуда во-втором варианте можно узнать, что Шарик это собака, а не кошка?


Я пока мне не докажут обратного, я буду считать, что Шарик собака. Если я узнаю, что в моей программе кто-то назвал кошку Шариком я буду сильно ругаться, вне зависимости, указал он явно что это кошка или это вывел компилятор.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[18]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 10:00
Оценка: +3 :)
Здравствуйте, VladD2, Вы писали:

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


А еще лучше писать так, чтобы ошибку было видно и без отладчика.
лэт ми спик фром май харт
Re[2]: LINQ как шаг к функциональному программированию
От: nikov США http://www.linkedin.com/in/nikov
Дата: 15.01.09 12:07
Оценка: 14 (2) +1
Здравствуйте, elmal, Вы писали:

E>Кстати, хочется спросить, а почему возвращаемые значения все время присваиваются как var, в результате я о типе могу лишь догадываться (компилятор то тип знает, а вот я не знаю)? Имхо очертененно уменьшает читаемость текста. Я один такой, кто б предпочел это ключевое слово не использовать без крайней необходимости (и если б использовал, то добавлял бы префиксы или постфиксы к имени, что приходится делать в языках с динамической типизацией чтоб не огрести потом проблем)? Может мне объяснить сакральный смысл использования var везде где только можно?


Varification -- Using Implicitly Typed Locals
Re[2]: LINQ как шаг к функциональному программированию
От: Qbit86 Кипр
Дата: 14.01.09 21:05
Оценка: +3
Здравствуйте, elmal, Вы писали:

E>компилятор то тип знает, а вот я не знаю?


А зачем тебе его знать? Меньше будешь знать, крепче будешь спать. Пишем «var result = ...», затем где-то «result.», и вот после этой точки IDE выдаёт список методов — и этого достаточно. А что там возвращается — IEnumerable<T>, Querable<T>, SomeProxyIterator<T> — избыточная информация, она засоряет код и делает его менее устойчивым к изменениям.
Глаза у меня добрые, но рубашка — смирительная!
Re[3]: LINQ как шаг к функциональному программированию
От: elmal  
Дата: 15.01.09 07:29
Оценка: +2 -1
Здравствуйте, VladD2, Вы писали:

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

Это новое старо как мир . В языках с динамической типизацией уже лет 20 считают, что лучше var ничего нет, и не будет.

VD>Если вопрос тебя действительно интересует, то давай начнем с вопросов к тебе.

VD>1. Попробуй пройтись по статье и найти все места где тип переменных не очевиден?
Очевиден то он очевиден, но это напрягаться надо. И нет гарантии что где-то внутри цепочки вызовов тип не поменяется, более того, он меняется (дергается toString).

VD>2. Задумывался ли ты над тем, что вывод типов есть не только для переменных объявленных с использованием var, но и при вызове методов (особенно обобщенных)? Чем, скажем вот этот код:

VD>
VD>PrintSeq(array1.Reverse().Where((name, i) => i % 2 == 0));
VD>var result = array1.Reverse().Where((name, i) => i % 2 == 0);
VD>PrintSeq(result);
VD>

VD>?
Именно из соображений плохой читаемости я в основном предпочитаю второй тип записи (естественно не var, а имя типа). Пишу первым способом только что-то тривиальное, из соображений чтоб места было меньше (например частичный перенос данных из одного объекта в другой type1.setName1(type2.getName2())).

VD>3. Почему поборники типизации переменных спокойно пишут SQL-запросы не указывая типов для возвращаемых колонок и при этом не возмущаются по поводу потери информации?

А я кстати возмущаюсь, что для типов возвращаемых колонок не указывается тип, когда приходится пользоваться SQL. Именно по этому предпочитаю вместо его HQL. Но и в HQL не все хорошо, в случае с наследованием сущностей далеко не тривиально узнать кого ж я получил из запроса и могу ли я дернуть соответствующее свойство — мне очень не хватает возможности указания типа даже в HQL запросе.

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

JavaScript и VBScript пойдет? 2 года опыта достаточно? Я как раз попрограммировав на этих языках наоборот на строгую типизацию намолиться не могу.

И относительно того, что при написании все будет хорошо, студия по нажатию точка все возможные варианты скажет. Код в основном читается, а не пишется. Один раз написал, 100 раз потом прочитал. Типы я обычно помню наизусть, а вот что принимает и что возвращает функция я обычно не помню, особенно если это не ясно из функции. В случае если все аргументы var и возвращается туда же, мне придется лезть смотреть что это за функция и что она принимает. Я бы запомнил что есть такая функция неосознанно, если б все типы ее я видел, тут же я через месяц вряд ли вспомню что такая функция уже есть, где-то я ее уже вижу и напишу свой велосипед.
Re[4]: LINQ как шаг к функциональному программированию
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.01.09 08:22
Оценка: +2 -1
Здравствуйте, elmal, Вы писали:

E>И относительно того, что при написании все будет хорошо, студия по нажатию точка все возможные варианты скажет. Код в основном читается, а не пишется. Один раз написал, 100 раз потом прочитал.

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

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

Зато это помнит студия, вы же не распечатки читаете. Достаточно навести курсор и все расскажет и покажет. Кроме того перегрузка методов позволяет создавать короткие вызовы, с 2-3 очевидными параметрами, а пере передавать десятки null для необязательных параметров.

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

Вообще-то C# имеет строгую типизацию, поэтому типы параметров и возвращаемого значения всегда известны, даже если не указаны явно. И снова подсказке среды разработки помогает.

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

Это ваши особенности памяти, другим людям они несвойственны.
Чтобы не писать постоянно велосипеды надо правильно группировать функции. Во-первых собираит их в классы по функциональному назначению, во-вторых использовать extension-методы.

В одном проекте видел несколько функций валидации email, которые были в неймспейсах
<project name>.Utils
<project name>.<еще что-то>.StringUtils
<project name>.Web.Utils
И у ваех был параметр String и возвращаемое значение String, но это никому не помогло.
Re[6]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 15.01.09 12:21
Оценка: :)))
Здравствуйте, Qbit86, Вы писали:

Q>Да не надо определять глазами этот тип! По той же причине, по которой часто не надо знать конкретный тип переменной и можно работать с обобщённым интерфейсом. Функция GetSomething() возвращает Something — nuff said.


Вообще-то обобщенный интерфейс это абстракция, а любая абстракция ухудшает читабельность кода достаточно серьезно. Поэтому абстракции используют не везде, по принципу абстракция это прогрессивно и круто, а только там где остальные решения еще хуже. Если же использовать обобщенные интерфейсы и там где надо и там где не надо, то вместо читабельного кода получится редкостный ужас, куда там var'ам.
Re[2]: LINQ как шаг к функциональному программированию
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 27.01.09 05:26
Оценка: +2 -1
Здравствуйте, mrUmka, Вы писали:


U>Изложение текста должно быть "бесстрасным"


спорное утверждение
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[6]: LINQ как шаг к функциональному программированию
От: hugo Австрия  
Дата: 15.01.09 13:39
Оценка: 8 (1) +1
Здравствуйте, elmal, Вы писали:

E>Это я прекрасно знаю. Но ... код визуально выглядит очень похоже на языки с динамической типизацией. И если распечатать код чтоб почитать перед сном — без поддержки студии понимать его будет значительно сложнее.

В Erlang'е даже var нету .
На самом деле, когда читаешь код, то часто все равно какого типа переменная, ибо не важно знать ее "внутренности". Когда же дело доходит до внутренностей, то все равно приходится часто "идти" в определение типа. Просто в одном случает — это class (или подобное), а в другом — функция. Отсутствие имен типов стимулирует людей задумываться над тем, что их код должен быть читабельным и сопровождаемым.
Re[17]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 10:13
Оценка: 3 (1) -1
Здравствуйте, Ziaw, Вы писали:

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


T>>Замени "Шарик" на "Васька".


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


Ага, это все равно, что написать: "надо учиться писать код, чтобы в нём не было багов. Ставить вместо этого подпорки в виде статической типизации, автоматического управления памятью и пр. не имеет никакого смысла". С идеей, конечно, не поспоришь, но пользы от неё никакой.
лэт ми спик фром май харт
Re[10]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 16.01.09 06:44
Оценка: 1 (1) +1
Здравствуйте, Undying, Вы писали:

U>
U>new SimpleColumn("Логин").WithCharWidth(16).WithFontBold(true).WithBackColor(Color.MistyRose).WithForeColor(Color.Black).WithFrozenColumn(true);
U>

для этого придумали синтаксический сахар который еще читабельнее:
new SimpleColumn("Логин") { CharWidth = 16, FontBold = true, ...};


U>А вот такой, когда у SimpleColumn двадцать пять перегрузок конструктора практически нет:


U>
U>new SimpleColumn("Логин", 16, true, Color.MistyRose, Color.Black, true);
U>


Плохой дизайн, как минимум нарушен SRP. Вообще такие конструкторы имеют смысл только для immutable классов. В таком случае я делаю рефакторинг в:
new SimpleColumn("Логин", 
    new FontStyle(16, FontDecoration.Bold, Color.Black), 
    new BackgroundStyle(Color.Black), 
    ColumnType.Frozen);


U>Имя переменной присваивается из соображений бизнес логики и обычно никак не связано с типом переменной.

Сравни:
Link first = GetFirstLink();
// полэкрана кода
Console.WriteLine(first.Length); // здесь мы должны пробежаться глазами вверх и узнать что у нас в переменной first


var firstLink = GetFirstLink(); // здесь мы без типа знаем, что это Link
// полэкрана кода
Console.WriteLine(firstLink.Length); // здесь мы легко понимаем, что происходит даже не зная тип переменной


U>Я утверждал, что знание типов упрощает понимание кода. Я не утверждал, что знание типов дает полное понимание кода.


А я утверждаю, что зачастую усложняет. Приходится невольно думать о том, что означают все эти типы, хотя это далеко не всегда важно.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[14]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 16.01.09 11:52
Оценка: 1 (1) :)
Здравствуйте, Undying, Вы писали:

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


Это уже не Column тогда, а хранилище кучи свойств, которые он сам использовать не в состоянии. Не могу понять, для чего такое может понадобиться. Используй вместо него Dictionary или пустой наследник от него для типизации. И самое главное: зачем в нем дикие конструкторы???

U>>>Если у нас есть набор настроек, которые пользователь может выбирать произвольным образом, то подход с конструктором не работает. Даже если настроек всего лишь 10, то нужно написать всего-то штук 50 конструкторов. Это, во-первых, малость трудоемко, а, во-вторых, даже если не полениться и заюзать какую-нибудь кодогенерацию, то все равно очень плохо читаемо.


Z>>Остается понять, зачем делать такой класс immutable. Если его не делать таковым, смысл кучи конструкторов ускользает.


U>Вообще-то immutable код намного проще читать и в нем гораздо труднее сделать ошибку. Но в данном контексте это не важно, mutable класс у тебя как выглядеть будет? Так что ли?


U>
U>SimpleColumn column = new SimpleColumn("Логин");
U>column.CharWidth = 12;
U>column.BackColor = Color.MistyRose;
U>


Почти так.
SimpleColumn column = new SimpleColumn { Title = "Логин", CharWidth = 12; BackColor = Color.MistyRose };


Z>>Я не встречал ни одного маломальски универсального класса.


U>Ты не встречал классы List, object, string?


в чем универсальность-то?
List: ничуть не универсален, хранит список других объектов. Обычно характеризуется тем, что переменная названа существительным во множественном числе. Вобщем-то также называют экземпляры реализущие ICollection, IEnumerable но для понимания алгоритма это неважно.

object: экземпляры object я встречал только в качестве объектов для синхронизации. Менее универсального класса и придумать сложно.

string: абсолютно конкретный класс, хранит строку. вполне ясное и понятное предназначение.


Z>>Каждый класс предназначен для выполнения какой-то своей задачи (SRP). Хорошая практика отражать это в названии класса. Хорошая практика также называть переменную содержащую экземпляр этого класса в соответствии с задачей которую он выполняет.


U>Естественно, поэтому мы называем коллекцию linkedElements, а не linkedElementList, и соответственно вывести из названия переменной тип не можем.


Странно, а я могу: тип коллекция, если я встречу индекс — я пойму, что она индексирована. Пока не встречу, это не имеет ровно никакого значения для понимания.

U>Понять можно, но сделать это значительно сложнее.


Могу поспорить, что ты не писал и не читал код с варами. Либо качество написанного/прочтенного кода стремится к спагетти.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re: LINQ как шаг к функциональному программированию
От: McSim  
Дата: 01.09.08 01:42
Оценка: :))
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

ЧВV>LINQ как шаг к функциональному программированию
Автор(ы): Чистяков Влад (VladD2)
Дата: 26.01.2009
Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
Кроме того, эта статья дает некоторое понимание того, как работает «LONQ to Object» и на каких принципах он основан.


Здравствуйте, Влад!
Статью читал в журнале. Очень понравилась. Взял на вооружение.
Но очень огорчает большое количество орфографических ошибок в тексте.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: LINQ как шаг к функциональному программированию
От: AngeL B. Россия  
Дата: 01.09.08 03:36
Оценка: +2
Здравствуйте, Cyberax, Вы писали:

MS>>Но очень огорчает большое количество орфографических ошибок в тексте.

C>Это чтоб сразу было видно, что Влад пишет

Вместо того, чтобы писать вот такие комментарии про людей, которые для тебя статьи пишут, лучше бы предложил свои услуги по вычитке и коррекции текста.
Re[6]: LINQ как шаг к функциональному программированию
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.01.09 09:47
Оценка: -1 :)
Здравствуйте, elmal, Вы писали:

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


IB>>В языках с динамической типизацией совсем другой var. C# по прежнему статически типизирован и все типы выводятся на этапе копиляции.

IB>>Нет, не подойдет, так как там var совсем другой.
IB>>Строгая типизация никуда не делась.
E>Это я прекрасно знаю. Но ... код визуально выглядит очень похоже на языки с динамической типизацией.
Эх, что же вы бедете делать когда появится dynamic (который кстати тоже является строгим типом)?

E>И если распечатать код чтоб почитать перед сном — без поддержки студии понимать его будет значительно сложнее.

А таким кто-то занимается?
Re[2]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 15.01.09 11:25
Оценка: -2
Здравствуйте, elmal, Вы писали:

E>Кстати, хочется спросить, а почему возвращаемые значения все время присваиваются как var, в результате я о типе могу лишь догадываться (компилятор то тип знает, а вот я не знаю)? Имхо очертененно уменьшает читаемость текста. Я один такой, кто б предпочел это ключевое слово не использовать без крайней необходимости?


Не один.

E>Может мне объяснить сакральный смысл использования var везде где только можно?


Сакральный смысл заключается в экономии на спичках. 'string str;' это же целых 11 символов, а 'var str;' всего 8 символов.

Это же круто, что мы на целых 3 символа меньше записали, а читабельность кода... кому она нужна?
Re[8]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 11:49
Оценка: +2
Здравствуйте, elmal, Вы писали:

G>>А таким кто-то занимается?

E>А как-же? Простейший пример — когда задают вопрос на форуме или пишут статью, копипастят исходники, и те, кто читают, к исходникам доступа не имеют и им труднее понять получается. Когда просят отревьюить код тоже частенько бросают его в аську. А там никакой студии нет встроенной.

Можно ссылку на сообщение из форума где наличие var-ов мешало бы пониманию кода?

И еще один вопрос. А почему ты не протестуешь против перегрузки и вывода типов параметров? Они ведь точно так же скрывают информацию о типах выражений и функций.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: LINQ как шаг к функциональному программированию
От: Qbit86 Кипр
Дата: 15.01.09 12:03
Оценка: +1 :)
Здравствуйте, Undying, Вы писали:

U>Такой сильно хуже:

Q>>var c1 = GetSomething();

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

Да не надо определять глазами этот тип! По той же причине, по которой часто не надо знать конкретный тип переменной и можно работать с обобщённым интерфейсом. Функция GetSomething() возвращает Something — nuff said.
Глаза у меня добрые, но рубашка — смирительная!
Re[10]: LINQ как шаг к функциональному программированию
От: MxKazan Португалия  
Дата: 15.01.09 13:08
Оценка: +2
Здравствуйте, Undying, Вы писали:

U>Поэтому в шарпе 2.0 для определения типа полей класса приходилось пользоваться intellicence. var же вынуждает пользоваться intellicence и для определения типов локальных переменных тоже, т.е. intellicence приходиться использовать чаще.

С переходом на var я не то, что не стал чаще обращаться к IntelliSense, а совсем наоборот! Ведь порой не сразу вспомнишь, какой тип функция возвращает, надо юзать IntelliSense. Теперь я написал var и всё. Когда буду использовать переменную, список свойств и методов все-равно "выпадет" после нажатия точки. Видимо правильно написал nikov: "это дело привычки". Я сейчас спокойно часто юзаю var, никакую читабельность он не уменьшает. Скорее наоборот, повышает, убирая чехарду из типов, а если уж там generic'и так совсем щастье
Re[9]: LINQ как шаг к функциональному программированию
От: C...R...a...S...H  
Дата: 21.01.09 15:47
Оценка: +2
Здравствуйте, Undying, Вы писали:

U>
U>      if (true)
U>      {
U>        LightSynchronizer<int> sync = new LightSynchronizer<int>(this,
U>          delegate
U>          {
U>            return modifyDeviceGridSynch.VisibleDataRegion.Height;
U>          },
U>          delegate (int visibleHeight)
U>          {
U>            int rowHeight = modifyDeviceGridSynch.RowHeight;
U>            modifyDevicePanel.Height = modifyDevicePanel.Height + (rowHeight - visibleHeight);
U>          },
U>          TimeSpan.FromMilliseconds(100));
U>      }

U>      if (true)
U>      {
U>        LightSynchronizer<string> sync = new LightSynchronizer<string>(this,
U>          delegate
U>          {
U>            return Passport2.Model.GetValue(modifyDevice);
U>          },
U>          delegate(string model)
U>          {
U>            foreach (string dataType in modelBox.GetNewDataTypes(model))
U>              Passport2.StoragePeriod.SetProperty(modifyDevice, 14, dataType);
U>          });
U>      }
U>


Читал этот код и плакал
Undying доказывает что var — зло при этом сам же пишет который читать вообще не реально, НО самое интересное, что он так же скрывает типы переменных

delegate
{
    return modifyDeviceGridSynch.VisibleDataRegion.Height;
}
delegate
{
    return Passport2.Model.GetValue(modifyDevice);
}

Какой интересно тип результата?

Следуя вашим рассуждениям данный код должне быть написан так:
delegate
{
     int result = modifyDeviceGridSynch.VisibleDataRegion.Height;
     return result;
}
delegate
{
     int result = Passport2.Model.GetValue(modifyDevice);
     return result;
}
Там было написано русским по белому...
Re[10]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 22.01.09 04:44
Оценка: -2
Здравствуйте, C...R...a...S...H, Вы писали:

CRA>
    LightSynchronizer<int> sync = new LightSynchronizer<int>(this,
CRA>delegate
CRA>{
CRA>    return modifyDeviceGridSynch.VisibleDataRegion.Height;
CRA>}
CRA>

CRA>Какой интересно тип результата?

LightSynchronizer<int> sync

CRA>Следуя вашим рассуждениям данный код должне быть написан так:

CRA>
CRA>delegate
CRA>{
CRA>     int result = modifyDeviceGridSynch.VisibleDataRegion.Height;
CRA>     return result;
CRA>}
CRA>


Заставь дурака богу молиться, он и лоб расшибет (с) народная мудрость
Re[13]: LINQ как шаг к функциональному программированию
От: hugo Австрия  
Дата: 22.01.09 09:58
Оценка: -1 :)
Здравствуйте, Undying, Вы писали:

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


U>>>Объясни почему такой код по-твоему читабелен:

H>>Я НИГДЕ НЕ писал, что такой код читабелен, будь внимателен, когда отвечаешь. Теперь я уже вообще не пойму, о чем ты говоришь .

U>Я привел два варианта кода. В http://rsdn.ru/forum/message/3258359.1.aspx
Автор: hugo
Дата: 21.01.09
второй из вариантов ты поскипал, а по поводу первого варианта написал, что этот код нечитабелен. Это логично понять, как то, что второй вариант ты посчитал приемлимым. Если бы ты сразу написал, что оба варианта кода нечитабельны вопросов бы к тебе у меня не возникло.


У тебя не вопросы возникли, а телепатические умозаключения, основанные на том, что ты что-то там себе логично предположил. Не стоит мудрствовать и "читать" дальше моего ответа.
Re[19]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.01.09 08:25
Оценка: +1 :)
Здравствуйте, Ziaw, Вы писали:

Z>Кто-то спорит с пользой статической типизации, сборки мусора и пр.?


Ага. И не мало народу. Есть фанаты скриптво, есть фанаты С++. В их любимых игрушках нет этих фич, значит это вредно или на худой конец ненужно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Пример кода без порчи кодировки
От: Ziaw Россия  
Дата: 15.01.09 12:43
Оценка: 1 (1)
Здравствуйте, Undying, Вы писали:

Не вижу чем тут смогут помочь имена типов. Мое понимание нисколько не улучшится, почти наверняка даже ухудшится.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[10]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 12:55
Оценка: 1 (1)
Здравствуйте, elmal, Вы писали:

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


VD>>Можно ссылку на сообщение из форума где наличие var-ов мешало бы пониманию кода?

сvar result = ...
E>Да, я прекрасно, если заострю внимание, пойму о чем речь. Но беглым взглядом уже сложнее читать, чем IEnumerable<string> result.

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

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

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

E> В любом случае result неудачное имя для переменной. Ладно, на деле, я согласен, что если я заменю все свои аннотации типов на var я почти ничего не потеряю, так как у меня имя переменной отражает тип. И если уж будут сторонники var, я в коде не потеряюсь, при условии что переменные будут называться так, чтоб я мог понять что это такое.


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

VD>>И еще один вопрос. А почему ты не протестуешь против перегрузки и вывода типов параметров? Они ведь точно так же скрывают информацию о типах выражений и функций.

E>Причина проста. Если мне понадобится узнать как именно работает метод, мне в любом случае потребуется лезть в его код, то есть пользоваться ИДЕ.

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

Честный ответ на этот вопрос и является ключом к пониманию того почему можно жить без явных аннотаций типов.
E>Как именно он работает чаще всего знать не надо, надо чтоб у него было нормальное имя.

Именно! Но не только. Не важно не только "как работает метод", но и что это за метод. Важно только, чтобы сочетание объект.Метод(параметры) объясняли тебе что же происходит. По этому очень важны осмысленные имена методов и переменных. Если имена осмысленные и описывают (в купе) происходящее, то мы на весьма высоком уровне абстракции может определить, что же происходит. Ну, а если нам нужны детали, то одними аннотациями типов переменных не отделаешся и потребляется хорошая IDE с навигацией.

E>А вот типы данных, которыми я оперирую, мне более интересны в большинстве случаев (есть допустим переменная number — число. А числа бывают разные, комплексные, целые, беззнаковые, с фиксированной точностью, с неограниченной точностью — и про то, каким числом ты оперируешь очень полезно всегда помнить, так как есть тонкости. Если я тонкости не знаю, я могу про это забыть и допустить ошибку. Вероятность того, что я при беглом просмотре найду ошибку в чужом коде гораздо выше, если я вижу тип).


На самом деле совершенно не важно каким числом ты оперируешь. Ну, или почти никогда не важно. Ты оперируешь абстрактным числ и тебе требуется конкретный результат. Если результат достигается, то детали не важны. Если же тонкости реально важны, то никто не запрещает описать их явно. Просто не надо все доводить до крайностей.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: LINQ как шаг к функциональному программированию
От: SuhanovSergey  
Дата: 21.01.09 16:34
Оценка: 1 (1)
var result = array1.Aggregate((first, second) => first + ", " + second);

Это всё конечно изящно, но оно вылетает с исключением при пустой последовательности.
Re[15]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 10:15
Оценка: 1 (1)
Здравствуйте, Ziaw, Вы писали:

Z>Тогда шаримся в нюансах, дебажим и т.п.


Бывает ещё так, что дебажить нельзя, или бессмысленно в виду невоспроизводимости бага. Остается только одно: тупо вчитываться в код. И тогда очень жалеешь, что ты не компилятор и не можешь автоматически в уме выводить типы.
лэт ми спик фром май харт
Re[3]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.01.09 08:04
Оценка: 1 (1)
Здравствуйте, Undying, Вы писали:

U>Перегрузка Aggregate((first, second) => first + ", " + second) вообще сомнительна, лучше всегда использовать:


U>
U>array1.Aggregate("", (first, second) => first + ", " + second);
U>


U>Здесь все прозрачно и может корректно работать на любой коллекции.


Лучше говоришь? Ну, тогда попробуй свой вариант в действии. Тебя ждет сюрприз.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: LINQ как шаг к функциональному программированию
От: nikov США http://www.linkedin.com/in/nikov
Дата: 28.08.08 19:48
Оценка: +1
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

ЧВV>LINQ как шаг к функциональному программированию
Автор(ы): Чистяков Влад (VladD2)
Дата: 26.01.2009
Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
Кроме того, эта статья дает некоторое понимание того, как работает «LONQ to Object» и на каких принципах он основан.


Терминологическое уточнение: x = y это не "присвоение", а "присваивание".
Re[3]: LINQ как шаг к функциональному программированию
От: McSim  
Дата: 01.09.08 08:30
Оценка: :)
Здравствуйте, VladD2, Вы писали:

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


VD>Это довольно странно, так как статьи проходит корректуру в редакции.

VD>Огромная просьба выслать примеры ошибок на адрес mag@rsdn.ru или submit@rsdn.ru.

К сожалению с собой только диск от журнала. Мне надо посмотреть на сами страницы журнала.
Сейчас же из статьи с диска несколько цитат:
1.

Далее в запросе просто используются выражения:

where УСЛОВИЕ_ФИЛЬРАЦИИ
select ОПИСАНИЕ_ВОЗВРАЩЯЕМОГО_ЗНАЧЕНИЯ


2. Такая проблема может возникнуть, например, если вам потребуется создать собственную реализацию EqualityComparer основанную на лябде:

и т.д.

Т.е., то буква пропущена, то местами поменяны, то запятой нету.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: LINQ как шаг к функциональному программированию
От: Cyberax Марс  
Дата: 01.09.08 14:00
Оценка: :)
Здравствуйте, AngeL B., Вы писали:

C>>Это чтоб сразу было видно, что Влад пишет

AB>Вместо того, чтобы писать вот такие комментарии про людей, которые для тебя статьи пишут, лучше бы предложил свои услуги по вычитке и коррекции текста.
Я это не в упрёк Владу, его орфографические ашыпки и очепятки — уже давно неотъемлимая часть РСДН.
Sapienti sat!
Re: LINQ как шаг к функциональному программированию
От: elmal  
Дата: 14.01.09 12:15
Оценка: +1
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

ЧВV>LINQ как шаг к функциональному программированию
Автор(ы): Чистяков Влад (VladD2)
Дата: 26.01.2009
Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
Кроме того, эта статья дает некоторое понимание того, как работает «LONQ to Object» и на каких принципах он основан.

Кстати, хочется спросить, а почему возвращаемые значения все время присваиваются как var, в результате я о типе могу лишь догадываться (компилятор то тип знает, а вот я не знаю)? Имхо очертененно уменьшает читаемость текста. Я один такой, кто б предпочел это ключевое слово не использовать без крайней необходимости (и если б использовал, то добавлял бы префиксы или постфиксы к имени, что приходится делать в языках с динамической типизацией чтоб не огрести потом проблем)? Может мне объяснить сакральный смысл использования var везде где только можно?
Re[2]: LINQ как шаг к функциональному программированию
От: MxKazan Португалия  
Дата: 14.01.09 13:23
Оценка: +1
Здравствуйте, Denom, Вы писали:

D>Разве это не есть реализация однонаправленного связанного списка. Появилось кажись в версии 2.0

Нет. Там же написано "Represents a doubly linked list". Двусвязный так чтэ...
Re[5]: LINQ как шаг к функциональному программированию
От: mrozov  
Дата: 14.01.09 14:15
Оценка: :)
Здравствуйте, _FRED_, Вы писали:

_FR>Всё не так просто: а если array1 массив не строк, а каких-то объектов с переопределённым ToString?

Если бы, да кабы, до во рту росли грибы В данном конкретном случае — лучше сделать нельзя.
P.S. Я просто хотел в шуточной форме вернуть дискуссию в русло ФЯ.
Re[2]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.01.09 18:28
Оценка: +1
Здравствуйте, eao197, Вы писали:

E>Идентификатор seed при вызове func -- это ошибка или что-то другое?


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

E>PS. Из статьи можно было бы смело выкинуть, как минимум, 1/3 текста при сохранении той же информативности.


Будешь писать сам — выклинишь. А это моя статья, мой стиль и мой подход к изложению.

E>PPS. По ходу чтения сильно напрягает стиль изложения "от первого лица" с наездами на "императивных программистов".


Больше конкретики, плиз. Если какие-то места задевают, можно подумать об их замене. А так... это не критика, а наезд.

E>PPPS. Надеюсь, что 90% императивных программистов все-таки пишут так:

Надеюсь, что по прочтении этой статьи хотя бы 10% начнут писать подобный код в функциональном стиле.
Остальное — не важные детали.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 11:46
Оценка: -1
Здравствуйте, elmal, Вы писали:

E>Это я прекрасно знаю. Но ... код визуально выглядит очень похоже на языки с динамической типизацией. И если распечатать код чтоб почитать перед сном — без поддержки студии понимать его будет значительно сложнее.


Ты видимо отстал от жизни лет эдак на 30. Современные объемы кода не распечатать. Распечатать ты сможешь только одну-две функции. А в них типы будут и так очевидны так как вывод типов работает исключительно на уровне метода.

Более того писать надо стараться так, чтобы у людей не возникало желания задуматься над типами переменных. Код должен быть самодокументированным. Если информации не хватает, то можно добавить комментарий или описать тип явно. C# тут немного проигрывает другим функциональным языкам, так как не позволяет указать тип для произвольного выражения. В других же языках тип можно указать где угодно. Скажем вместо того чтобы указывать тип возвращаемый LINQ-запросом так:
IEnumerable<Order> processedOrdrs = orders.Where(...);
foreach (Order order in processedOrdrs)
  ...

в Немерле (к примеру) можно сделать так:
foreach (order : Order in orders.Where(...))
  ...

При этом компилятор укажет на ошибку если в элемент коллекции не будет иметь тип order (при этом не будет производиться никаких приведений типов). Ну, а то что это последовательность становится ясно из использования ее в foreach-е.
Причем нам совершенно по барабану какой реальный тип этой последовательности (массив, List<Order> или IEnumerable<Order> и т.п.). Нам важно, что мы можем перебрать ее элементы.
Вот на этом и строится использование вывода типов в реальных приложений. А проблемы видятся только тем кто сам это не пробовал.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 15.01.09 11:51
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Я не знаток Гибернейта, но первый же найденный мною пример HQL-запроса показал, что типы колонок в нем так же не указываются:

VD>http://www.java2s.com/Code/Java/Hibernate/SelectSQL.htm
VD>
VD>Session session = HibernateUtil.currentSession();
    
VD>String sql = "select {supplier.*} from Supplier supplier";
            
VD>SQLQuery query = session.createSQLQuery(sql);
VD>query.addEntity("supplier", Supplier.class);
VD>List results = query.list();
VD>displaySupplierList(results);
VD>

VD>Кто-то из нас пытается выдать желаемое за действительное?

Это не HQL. HQL примерно так выглядит:
IList<Supplier> results = session.CreateQuery("from Supplier").List<Supplier>();


Впрочем в HQL с типизацией тоже все грустно. Все проверки в рантайме. Но типы колонок прописаны в маппинге, с этим все нормально.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[8]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 12:07
Оценка: -1
Здравствуйте, Undying, Вы писали:

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


E>>>И если распечатать код чтоб почитать перед сном — без поддержки студии понимать его будет значительно сложнее.

G>>А таким кто-то занимается?

U>Что быстрее просто посмотреть на код или навести мышку на переменную, чтобы воспользоваться подсказкой intellicence?


Если код не забит аннотациями типов, то обычно достаточно один раз навести курсор куда надо и запомнить в короткой памяти тип. Дальше все становится очевидным просто глядя на код.
Если же код испещрен аннотациями типов, то придется долго продираться сквозь них вычленяя из ненужной мишуры действительно нужный код.
Так что, как не странно, проще понять качественно написанный код с малым числом (или вообще нулевым) аннотаций нежели утыканный аннотациями "по самое не не хочу".

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


Переменные уровня класса — это наверное поля. Каким боком к ним вообще var относится?
Их тип конечно может быть не очевиден (если названия плохие). Но он так же будет не очевиден и без вар. \
У тебя тоже спрошу... А тебе не сильно мешает вывод типов в параметрах функций и алгоритм перегрузки?
Скажем, код типа:
f(x);

ровным счетом ничего не говорит ни о "f", ни о "x".

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


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

В общем, "вы его есть пробовали?" (с).

U> Переменных уровня класса в куске кода обычно 2-3, а всего переменных 10-20. Соответственно в коде с var'ами пользоваться подсказками intellicence приходиться в разы чаще, что ухудшает читабельность очень существенно.


Знаешь, я иногда не могу понять код в котором все типы очевидны как дважды два. Только отладка дает полное (и то не всегда) понимание. Ты наверно гений, раз можешь просто из аннотаций типов понять всю семантику кода.
Ну, гений так гений. Остальные люди не так гениальны. Они воспринимают код не как компилятор. Им чтобы понять, что делает код нужно объяснении автора (например, в виде комментариев или общения по аске), им нужно знать что за значение может быть в той или иной переменной. Им нужны рантайм-типы переменных, а не только те, что вывел компилятор или указал программист.
Учитывая тот факт, что код читаешь не только ты, код нужно писать так, чтобы он был максимально понятен. Это подразумевает интуитивность его восприятия. И редко когда этого качества удается добиться явным указанием типов переменных. А вот породить кашу забив все и вся многометровыми аннотациями типов очень легко.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Пример кода без порчи кодировки
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 12:35
Оценка: +1
Здравствуйте, Undying, Вы писали:


В понимании указанного кода реальной проблемой является то, что не ясна суть используемых объектов и общая задача. А как раз var-ы лично мне нисколько не мешают (даже без наличия подсказок от IDE).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 16.01.09 07:07
Оценка: +1
Здравствуйте, MxKazan, Вы писали:

MK>С переходом на var я не то, что не стал чаще обращаться к IntelliSense, а совсем наоборот! Ведь порой не сразу вспомнишь, какой тип функция возвращает, надо юзать IntelliSense. Теперь я написал var и всё. Когда буду использовать переменную, список свойств и методов все-равно "выпадет" после нажатия точки. Видимо правильно написал nikov: "это дело привычки". Я сейчас спокойно часто юзаю var, никакую читабельность он не уменьшает.


Уточню:

var же вынуждает пользоваться intellicence при чтении кода и для определения типов локальных переменных тоже, т.е. intellicence приходиться использовать чаще.

Запись кода меня мало волнует, т.к. чтение кода занимает куда больше времени.
Re[12]: LINQ как шаг к функциональному программированию
От: MxKazan Португалия  
Дата: 16.01.09 07:52
Оценка: :)
Здравствуйте, Undying, Вы писали:

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

Да, да. И это тоже при-выч-ка. Ну не можешь без точного типа и всё тут. А нужно просто расслабиться и получать удовольствие Просто попробуй не замечать var — ну есть переменная и Слава Богу! Со временем, привычка "искать тип" уйдет и var начнет нравицца

P.S. intellisense
Re[10]: Пример кода без порчи кодировки
От: hugo Австрия  
Дата: 16.01.09 09:24
Оценка: :)
Здравствуйте, Undying, Вы писали:

AspidContext, надо взять на вооружение...
Re[11]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 16.01.09 09:51
Оценка: +1
Здравствуйте, Ziaw, Вы писали:

U>>Я утверждал, что знание типов упрощает понимание кода. Я не утверждал, что знание типов дает полное понимание кода.


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


Обычно упрощает. Человеческое мышление же заточено на оперирование типами объектов, а не экземплярами объектов. Ведь большинство существительных в человеческих языках обозначают типы (стол, человек, собака), а экземпляр обозначают только имена собственные (Петя, Шарик), которые в основном используются в хорошо знакомом контексте.
Re[15]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 16.01.09 12:59
Оценка: +1
Здравствуйте, Ziaw, Вы писали:

Z>Я пока мне не докажут обратного, я буду считать, что Шарик собака. Если я узнаю, что в моей программе кто-то назвал кошку Шариком я буду сильно ругаться, вне зависимости, указал он явно что это кошка или это вывел компилятор.


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

Чтение кода в основном производиться по двум причинам:

1) Поиск ошибки.
2) Внесение изменений в код.

При поиске ошибок детали кода нас как раз и интересуют, т.к. причина ошибки, как правило, в деталях и скрывается.

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

Типы переменных эта деталь кода важная для понимания, без них как производить поиск ошибок, так и понимать нюансы бизнес-логики и/или реализованного решения значительно сложнее.
Re[16]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 16.01.09 13:23
Оценка: :)
Здравствуйте, Undying, Вы писали:

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


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

U>Чтение кода в основном производиться по двум причинам:


U>1) Поиск ошибки.

U>2) Внесение изменений в код.

U>При поиске ошибок детали кода нас как раз и интересуют, т.к. причина ошибки, как правило, в деталях и скрывается.


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

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


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

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


Я уже писал про это. Надо учиться писать понятный код, а не воевать с ветряными мельницами.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[9]: LINQ как шаг к функциональному программированию
От: hugo Австрия  
Дата: 21.01.09 14:17
Оценка: +1
Здравствуйте, Undying, Вы писали:


VD>>А какая разница есть она или нет? Ты код перестаешь читать если значение прямо в параметр (без переменной) передается?


U>В шарпе 2.0 есть три варианта объявления переменной:


На Erlang нет ни одного варианта, просто нету анотаций типов. Мне не мешает.
Как уже здесь говорили, наибольшая проблема — это понимание алгоритма. Conway's Game of Life, все, что я использую там — это int, массивы int'ов, таплы int'ов и всевозможные комбинации с int'ами. Здесь информация о типе перестает играть какую-либо роль вообще и начинаешь уделять внимание именам переменных и функций. И вынужден следить за этим постоянно. А имя переменной, это то, что видно на протяжении всего участка кода. Чего нельзя сказать о типе. Имея нормальное именование, за которыи ты просто уже обязан следить, начинаешь действительно читать код, а не копаться в нем.
Re[4]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.01.09 07:20
Оценка: +1
Здравствуйте, MxKazan, Вы писали:

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

MK>Как это не нужна? А события?

А события нужно было реализовывать как список функциональных типов. Обычный List<T> решил бы проблему без каких-нибудь проблем. Более того, решение на базе явного списка получается гибче. Реализуя основанная на списке может сама управлять тем как обрабатывать возвращаемые значения отдельных "делегатов". Мултикаст-делегат же использует одну стратегию — игнорирования всех возвращаемых значений кроме одного. Та же ерунда и с возвращаемыми параметрами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 22.01.09 08:07
Оценка: :)
Здравствуйте, SuhanovSergey, Вы писали:

SS>
var result = array1.Aggregate((first, second) => first + ", " + second);

SS>Это всё конечно изящно, но оно вылетает с исключением при пустой последовательности.

Перегрузка Aggregate((first, second) => first + ", " + second) вообще сомнительна, лучше всегда использовать:

array1.Aggregate("", (first, second) => first + ", " + second);


Здесь все прозрачно и может корректно работать на любой коллекции.
Re[11]: LINQ как шаг к функциональному программированию
От: hugo Австрия  
Дата: 22.01.09 09:11
Оценка: :)
Здравствуйте, Undying, Вы писали:

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


U>>>проще читается и модифицируется, нежели канонический:

H>>Я, наверное, еще очень молодой, но ИМХО этот код не читается вообще .

U>Объясни почему такой код по-твоему читабелен:


Я НИГДЕ НЕ писал, что такой код читабелен, будь внимателен, когда отвечаешь. Теперь я уже вообще не пойму, о чем ты говоришь .
Re[12]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 22.01.09 09:19
Оценка: -1
Здравствуйте, hugo, Вы писали:

U>>Объясни почему такой код по-твоему читабелен:

H>Я НИГДЕ НЕ писал, что такой код читабелен, будь внимателен, когда отвечаешь. Теперь я уже вообще не пойму, о чем ты говоришь .

Я привел два варианта кода. В http://rsdn.ru/forum/message/3258359.1.aspx
Автор: hugo
Дата: 21.01.09
второй из вариантов ты поскипал, а по поводу первого варианта написал, что этот код нечитабелен. Это логично понять, как то, что второй вариант ты посчитал приемлимым. Если бы ты сразу написал, что оба варианта кода нечитабельны вопросов бы к тебе у меня не возникло.
Re[13]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 09:36
Оценка: +1
Здравствуйте, Ziaw, Вы писали:

Z>Нам не важен конкретный тип переменной. Нам важен лишь смысл вызовов методов, его можно понять не зная конкретного типа.


А если общего смысла недостаточно, а надо знать нюансы, так как где-то баг?
лэт ми спик фром май харт
Re[5]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.01.09 16:04
Оценка: +1
Здравствуйте, Undying, Вы писали:

U>Мда... я был лучшего мнения об MS. Разложить столько граблей в одной функции это надо уметь. Считать initialValue по сути первым элементом коллекции это сильно, но мягко говоря неочевидно.


Причем тут МС? Ты бы прочел бы статью еще раз обращая внимание на ее суть, а не на никому не нужные в данном случае оптимизации. Глядишь и вопросы такие не возникли бы.

U>Тогда да в реализации от МS нормального решения нет, использовать Aggregate можно только так:


U>
U>  string result = "";
U>  if (array1.Count != 0)
U>    result = array1.Aggregate((first, second) => first + ", " + second));
U>


U>Что есть ужас.


Ужас в твоей голове. Шарп конечно не лучший ФП язык и его библиотеки не очень чисты, но тем не менее и на нем можно писать вполне себе функционально.

array1.Count == 0 ? "" : array1.Aggregate((first, second) => first + ", " + second))


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

U>Тем не менее написать реализацию без граблей вида Aggregate(T startValue, Func<T, T, T> func) вполне можно, но MS это не удалось.


Ну, конечно МС виновата в том, что кто-то глядя в книку видит фигу.

Если говорить о решении конкретной задачи — преобразовании последовательности в строку, то грамотным решением будет создание специализированных функций вроде:
string ToString<T>(this IEnumerable<T> seq, string separator);
string ToString<T>(this IEnumerable<T> seq, string separator, Fanc<T, string> converter);

А вот как их реализовать — это отдельный вопрос. Учитывая, что основная работа — это работа над своим проектом, то сначала их можно реализовать декларативно с применением LINQ-функций, а в последствии переписать императивно для большей скорости. При этом можно создать дополнительные перегрузки для специализированных коллекций вроде массивов. Это позволит еще больше поднять скорость в частных случаях.

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

Aggregate же (ака Fold, reduce) полезен как универсальный заменитель циклов. При его использовании циклы сжимаются до декларации их сути.

К сожалению именно этого ты и не увидел. Зато усмотрел проблемы у МС. Меж тем в большинстве ФЯ вообще нет аналога Aggregate не принимающего начальное значение. Так что это своего рода расширение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 27.01.09 09:40
Оценка: -1
Здравствуйте, VladD2, Вы писали:

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


А причем здесь статья? Сергей Суханов обратил внимание, что в реализации Aggregate от MS разложены грабли, соответственно эти грабли в данной подветке и обсуждаются.

Что касается твоей статьи, то она толковая, существенных претензий у меня к ней нет.

U>>Что есть ужас.


VD>Ужас в твоей голове. Шарп конечно не лучший ФП язык и его библиотеки не очень чисты, но тем не менее и на нем можно писать вполне себе функционально.


VD>
VD>array1.Count == 0 ? "" : array1.Aggregate((first, second) => first + ", " + second))
VD>


И что от того, что ты использовал запись в одну строчку, необходимость явной записи условия куда-то делась? Необходимость явной записи условия при использовании библиотечной функции это ужас.

VD>Если говорить о решении конкретной задачи — преобразовании последовательности в строку, то грамотным решением будет создание специализированных функций вроде:

VD>
VD>string ToString<T>(this IEnumerable<T> seq, string separator);
VD>string ToString<T>(this IEnumerable<T> seq, string separator, Fanc<T, string> converter);
VD>


И каким образом полноценный string.Join устранит грабли при использовании Aggregate?

VD>К сожалению именно этого ты и не увидел. Зато усмотрел проблемы у МС. Меж тем в большинстве ФЯ вообще нет аналога Aggregate не принимающего начальное значение. Так что это своего рода расширение.


Потому что в большинстве ФЯ решили не добавлять библиотечную функцию с заботливо разложенными граблями, в MS же не додумали. В то время как достаточно было вместо Aggregate(Func<T, T, T> func) сделать такую перегрузку:

Aggregate(Func<T, T, T> func, T defaultValue)


Такая перегрузка позволила бы прозрачным образом обрабатывать и пустую коллекцию и отсутствие коллекции(null).
Re[7]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.01.09 04:40
Оценка: +1
Здравствуйте, Undying, Вы писали:

VD>>
VD>>array1.Count == 0 ? "" : array1.Aggregate((first, second) => first + ", " + second))
VD>>


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


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

VD>>Если говорить о решении конкретной задачи — преобразовании последовательности в строку, то грамотным решением будет создание специализированных функций вроде:

VD>>
VD>>string ToString<T>(this IEnumerable<T> seq, string separator);
VD>>string ToString<T>(this IEnumerable<T> seq, string separator, Fanc<T, string> converter);
VD>>


U>И каким образом полноценный string.Join устранит грабли при использовании Aggregate?


Я наверно потерял нить. О чем речь? Причем тут string.Join?

U>Потому что в большинстве ФЯ решили не добавлять библиотечную функцию с заботливо разложенными граблями, в MS же не додумали. В то время как достаточно было вместо Aggregate(Func<T, T, T> func) сделать такую перегрузку:


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


U>
U>Aggregate(Func<T, T, T> func, T defaultValue)
U>


U>Такая перегрузка позволила бы прозрачным образом обрабатывать и пустую коллекцию и отсутствие коллекции(null).


Согласен. Ее не трудно написать на базе имеющейся функции.
Но конечно выбранное решение не очень хорошее.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: LINQ как шаг к функциональному программированию
От: _FRED_ Черногория
Дата: 29.08.08 05:51
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

ЧВV>LINQ как шаг к функциональному программированию
Автор(ы): Чистяков Влад (VladD2)
Дата: 26.01.2009
Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
Кроме того, эта статья дает некоторое понимание того, как работает «LONQ to Object» и на каких принципах он основан.


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

Это как объявление и использование переменных

Даже в узкоспециализированной литературе пренебрегать этим, ИМХО, неправильно: тяжело сразу настроить мозг на "раскрытие" сокращений и чтение уже не такое лёгкое, и удовольствия от него меньше.

Аббревиатуры "ФП" и "ИЯ" встречаются сразу без предупреждения:

Но чтобы иметь возможность читать (и писать) функциональный код надо быт знакомыми с основными приемами ФП.

Меж тем в ИЯ имеется множество конструкций создающих побочные эффекты.

Help will always be given at Hogwarts to those who ask for it.
Re[4]: LINQ как шаг к функциональному программированию
От: McSim  
Дата: 01.09.08 03:58
Оценка:
Здравствуйте, AngeL B., Вы писали:

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


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

Да разве же я с претензией написал это? Скорее просто пожелание на будущее. И если что, то мог бы принять участие в корректировке тексте перед публикацией.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: LINQ как шаг к функциональному программированию
От: AngeL B. Россия  
Дата: 01.09.08 06:06
Оценка:
Здравствуйте, McSim, Вы писали:

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


To McSim: Я не про твою фразу написал, а про Cyberax-овскую
Re[2]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.09.08 07:44
Оценка:
Здравствуйте, McSim, Вы писали:

MS>Но очень огорчает большое количество орфографических ошибок в тексте.


Это довольно странно, так как статьи проходит корректуру в редакции.
Огромная просьба выслать примеры ошибок на адрес mag@rsdn.ru или submit@rsdn.ru.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: LINQ как шаг к функциональному программированию
От: Kupaev Россия www.rsdn.ru
Дата: 01.09.08 11:25
Оценка:
Здравствуйте, McSim, Вы писали:

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


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


VD>>Это довольно странно, так как статьи проходит корректуру в редакции.

VD>>Огромная просьба выслать примеры ошибок на адрес mag@rsdn.ru или submit@rsdn.ru.

MS>К сожалению с собой только диск от журнала. Мне надо посмотреть на сами страницы журнала.


Спешка, увы, дает о себе знать.
Re: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.09.08 00:34
Оценка:
Хороший сравнительный пример использования LINQ привел IT в этом сообщении
Автор: IT
Дата: 22.09.08
.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: LINQ как шаг к функциональному программированию
От: Alf США  
Дата: 12.01.09 21:16
Оценка:
Похоже китайская техника копипейста добралась и до статей =)

Особенность 1: В ФЯ иногда можно встретить два варианта этой функции FoldLeft, FoldRight. Первая производит свертку от начала списка к концу, вторая, соответственно, наоборот, от начала к концу.
Re: LINQ как шаг к функциональному программированию
От: alvas  
Дата: 13.01.09 07:11
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Аннотация:

ЧВV>Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
ЧВV>Кроме того, эта статья дает некоторое понимание того, как работает «LINQ to Object» и на каких принципах он основан.

Здравствуйте, Влад!
Статья очень понравилась. С нетерпением жду продолжения.
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[3]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.01.09 10:19
Оценка:
Здравствуйте, Alf, Вы писали:

Alf>Похоже китайская техника копипейста добралась и до статей =)


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

Alf>Особенность 1: В ФЯ иногда можно встретить два варианта этой функции FoldLeft, FoldRight. Первая производит свертку от начала списка к концу, вторая, соответственно, наоборот, от начала к концу.


Да, есть такая ошибка. Сам заметил, но уже поздно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: LINQ как шаг к функциональному программированию
От: _FRED_ Черногория
Дата: 13.01.09 10:40
Оценка:
Здравствуйте, VladD2, Вы писали:

Извиняюсь, что спамлю, но на форум mag ты, наверное, не подписан, и личные сообщения не получаешь

Что с подпиской на журнал?
Автор: _FRED_
Дата: 24.12.08
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Re: LINQ как шаг к функциональному программированию
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 13.01.09 11:26
Оценка:
Здравствуйте, Чистяков Влад (VladD2)

Идентификатор seed при вызове func -- это ошибка или что-то другое?
public static TAccumulate AggregateRight<TSource, TAccumulate>(
  this IEnumerable<TSource> source, 
  TAccumulate acc, 
  Func<TAccumulate, TSource, TAccumulate> func)
{
  if (source == null)
    throw New ArgumentNullException("source");
  if (func == null)
    throw New ArgumentNullException("func");

  foreach (TSource item in source.Reverse())
    acc = func(seed, item);

  return acc;
}


PS. Из статьи можно было бы смело выкинуть, как минимум, 1/3 текста при сохранении той же информативности.
PPS. По ходу чтения сильно напрягает стиль изложения "от первого лица" с наездами на "императивных программистов".
PPPS. Надеюсь, что 90% императивных программистов все-таки пишут так:
for (int i = 0; i < array1.Length; i++)
{
  if (i != 0)
    result += ", ";

  result += array1[i];
}


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: LINQ как шаг к функциональному программированию
От: server_mouse Беларусь about:blank
Дата: 13.01.09 16:44
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

ЧВV>LINQ как шаг к функциональному программированию
Автор(ы): Чистяков Влад (VladD2)
Дата: 26.01.2009
Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
Кроме того, эта статья дает некоторое понимание того, как работает «LONQ to Object» и на каких принципах он основан.


ЧВV>Авторы:

ЧВV> Чистяков Влад (VladD2)

ЧВV>Аннотация:

ЧВV>Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
ЧВV>Кроме того, эта статья дает некоторое понимание того, как работает «LINQ to Object» и на каких принципах он основан.


Жаль про join не рассказали ничего.
Повреждение мозга после ректальной биопсии — редкая штука (с) Хаус
Re[2]: LINQ как шаг к функциональному программированию
От: Andrey Gliznetsov  
Дата: 14.01.09 08:39
Оценка:
Здравствуйте, eao197, Вы писали:

E>PPPS. Надеюсь, что 90% императивных программистов все-таки пишут так:

E>
E>for (int i = 0; i < array1.Length; i++)
E>{
E>  if (i != 0)
E>    result += ", ";

E>  result += array1[i];
E>}
E>


Надеюсь что любой грамотный программист напишет вот так:



var sb = new StringBuilder();
for (int i = 0; i < array1.Length; i++)
{
    if (i != 0)
    sb.Append(", ");
    sb.Append(array1[i]);
}
result = sb.ToString();



Кроме того за все в этой жизни надо платить, в том числе и за лаконичность LINQ, вот результаты конкатенации массива чисел из 10000 элементов:

Способ: императивный
Расход памяти: 1200 kb
Время: 1600 ms

Способ: LINQ
Расход памяти: 2400 kb
Время: 860 ms

Способ: StringBuilder
Расход памяти: 580 kb
Время: 4 ms

Интересно что Linq отаработал в два раза быстрее и сожрал в два раза больше памяти, чем простой цикл. Ну а последний результат, как говорится без коментариев
Re[3]: LINQ как шаг к функциональному программированию
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 14.01.09 11:27
Оценка:
Здравствуйте, Andrey Gliznetsov, Вы писали:

AG>Надеюсь что любой грамотный программист напишет вот так:


Если что-то может быть истолковано неправильно, это будет истолковано неправильно.

Мой поинт был в том, что выражение:
if (i != array1.Length - 1)

гораздо сложнее, чем:
if (i != 0)


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

Производительность и пр. не имеет к этому никакого отношения.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: LINQ как шаг к функциональному программированию
От: Denom Украина  
Дата: 14.01.09 12:46
Оценка:
Здравствуйте, Влад.

в статье написано:

К сожалению, в .NET нет реализации однонаправленного связанного списка.
Разве это не есть реализация однонаправленного связанного списка. Появилось кажись в версии 2.0
... << RSDN@Home 1.2.0 alpha 4 rev. 1125>>
Re[3]: LINQ как шаг к функциональному программированию
От: mrozov  
Дата: 14.01.09 13:27
Оценка:
Здравствуйте, Andrey Gliznetsov, Вы писали:

AG>Надеюсь что любой грамотный программист напишет вот так:


AG>
AG>var sb = new StringBuilder();
AG>for (int i = 0; i < array1.Length; i++)
AG>{
AG>    if (i != 0)
AG>    sb.Append(", ");
AG>    sb.Append(array1[i]);
AG>}
AG>result = sb.ToString();
AG>


Ну а я надеюсь, что любой грамотный программист напишет вот так:
result = string.Join(", ", array1);

P.S. Все украдено до нас.
Re[4]: LINQ как шаг к функциональному программированию
От: _FRED_ Черногория
Дата: 14.01.09 13:57
Оценка:
Здравствуйте, mrozov, Вы писали:

AG>>var sb = new StringBuilder();
AG>>for (int i = 0; i < array1.Length; i++)
AG>>{
AG>>    if (i != 0)
AG>>    sb.Append(", ");
AG>>    sb.Append(array1[i]);
AG>>}
AG>>result = sb.ToString();


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

M>result = string.Join(", ", array1);

M>P.S. Все украдено до нас.

Всё не так просто: а если array1 массив не строк, а каких-то объектов с переопределённым ToString?
result = string.Join(", ", Array.Convert(array1, x => x.ToString()));

А если размер массива достаточно велик, что бы делать его копию?
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Re[5]: LINQ как шаг к функциональному программированию
От: Tissot Россия  
Дата: 14.01.09 14:08
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Всё не так просто: а если array1 массив не строк, а каких-то объектов с переопределённым ToString?

_FR>
_FR>result = string.Join(", ", Array.Convert(array1, x => x.ToString()));
_FR>

_FR>А если размер массива достаточно велик, что бы делать его копию?

Все действительно не так просто. Если размер достаточно велик, то и со стрингбилдером может не сработать, т.к. в какой-то момент он может пожелать переаллоцировать память под внутренний буфер и тут-то и придет кирдык.
Имхо, такие граничные случай не следует даже пытаться решить в обобщенном виде. Если размер результируюшей строки действительно велик, то может оказать полезным сначала пробежать по массиву, вычислить размер строки, создать стрингбилдер с буфером такого размера и потом уже в него писать, чтобы избежать изменения размера буфера.
Re[2]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.01.09 18:29
Оценка:
Здравствуйте, server_mouse, Вы писали:

_>Жаль про join не рассказали ничего.


join — это уже расширение выходящее за рамки функционального подхода.

Как я написал в конце статьи, если у читателей будет массовое желание, то можно написать продолжение в котором коснуться и этих расширений.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: LINQ как шаг к функциональному программированию
От: IB Австрия http://rsdn.ru
Дата: 15.01.09 09:22
Оценка:
Здравствуйте, elmal, Вы писали:

E> В языках с динамической типизацией уже лет 20 считают, что лучше var ничего нет, и не будет.

В языках с динамической типизацией совсем другой var. C# по прежнему статически типизирован и все типы выводятся на этапе копиляции.

E>JavaScript и VBScript пойдет? 2 года опыта достаточно?

Нет, не подойдет, так как там var совсем другой.

E>Я как раз попрограммировав на этих языках наоборот на строгую типизацию намолиться не могу.

Строгая типизация никуда не делась.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[5]: LINQ как шаг к функциональному программированию
От: elmal  
Дата: 15.01.09 09:36
Оценка:
Здравствуйте, IB, Вы писали:

IB>В языках с динамической типизацией совсем другой var. C# по прежнему статически типизирован и все типы выводятся на этапе копиляции.

IB>Нет, не подойдет, так как там var совсем другой.
IB>Строгая типизация никуда не делась.
Это я прекрасно знаю. Но ... код визуально выглядит очень похоже на языки с динамической типизацией. И если распечатать код чтоб почитать перед сном — без поддержки студии понимать его будет значительно сложнее.
Re[7]: LINQ как шаг к функциональному программированию
От: elmal  
Дата: 15.01.09 10:37
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Эх, что же вы бедете делать когда появится dynamic (который кстати тоже является строгим типом)?

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

G>А таким кто-то занимается?

А как-же? Простейший пример — когда задают вопрос на форуме или пишут статью, копипастят исходники, и те, кто читают, к исходникам доступа не имеют и им труднее понять получается. Когда просят отревьюить код тоже частенько бросают его в аську. А там никакой студии нет встроенной.
Re[8]: LINQ как шаг к функциональному программированию
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.01.09 10:46
Оценка:
Здравствуйте, elmal, Вы писали:

G>>А таким кто-то занимается?

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

E>Когда просят отревьюить код тоже частенько бросают его в аську. А там никакой студии нет встроенной.

По куску текста можно только алгоритм увидеть, а в алгоритмах как раз конкретные типы — не главное.
Рвьювить на предмет дизайна по небольшому куску кода не сильно получится.
Re[7]: LINQ как шаг к функциональному программированию
От: _FRED_ Черногория
Дата: 15.01.09 10:55
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Эх, что же вы бедете делать когда появится dynamic (который кстати тоже является строгим типом)?


В каком смысле "строгим"? Как-раз таки это позднее связывание.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Re[3]: LINQ как шаг к функциональному программированию
От: Qbit86 Кипр
Дата: 15.01.09 11:31
Оценка:
Здравствуйте, Undying, Вы писали:

U>Это же круто, что мы на целых 3 символа меньше записали, а читабельность кода... кому она нужна?


Как-то ты неправдоподно эти три символа посчитал.

OuterNamespace.InnerNamespace.SomeLibraryClass c1 = new OuterNamespace.InnerNamespace.SomeLibraryClass();
var c2 = new OuterNamespace.InnerNamespace.SomeLibraryClass();

Какие преимущества в читабельности у первого варианта перед вторым?
Глаза у меня добрые, но рубашка — смирительная!
Re[4]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 11:33
Оценка:
Здравствуйте, elmal, Вы писали:

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

E>Это новое старо как мир . В языках с динамической типизацией уже лет 20 считают, что лучше var ничего нет, и не будет.

Как сказать. Все же между динамическими языками и языками с выводом типов есть огромная разница.
В прочем, это скорее аргумент "за", а не "против".

VD>>Если вопрос тебя действительно интересует, то давай начнем с вопросов к тебе.

VD>>1. Попробуй пройтись по статье и найти все места где тип переменных не очевиден?
E>Очевиден то он очевиден, но это напрягаться надо. И нет гарантии что где-то внутри цепочки вызовов тип не поменяется, более того, он меняется (дергается toString).

VD>>2. Задумывался ли ты над тем, что вывод типов есть не только для переменных объявленных с использованием var, но и при вызове методов (особенно обобщенных)? Чем, скажем вот этот код:

VD>>
VD>>PrintSeq(array1.Reverse().Where((name, i) => i % 2 == 0));
VD>>var result = array1.Reverse().Where((name, i) => i % 2 == 0);
VD>>PrintSeq(result);
VD>>

VD>>?
E>Именно из соображений плохой читаемости я в основном предпочитаю второй тип записи (естественно не var, а имя типа). Пишу первым способом только что-то тривиальное, из соображений чтоб места было меньше (например частичный перенос данных из одного объекта в другой type1.setName1(type2.getName2())).

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

А почему нет ответа на первый попро?

VD>>3. Почему поборники типизации переменных спокойно пишут SQL-запросы не указывая типов для возвращаемых колонок и при этом не возмущаются по поводу потери информации?

E>А я кстати возмущаюсь, что для типов возвращаемых колонок не указывается тип, когда приходится пользоваться SQL. Именно по этому предпочитаю вместо его HQL. Но и в HQL не все хорошо, в случае с наследованием сущностей далеко не тривиально узнать кого ж я получил из запроса и могу ли я дернуть соответствующее свойство — мне очень не хватает возможности указания типа даже в HQL запросе.

Я не знаток Гибернейта, но первый же найденный мною пример HQL-запроса показал, что типы колонок в нем так же не указываются:
http://www.java2s.com/Code/Java/Hibernate/SelectSQL.htm
Session session = HibernateUtil.currentSession();
    
String sql = "select {supplier.*} from Supplier supplier";
            
SQLQuery query = session.createSQLQuery(sql);
query.addEntity("supplier", Supplier.class);
List results = query.list();
displaySupplierList(results);

Кто-то из нас пытается выдать желаемое за действительное?

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

E>JavaScript и VBScript пойдет?

Нет. Пойдут:
Nemele, Scala, OCaml, Haskel и т.п.

E>2 года опыта достаточно? Я как раз попрограммировав на этих языках наоборот на строгую типизацию намолиться не могу.


А что ты понимаешь под термином "строгая типизация"? У тебя вообе какая-то каша в голове. Строгая типизация может быть как у статически-типизированных языков (все вышеперечисленные), так и у динамически-типизированных (приведенный тобой JavaScript весма строго-тапизирован). Ты видимо путаешь строгую и статическую типизацию. Но по любому JavaScript динамически-типизирован и в никакого опыта программирования на статически-типизированном языке с выводом типа на нем получить нельзя.

E>И относительно того, что при написании все будет хорошо, студия по нажатию точка все возможные варианты скажет. Код в основном читается, а не пишется. Один раз написал, 100 раз потом прочитал.


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

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

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


Вот тебе на! А что же ты тогда споришь? Как раз типы параметров функций почти во всех мэйнстрим языках (разве что в С — нет) выводятся из инициализации. Более того ты даже не знаешь что за функция вызвана, так как ее тип определяется компилятором по весьма сложному алгоритму разрешения перегрузки.

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

Так что ты сам себе противоречишь.

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


Что за "var"-аргументы? Ты видимо думаешь, что C# 3.0 ведет себя как скрипт? Отнюдь. Типы аргументов четко определены. Просто они не указываются явно (никогда). Если ты твои чаянья были притворены в жизнь, то писать пришлось бы вот такую жудь:

void PrintSeq(System.IEnumerable[int] array1 System.IEnumerable[string] .Reverse() System.IEnumerable[string] .Where((string name, int i) => int i % 2 == 0));

вместо:
PrintSeq(array1.Reverse().Where((name, i) => i % 2 == 0));

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

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


Если возникнет такая необходимость, то ты можешь подвести курсор мыши к переменной или выражению и посмотреть ее тип.
Ты лучше ответь на вопрос. В статье есть примеры тип выражений в которых для тебя оказался не очевидным (при прочтении статьи)? Ведь в статье действительно подсмотреть тип не выйдет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 15.01.09 11:43
Оценка:
Здравствуйте, gandjustas, Вы писали:

E>>И если распечатать код чтоб почитать перед сном — без поддержки студии понимать его будет значительно сложнее.

G>А таким кто-то занимается?

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

Чтобы понять кусок кода без var'ов обычно нужно навестись мышкой на переменные уровня класса, т.к. их тип неочевиден. Чтобы понять кусок кода с var'ами нужно навестись мышкой на все переменные, т.к. var делает неочевидным тип всех переменных. Переменных уровня класса в куске кода обычно 2-3, а всего переменных 10-20. Соответственно в коде с var'ами пользоваться подсказками intellicence приходиться в разы чаще, что ухудшает читабельность очень существенно.
Re[4]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 15.01.09 11:55
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Как-то ты неправдоподно эти три символа посчитал.


Q>
Q>OuterNamespace.InnerNamespace.SomeLibraryClass c1 = new OuterNamespace.InnerNamespace.SomeLibraryClass();
Q>

Q>Какие преимущества в читабельности у первого варианта перед вторым?

Такой вариант по читабельности эквивалентен или даже чуть лучше:

Q>
Q>OuterNamespace.InnerNamespace.SomeLibraryClass c1 = new ();
Q>


Но к сожалению в шарпе так писать нельзя.

Такой чуть хуже:

Q>
Q>var c1 = new OuterNamespace.InnerNamespace.SomeLibraryClass();
Q>


Т.к. в C# 2.0 тип переменных всегда писался слева и можно было всегда смотреть влево, а теперь иногда пишется слева, а иногда справа.

Такой сильно хуже:

Q>
Q>var c1 = GetSomething();
Q>


Т.к. определить тип переменной глазами уже нельзя, нужна подсказка интеллисенса, что требует наведения мышки, а это много медленее, чем взгляд.
Re[8]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 15.01.09 11:56
Оценка:
Здравствуйте, Undying, Вы писали:

U>Чтобы понять кусок кода без var'ов обычно нужно навестись мышкой на переменные уровня класса, т.к. их тип неочевиден. Чтобы понять кусок кода с var'ами нужно навестись мышкой на все переменные, т.к. var делает неочевидным тип всех переменных. Переменных уровня класса в куске кода обычно 2-3, а всего переменных 10-20. Соответственно в коде с var'ами пользоваться подсказками intellicence приходиться в разы чаще, что ухудшает читабельность очень существенно.


В описываемом коде явные проблемы с именованием переменных и/или методов/выражений с помощью которых эти переменные инициализируются. Можно пример кода, для понимания смысла которого важно знание типа какой-либо переменной?
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[5]: LINQ как шаг к функциональному программированию
От: nikov США http://www.linkedin.com/in/nikov
Дата: 15.01.09 12:12
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А что ты понимаешь под термином "строгая типизация"? У тебя вообе какая-то каша в голове. Строгая типизация может быть как у статически-типизированных языков (все вышеперечисленные), так и у динамически-типизированных (приведенный тобой JavaScript весма строго-тапизирован).


Вот как раз у JavaScript динамическая слабая типизация (потому что выполняются нявные преобразования между типами).
Re[9]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 15.01.09 12:13
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>В описываемом коде явные проблемы с именованием переменных и/или методов/выражений с помощью которых эти переменные инициализируются. Можно пример кода, для понимания смысла которого важно знание типа какой-либо переменной?


    string GetNumberAbonent(AspidContext context, ObjectPropertyBox propertyBox, PassportBox passport, ResultBox3 resultBox, int objId)
    {
      if (propertyBox == null || passport == null)
        return string.Empty;
      var objectKind = ObjectExtendedProperty.ObjectKind.FindValue(propertyBox, objId);
      var relationName = string.Empty;
      if (objectKind.CompareTo("п п п ") == 0)
        relationName = "п п п  - п п п ";
      else if (objectKind.CompareTo("пёпё") == 0)
        relationName = "п п п  - п п п п п п п  я п п п  я я п я п ";
      else if (resultBox != null)
      {
        var value = new Alias(objectId, "ObjectName").GetValue(resultBox);
        if (value != null)
          return value.ToString();
      }
      var links = Passport2.п п п п п я я п п п я п _п п я п п я я .FindValue(passport, objId);
      var parentLink = links
        .FirstOrDefault(link => link.ObjectRelTypeName.CompareTo(relationName) == 0);
      if (parentLink == null || parentLink.LinkObjectIds.Length == 0)
        return string.Empty;
      var parentId = parentLink.LinkObjectIds[0];
      var parentProperty = AspidDataModelHlp.GetPropertiesByObjects(context, new[] { parentId },
        ObjectExtendedProperty.ObjectName);
      return ObjectExtendedProperty.ObjectName.FindValue(parentProperty, parentId);
    }


Извиняюсь за проблемы с кодировкой русских символов, из почты копировал.
Re[10]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 12:17
Оценка:
Здравствуйте, Undying, Вы писали:

U>Извиняюсь за проблемы с кодировкой русских символов, из почты копировал.


Я тоже извиняюсь, но вот это:
      var links = Passport2.п п п п п я я п п п я п _п п я п п я я .FindValue(passport, objId);

Понять конечно нельзя. Но не потому, что там тип не указан, а потому, что имя функции в кашу превратилось.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 12:21
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Это не HQL. HQL примерно так выглядит:

Z>
Z>IList<Supplier> results = session.CreateQuery("from Supplier").List<Supplier>();
Z>


Z>Впрочем в HQL с типизацией тоже все грустно. Все проверки в рантайме. Но типы колонок прописаны в маппинге, с этим все нормально.


Что нормально? Что делать если мне нужно выбрать не объект, а две его колонки?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 12:24
Оценка:
Здравствуйте, nikov, Вы писали:

VD>>А что ты понимаешь под термином "строгая типизация"? У тебя вообе какая-то каша в голове. Строгая типизация может быть как у статически-типизированных языков (все вышеперечисленные), так и у динамически-типизированных (приведенный тобой JavaScript весма строго-тапизирован).


N>Вот как раз у JavaScript динамическая слабая типизация (потому что выполняются нявные преобразования между типами).


Это вопрос очень спорный. Вот в С++ слабая статическая типизация даже если забыть о неявном преобразовании типов.

Во многих источниках под строгостью понимается невозможность некорретного преобразования типов. Например, побитовое преобразование int64 в double или int в указатель. А неявные преобразования могут качественно обрабатываться в рантайме.

Я же говорил о другом. Человек явно путает понятия "строгая типизация" и "статическая типизация".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 12:26
Оценка:
Здравствуйте, Undying, Вы писали:

U>Т.к. в C# 2.0 тип переменных всегда писался слева и можно было всегда смотреть влево, а теперь иногда пишется слева, а иногда справа.


Чушь полнейшая. Вот тебе код на C# 1.0:
X(new Y());

U>Такой сильно хуже:


Q>>
Q>>var c1 = GetSomething();
Q>>


U>Т.к. определить тип переменной глазами уже нельзя, нужна подсказка интеллисенса, что требует наведения мышки, а это много медленее, чем взгляд.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: LINQ как шаг к функциональному программированию
От: elmal  
Дата: 15.01.09 12:26
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Можно ссылку на сообщение из форума где наличие var-ов мешало бы пониманию кода?

var result = ...
Да, я прекрасно, если заострю внимание, пойму о чем речь. Но беглым взглядом уже сложнее читать, чем IEnumerable<string> result. В любом случае result неудачное имя для переменной. Ладно, на деле, я согласен, что если я заменю все свои аннотации типов на var я почти ничего не потеряю, так как у меня имя переменной отражает тип. И если уж будут сторонники var, я в коде не потеряюсь, при условии что переменные будут называться так, чтоб я мог понять что это такое.

VD>И еще один вопрос. А почему ты не протестуешь против перегрузки и вывода типов параметров? Они ведь точно так же скрывают информацию о типах выражений и функций.

Причина проста. Если мне понадобится узнать как именно работает метод, мне в любом случае потребуется лезть в его код, то есть пользоваться ИДЕ. Как именно он работает чаще всего знать не надо, надо чтоб у него было нормальное имя. А вот типы данных, которыми я оперирую, мне более интересны в большинстве случаев (есть допустим переменная number — число. А числа бывают разные, комплексные, целые, беззнаковые, с фиксированной точностью, с неограниченной точностью — и про то, каким числом ты оперируешь очень полезно всегда помнить, так как есть тонкости. Если я тонкости не знаю, я могу про это забыть и допустить ошибку. Вероятность того, что я при беглом просмотре найду ошибку в чужом коде гораздо выше, если я вижу тип).
Re[9]: Пример кода без порчи кодировки
От: Undying Россия  
Дата: 15.01.09 12:29
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>В описываемом коде явные проблемы с именованием переменных и/или методов/выражений с помощью которых эти переменные инициализируются. Можно пример кода, для понимания смысла которого важно знание типа какой-либо переменной?


    string GetNumberAbonent(AspidContext context, ObjectPropertyBox propertyBox, PassportBox passport, ResultBox3 resultBox, int objId)
    {
      if (propertyBox == null || passport == null)
        return string.Empty;
      var objectKind = ObjectExtendedProperty.ObjectKind.FindValue(propertyBox, objId);
      var relationName = string.Empty;
      if (objectKind.CompareTo("ПТР") == 0)
        relationName = "ЦТП - Дом";
      else if (objectKind.CompareTo("УУ") == 0)
        relationName = "ЦТП - Домовой узел учета";
      else if (resultBox != null)
      {
        var value = new Alias(objectId, "ObjectName").GetValue(resultBox);
        if (value != null)
          return value.ToString();
      }
      var links = Passport2.Подключенные_Объекты.FindValue(passport, objId);
      var parentLink = links
        .FirstOrDefault(link => link.ObjectRelTypeName.CompareTo(relationName) == 0);
      if (parentLink == null || parentLink.LinkObjectIds.Length == 0)
        return string.Empty;
      var parentId = parentLink.LinkObjectIds[0];
      var parentProperty = AspidDataModelHlp.GetPropertiesByObjects(context, new[] { parentId },
        ObjectExtendedProperty.ObjectName);
      return ObjectExtendedProperty.ObjectName.FindValue(parentProperty, parentId);
    }
Re[7]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 15.01.09 12:38
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Что нормально? Что делать если мне нужно выбрать не объект, а две его колонки?


Тогда все плохо. Никакой типизации и боксинг вдобавок.
var results = session.CreateQuery("select s.Id, s.Name from Supplier s").List<object[]>();


В простейшем запросе поможет linq2nhibernate:
var results = from s in session.Linq<Supplier>() select new { s.Id, s.Name };


В более менее сложных запросах только HQL и работа с row в виде object[]. Можно немного припудрить конечно, но по сути грустно.
var results = session
  .CreateQuery("select s.Id, s.Name from Supplier s")
  .List<object[]>.Select(s => new { (long)s.Id, (string)s.Name} );


Вообще я не заявлял, что все хорошо в NH. Но приводить в качестве примера код на яве, где выборка идет с помощью голого SQL и возвращается нетипизированый список слегка некорректно.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[9]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 15.01.09 12:51
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Переменные уровня класса — это наверное поля. Каким боком к ним вообще var относится?

VD>Их тип конечно может быть не очевиден (если названия плохие). Но он так же будет не очевиден и без вар. \

Поэтому в шарпе 2.0 для определения типа полей класса приходилось пользоваться intellicence. var же вынуждает пользоваться intellicence и для определения типов локальных переменных тоже, т.е. intellicence приходиться использовать чаще.

VD>У тебя тоже спрошу... А тебе не сильно мешает вывод типов в параметрах функций и алгоритм перегрузки?

VD>Скажем, код типа:
VD>
VD>f(x);
VD>

VD>ровным счетом ничего не говорит ни о "f", ни о "x".

В сложных случаях мешает сильно. Такой код читабелен:

new SimpleColumn("Логин").WithCharWidth(16).WithFontBold(true).WithBackColor(Color.MistyRose).WithForeColor(Color.Black).WithFrozenColumn(true);


А вот такой, когда у SimpleColumn двадцать пять перегрузок конструктора практически нет:

new SimpleColumn("Логин", 16, true, Color.MistyRose, Color.Black, true);



VD>Ну, где ты видел код в котором для его понимания приходится наводить курсор на все переменные?

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

Имя переменной присваивается из соображений бизнес логики и обычно никак не связано с типом переменной.

VD>Знаешь, я иногда не могу понять код в котором все типы очевидны как дважды два. Только отладка дает полное (и то не всегда) понимание. Ты наверно гений, раз можешь просто из аннотаций типов понять всю семантику кода.


Я утверждал, что знание типов упрощает понимание кода. Я не утверждал, что знание типов дает полное понимание кода.

VD>Уважаемый, ты похож на старую бабку бурчащую на девочку в мини-юбке показываемую по телевизору.


Ты на личности переходишь из желания самоутвердиться или по каким-то другим соображения? Вроде в твоем возрасте этим уже поздновато заниматься.
Re[10]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 14:23
Оценка:
Здравствуйте, Undying, Вы писали:

U>Поэтому в шарпе 2.0 для определения типа полей класса приходилось пользоваться intellicence. var же вынуждает пользоваться intellicence и для определения типов локальных переменных тоже, т.е. intellicence приходиться использовать чаще.


И что в этом плохого? Не уж-то лучше венгерку использовать или захламлять код тем, что не интересно 99% времени?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 14:32
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Вообще я не заявлял, что все хорошо в NH.


Я понимаю. И первое что хочется сказать — спасибо за консультацию.
Я не использую Гибернэйт по разным причинам (первая из которых — он мне не нужен). По сему не могу привести корректных примеров. Но интуитивно понимаю, что выдвигаемые моим оппонентом аргументы высасоны из пальца. Твои слова это как раз подтверждают.

Z>Но приводить в качестве примера код на яве, где выборка идет с помощью голого SQL и возвращается нетипизированый список слегка некорректно.


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

А пример мне этот был нужен чтобы продемонстрировать, то что и в Гибернэйтовском HQL типы колонок возвращаемого результирующего набора не описываются явно. Ты это и продемонстрировал.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: LINQ как шаг к функциональному программированию
От: elmal  
Дата: 15.01.09 15:09
Оценка:
Здравствуйте, nikov, Вы писали:

N>Varification -- Using Implicitly Typed Locals

Спасибо, просвятился, убедили .
Re[4]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 15:23
Оценка:
Здравствуйте, eao197, Вы писали:

E>Если что-то может быть истолковано неправильно, это будет истолковано неправильно.


E>Мой поинт был в том, что выражение:

E>
E>if (i != array1.Length - 1)
E>

E>гораздо сложнее, чем:
E>
E>if (i != 0)
E>


E>Поэтому, если "императивный программист" выбирает сложные пути даже в простых программах, то точно так же он будет выбирать сложные пути и в функциональных программах.


Малаец. Теперь перечитай свои слова про неверность истолковывания несколько раз и подумай над тем зачем ты сделал исходное замечание. Ведь мой "поинт" был в том, что императивный программист напишет цикла с подробным описанием того как он будет конкатенировать строку, а не с описанием того, что он хочет получить в итоге. Ты же влез и совершенно не в кассу попытался перевести разговор в русло обсуждения деталей императивной реализации. В итоге ты совершенно заслужено получил упрек в ее неоптимальности. И действительно, если рассуждать об оптималности и ясности, то вариант который привел Andrey Gliznetsov ближе всего к тому что написал бы хороший императивщик. Вот только разговор то не о том был. И все эти частности реализации просто не важны.

Так чего лезть то с замечаниями не по делу?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: LINQ как шаг к функциональному программированию
От: elmal  
Дата: 15.01.09 15:50
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А пример мне этот был нужен чтобы продемонстрировать, то что и в Гибернэйтовском HQL типы колонок возвращаемого результирующего набора не описываются явно. Ты это и продемонстрировал.

Supplier как раз тут и является типом. А когда приходится возвращать часть значений, приходится создавать DTO, в конструктор которого передаются нужные параметры, это имхо лучше чем работать с результатом object[] и кастить к нужным типам.
Re[10]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.09 17:36
Оценка:
Здравствуйте, elmal, Вы писали:

VD>>А пример мне этот был нужен чтобы продемонстрировать, то что и в Гибернэйтовском HQL типы колонок возвращаемого результирующего набора не описываются явно. Ты это и продемонстрировал.

E>Supplier как раз тут и является типом.

Это тип объекта. Если ты его будешь возращать, то ты так же сможешь описать его (если захочешь). А когда речь идет о паре-тройке колонок, то почему-то описаний уже не видать.

E> А когда приходится возвращать часть значений, приходится создавать DTO, в конструктор которого передаются нужные параметры, это имхо лучше чем работать с результатом object[] и кастить к нужным типам.


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

Что до object[], то конечно работать с типизированными значениями надежнее и проще (для статически-типизированного языка). Но этого никто и не оспаривал. Оспаривалось утверждение о том, что все и всегда нужно аннотировать типами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 16.01.09 07:22
Оценка:
Здравствуйте, VladD2, Вы писали:

U>>Т.к. в C# 2.0 тип переменных всегда писался слева и можно было всегда смотреть влево, а теперь иногда пишется слева, а иногда справа.


VD>Чушь полнейшая. Вот тебе код на C# 1.0:

VD>X(new Y());

В этом коде есть объявление переменной?
Re[11]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 16.01.09 07:57
Оценка:
Здравствуйте, Ziaw, Вы писали:

U>>
U>>new SimpleColumn("Логин").WithCharWidth(16).WithFontBold(true).WithBackColor(Color.MistyRose).WithForeColor(Color.Black).WithFrozenColumn(true);
U>>

Z>для этого придумали синтаксический сахар который еще читабельнее:
Z>
Z>new SimpleColumn("Логин") { CharWidth = 16, FontBold = true, ...};
Z>


И с чего ты взял, что у SimpleColumn есть поля CharWidth, FontBold и т.д? Там внутри вообще Dictionary<string, ColumnExtension>, в который все настройки и записываются.

Z>Плохой дизайн, как минимум нарушен SRP. Вообще такие конструкторы имеют смысл только для immutable классов. В таком случае я делаю рефакторинг в:

Z>
Z>new SimpleColumn("Логин", 
Z>    new FontStyle(16, FontDecoration.Bold, Color.Black), 
Z>    new BackgroundStyle(Color.Black), 
Z>    ColumnType.Frozen);
Z>


И что мне теперь делать, если я не хочу указывать размер шрифта, но хочу указать, что он жирный? Что делать, если мне понадобилось поддержать новую настройку, например, Italic? Изменять FontStyle? А если у меня доступа к его коду нет? И какова цена если я его нечайно при изменении поломаю? Или завтра ячейку двумя шрифтами нужно будет отрисовывать и что тогда делать? Добавлять класс AdditionalFontStyle полностью идентичный FontStyle?

Если у нас есть набор настроек, которые пользователь может выбирать произвольным образом, то подход с конструктором не работает. Даже если настроек всего лишь 10, то нужно написать всего-то штук 50 конструкторов. Это, во-первых, малость трудоемко, а, во-вторых, даже если не полениться и заюзать какую-нибудь кодогенерацию, то все равно очень плохо читаемо.

Z>
Z>var firstLink = GetFirstLink(); // здесь мы без типа знаем, что это Link
Z>// полэкрана кода
Z>Console.WriteLine(firstLink.Length); // здесь мы легко понимаем, что происходит даже не зная тип переменной
Z>


Имя переменной полностью или частично содержит имя класса только в одном случае, когда это узкоспециализированный класс, заточенный под конкретную задачу/сущность бизнес-логики. Как только класс становиться мало-мальски универсальным, имя класса из имен переменных исчезает.
Re[12]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 16.01.09 09:34
Оценка:
Здравствуйте, Undying, Вы писали:

U>И с чего ты взял, что у SimpleColumn есть поля CharWidth, FontBold и т.д? Там внутри вообще Dictionary<string, ColumnExtension>, в который все настройки и записываются.


Предположил нормальный дизайн класса. Какой резон хранить настройки в словаре, если все равно они есть в контракте (методы WithBlaBla)?

Z>>Плохой дизайн, как минимум нарушен SRP. Вообще такие конструкторы имеют смысл только для immutable классов. В таком случае я делаю рефакторинг в:


U>И что мне теперь делать, если я не хочу указывать размер шрифта, но хочу указать, что он жирный? Что делать, если мне понадобилось поддержать новую настройку, например, Italic? Изменять FontStyle? А если у меня доступа к его коду нет? И какова цена если я его нечайно при изменении поломаю? Или завтра ячейку двумя шрифтами нужно будет отрисовывать и что тогда делать? Добавлять класс AdditionalFontStyle полностью идентичный FontStyle?


U>Если у нас есть набор настроек, которые пользователь может выбирать произвольным образом, то подход с конструктором не работает. Даже если настроек всего лишь 10, то нужно написать всего-то штук 50 конструкторов. Это, во-первых, малость трудоемко, а, во-вторых, даже если не полениться и заюзать какую-нибудь кодогенерацию, то все равно очень плохо читаемо.


Остается понять, зачем делать такой класс immutable. Если его не делать таковым, смысл кучи конструкторов ускользает.

U>Имя переменной полностью или частично содержит имя класса только в одном случае, когда это узкоспециализированный класс, заточенный под конкретную задачу/сущность бизнес-логики. Как только класс становиться мало-мальски универсальным, имя класса из имен переменных исчезает.


Я не встречал ни одного маломальски универсального класса. Каждый класс предназначен для выполнения какой-то своей задачи (SRP). Хорошая практика отражать это в названии класса. Хорошая практика также называть переменную содержащую экземпляр этого класса в соответствии с задачей которую он выполняет. А если мы можем догадаться о роли объекта, смысл вызовов его методов становится вполне понятен. Нам не важен конкретный тип переменной. Нам важен лишь смысл вызовов методов, его можно понять не зная конкретного типа.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[10]: LINQ как шаг к функциональному программированию OFF-
От: hugo Австрия  
Дата: 16.01.09 09:36
Оценка:
Здравствуйте, Undying, Вы писали:

U>В сложных случаях мешает сильно. Такой код читабелен:


U>
U>new SimpleColumn("Логин").WithCharWidth(16).WithFontBold(true).WithBackColor(Color.MistyRose).WithForeColor(Color.Black).WithFrozenColumn(true);
U>


U>А вот такой, когда у SimpleColumn двадцать пять перегрузок конструктора практически нет:


U>
U>new SimpleColumn("Логин", 16, true, Color.MistyRose, Color.Black, true);
U>


А вот, например. как это выгладело бы на Obj-C (если я правильно помню синтаксис )

SimpleColumn(Caption : "Логин", CharWidth: 16, FontBold: true, BackColor: Color.MistyRose, ForeColor : Color.Black, FrozenColumn: true);


ИМХО куда лучше, чем вариант с кучей методов. А то и ParameterClass паттерн можно прикрутить, раз уж C# не совершенен
Re[13]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 16.01.09 11:25
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Предположил нормальный дизайн класса. Какой резон хранить настройки в словаре, если все равно они есть в контракте (методы WithBlaBla)?


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

U>>Если у нас есть набор настроек, которые пользователь может выбирать произвольным образом, то подход с конструктором не работает. Даже если настроек всего лишь 10, то нужно написать всего-то штук 50 конструкторов. Это, во-первых, малость трудоемко, а, во-вторых, даже если не полениться и заюзать какую-нибудь кодогенерацию, то все равно очень плохо читаемо.


Z>Остается понять, зачем делать такой класс immutable. Если его не делать таковым, смысл кучи конструкторов ускользает.


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

SimpleColumn column = new SimpleColumn("Логин");
column.CharWidth = 12;
column.BackColor = Color.MistyRose;


Z>Я не встречал ни одного маломальски универсального класса.


Ты не встречал классы List, object, string?

Z>Каждый класс предназначен для выполнения какой-то своей задачи (SRP). Хорошая практика отражать это в названии класса. Хорошая практика также называть переменную содержащую экземпляр этого класса в соответствии с задачей которую он выполняет.


Естественно, поэтому мы называем коллекцию linkedElements, а не linkedElementList, и соответственно вывести из названия переменной тип не можем.

Z>А если мы можем догадаться о роли объекта, смысл вызовов его методов становится вполне понятен. Нам не важен конкретный тип переменной. Нам важен лишь смысл вызовов методов, его можно понять не зная конкретного типа.


Понять можно, но сделать это значительно сложнее.
Re[13]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 16.01.09 11:28
Оценка:
Здравствуйте, Ziaw, Вы писали:

U>>Обычно упрощает. Человеческое мышление же заточено на оперирование типами объектов, а не экземплярами объектов. Ведь большинство существительных в человеческих языках обозначают типы (стол, человек, собака), а экземпляр обозначают только имена собственные (Петя, Шарик), которые в основном используются в хорошо знакомом контексте.


Z>Отличная аналогия, в предложении "Собака Шарик виляет хвостом" слово собака несет избыточную информацию. Человек Петя устроился на работу .


Есть два варианта:

1) Шарик это собака.
Шарик виляет хвостом.

2) Шарик виляет хвостом.

Откуда во-втором варианте можно узнать, что Шарик это собака, а не кошка?
Re[13]: LINQ как шаг к функциональному программированию
От: rameel https://github.com/rsdn/CodeJam
Дата: 16.01.09 11:38
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Отличная аналогия, в предложении "Собака Шарик виляет хвостом" слово собака несет избыточную информацию. Человек Петя устроился на работу .


... << RSDN@Home 1.2.0 alpha 4 rev. 1111 >>
Re[11]: LINQ как шаг к функциональному программированию OFF-
От: Undying Россия  
Дата: 16.01.09 13:08
Оценка:
Здравствуйте, hugo, Вы писали:

H>А вот, например. как это выгладело бы на Obj-C (если я правильно помню синтаксис )


H>
H>SimpleColumn(Caption : "Логин", CharWidth: 16, FontBold: true, BackColor: Color.MistyRose, ForeColor : Color.Black, FrozenColumn: true);
H>


Такое решение неплохое, но у него есть два недостатка: 1) его нельзя расширить внешним образом, при добавлении нового параметра приходется вносить изменения в SimpleColumn 2) C# не поддерживает опциональные параметры в конструкторах.

Сейчас на мой взгляд лучшее решение такое:

           new SimpleColumn<RowLink>("Модель",
              delegate(RowLink device)
              {
                return modelBox.GetModel(Passport2.Model.GetValue(device));
              },
              GridExt.CharWidth(20), GridExt.HAlignment(true),
              GridExt.CellFiller(ComboGridCellFiller.Default),
              GridExt.ComboItems(modelBox.AllModels)),


Но у него есть недостаток, статический интерфейс класса почему-то нельзя расширять внешним образом, соответственно в общем случае придется плодить GridExtAdditional и т.п. With'ы на Extension в этом смысле лучше, хотя и выглядят чуть тяжеловесней.
Re[7]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.01.09 17:04
Оценка:
Здравствуйте, Undying, Вы писали:

VD>>Чушь полнейшая. Вот тебе код на C# 1.0:

VD>>X(new Y());

U>В этом коде есть объявление переменной?


А какая разница есть она или нет? Ты код перестаешь читать если значение прямо в параметр (без переменной) передается?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: LINQ как шаг к функциональному программированию
От: Аноним  
Дата: 17.01.09 08:27
Оценка:
AG>Кроме того за все в этой жизни надо платить, в том числе и за лаконичность LINQ, вот результаты конкатенации массива чисел из 10000 элементов:

AG>Способ: императивный

AG>Расход памяти: 1200 kb
AG>Время: 1600 ms

Вообще-то, неправильно выделять этот способ как именно императивный. Это только один из множества императивных способов, причем самый наивный и неэффективный.
Re[10]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.01.09 20:19
Оценка:
Здравствуйте, Undying, Вы писали:

U>В сложных случаях мешает сильно. Такой код читабелен:


U>
U>new SimpleColumn("Логин").WithCharWidth(16).WithFontBold(true).WithBackColor(Color.MistyRose).WithForeColor(Color.Black).WithFrozenColumn(true);
U>


U>А вот такой, когда у SimpleColumn двадцать пять перегрузок конструктора практически нет:


U>
U>new SimpleColumn("Логин", 16, true, Color.MistyRose, Color.Black, true);
U>


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

Более того — это пример отлично демонстрирует бессмысленность знания типов для понимания кода (в некоторых случаях).
Всмотрись в свой код. Все типы всех параметров ясны как божий день! Но что тебе это дало? Ровным счетом ничего.

А вот имена переменных тебе тут что-то дали бы. Вот только они привели бы к некоторому захламлению кода. Лучше всего в такой ситуации использовать именовыанные параметры. Nemerle и VB их поддерживают. C# к сожалению — нет. Но будет поддерживать в 4-ой версии.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.01.09 20:35
Оценка:
Здравствуйте, Undying, Вы писали:

U>Чтение кода в основном производиться по двум причинам:


U>1) Поиск ошибки.

U>2) Внесение изменений в код.

U>При поиске ошибок детали кода нас как раз и интересуют, т.к. причина ошибки, как правило, в деталях и скрывается.


В обоих случаях важна семантика кода. Ее ни типы, ни имена переменных на 100% не описывают. Можно даже утверждать, что сам факт наличия ошибки говорит о неверной семантике. А раз так, то имена могут только сбивать с толку. Ведь ошибка есть. А значит, что любое имя и любой тип прийдется ставить под сомнение.

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

К чему я? Да к тому, что для поиска ошибок нужно использовать тесты и отладчик или хотя бы тесты и консольный вывод (по дедовски, так сказать). При этом информация о всех типах не просто доступна, а доступна в полном объеме. А наличие типов в коде при этом может даже быть вредным, так как код от этого распухает.

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


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


Типы доступны в отладчике и интеллисенсе. Без оных все равно на 100 понять код нельзя. А раз это так, то зачем цепляться за неполную информацию основную часть времени только засоряющую код?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.01.09 20:41
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Внесение изменений в нормальный и покрытый тестами код очень простая процедура. Это не требует вдумчивой медитации над кодом и дебага в голове.


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

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

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

Само собой, что совершенно все равно как при этом объявлены переменные. Важно чтобы отладчик позволял бы их "смотреть".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: LINQ как шаг к функциональному программированию
От: Aikin Беларусь kavaleu.ru
Дата: 19.01.09 08:44
Оценка:
Здравствуйте, <Аноним>, Вы писали:

AG>>Кроме того за все в этой жизни надо платить, в том числе и за лаконичность LINQ, вот результаты конкатенации массива чисел из 10000 элементов:


AG>>Способ: императивный

AG>>Расход памяти: 1200 kb
AG>>Время: 1600 ms

А>Вообще-то, неправильно выделять этот способ как именно императивный. Это только один из множества императивных способов, причем самый наивный и неэффективный.

Это самый императивный из императивных способов

P.S. Под императивным я понимаю: "расскажу-ка я компу как нужно действовать".
Re[8]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 19.01.09 12:51
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А какая разница есть она или нет? Ты код перестаешь читать если значение прямо в параметр (без переменной) передается?


В шарпе 2.0 есть три варианта объявления переменной:

1) Переменная объявляется по месту использования:

SomeFunction(new SomeClass());


Здесь тип переменной всегда очевиден.

2) Переменная получена из функции по месту использования:

SomeFunction(GetSomeClass());


Здесь взглядом определить тип переменной нельзя, всегда нужно использовать intellisense.

3) Переменная объявлена перед использованием:

SomeClass someClass = GetSomeClass();
...
SomeFunction(someClass);


В этом случае, чтобы определить тип someClass всегда нужно посмотреть на левую часть объявления этой переменной.


Если же в коде используются var, то вариант 3 разбивается на три подварианта:

а) Как в шарпе 2.0

б) var + конструктор

var someClass = new SomeClass();
...
SomeFunction(someClass);


Чтобы определить тип someClass теперь нужно смотреть на правую часть объявления, а не на левую как в варианте а.

в) var + вызов функции

var someClass = GetSomeClass();
...
SomeFunction(someClass);


Упс... зря смотрели на объявление переменной, тип взглядом вывести нельзя, надо юзать intellisense.

Т.е. вариантов стало больше, видя код SomeFunction(someClass), мы теперь, чтобы определить тип someClass, в одном случае должны посмотреть в левую часть объявления переменной, в другом — в правую, в третьем — и вовсе воспользоваться intellisense, а, значит, читабельность стала хоть и чуточку, но хуже. А учитывая, что объявлений переменных в коде очень много, эта чуточка суммируется и становится довольно существенной.
Re[9]: LINQ как шаг к функциональному программированию
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.01.09 12:57
Оценка:
Здравствуйте, Undying, Вы писали:

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


И почему до сих пор думаете что читаемость зависит от информации о типах?

Получается что любой язык с динамической типизацией вообще нечитаем?
Re[8]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 19.01.09 13:08
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Вообще-то, абстракция — это отказ от несущественных деталей. И во многом благодаря абстракции читабельность улучшается.


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

      if (true)
      {
        LightSynchronizer<int> sync = new LightSynchronizer<int>(this,
          delegate
          {
            return modifyDeviceGridSynch.VisibleDataRegion.Height;
          },
          delegate (int visibleHeight)
          {
            int rowHeight = modifyDeviceGridSynch.RowHeight;
            modifyDevicePanel.Height = modifyDevicePanel.Height + (rowHeight - visibleHeight);
          },
          TimeSpan.FromMilliseconds(100));
      }

      if (true)
      {
        LightSynchronizer<string> sync = new LightSynchronizer<string>(this,
          delegate
          {
            return Passport2.Model.GetValue(modifyDevice);
          },
          delegate(string model)
          {
            foreach (string dataType in modelBox.GetNewDataTypes(model))
              Passport2.StoragePeriod.SetProperty(modifyDevice, 14, dataType);
          });
      }


проще читается и модифицируется, нежели канонический:

      CreateHeightModifyPanelSynchronizer();
      CreateDeviceDataTypeSynchronizer();


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

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

      inline("HeightModifyPanelSynchronizer")
      {
        ...
      }

      inline("DeviceDataTypeSynchronizer")
      {
        ...
      }


Соответственно с возможностью перемещения по этим inline в студии, аналогичной сегодняшнему перемещению по функциям, отражением inline в stacktrace и т.п.
Re: LINQ как шаг к функциональному программированию
От: Аноним  
Дата: 21.01.09 10:59
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Данное решение не создает особых проблем на практике, за исключением того, что вызов делегата медленнее, чем мог бы быть, так как приходится анализировать лишнюю информацию.


На основании чего сделан вывод? Вы смотрели генерируемый машинный код? Можете ли предложить более оптимальный, если бы делегат хранил одну ссылку (при этом поддерживая прочий функционал делегатов)?
Re[2]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.01.09 13:44
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Чистяков Влад (VladD2), Вы писали:


ЧВV>>Данное решение не создает особых проблем на практике, за исключением того, что вызов делегата медленнее, чем мог бы быть, так как приходится анализировать лишнюю информацию.


А>На основании чего сделан вывод?


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

А>Вы смотрели генерируемый машинный код?


В том числе и его.

А>Можете ли предложить более оптимальный, если бы делегат хранил одну ссылку (при этом поддерживая прочий функционал делегатов)?


Если исключить поддержку множественных вызовов, которая на практике не нужна, то обычный класс с виртуальным методом работает быстрее. Да и в реализации он проще. Так устроены функциональные типы в F#, Nemerle и в Scala. Учитывая, что конкретные экземпляры можно помечать как sealed потенциально такое решением может быть оптим в плоть до прямого не виртуального вызова, а то и подставлено по месту. Единственная его проблема — в больших проектах получается очень много "рабочих" классов, что в итоге приводит к замедлению загрузки сборок. Но прекомпилированные (ngen-ом) сборки грузятся довольно шустро. Если же реализовывать это на уровне виртуальной машины, можно добиться быстрой загрузки. С делегатами ведь такой проблемы нет...
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: LINQ как шаг к функциональному программированию
От: hugo Австрия  
Дата: 21.01.09 14:02
Оценка:
Здравствуйте, Undying, Вы писали:

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


U>
U>      if (true)
U>      {
U>        LightSynchronizer<int> sync = new LightSynchronizer<int>(this,
U>          delegate
U>          {
U>            return modifyDeviceGridSynch.VisibleDataRegion.Height;
U>          },
U>          delegate (int visibleHeight)
U>          {
U>            int rowHeight = modifyDeviceGridSynch.RowHeight;
U>            modifyDevicePanel.Height = modifyDevicePanel.Height + (rowHeight - visibleHeight);
U>          },
U>          TimeSpan.FromMilliseconds(100));
U>      }

U>      if (true)
U>      {
U>        LightSynchronizer<string> sync = new LightSynchronizer<string>(this,
U>          delegate
U>          {
U>            return Passport2.Model.GetValue(modifyDevice);
U>          },
U>          delegate(string model)
U>          {
U>            foreach (string dataType in modelBox.GetNewDataTypes(model))
U>              Passport2.StoragePeriod.SetProperty(modifyDevice, 14, dataType);
U>          });
U>      }
U>


U>проще читается и модифицируется, нежели канонический:


Я, наверное, еще очень молодой, но ИМХО этот код не читается вообще .
Re[3]: LINQ как шаг к функциональному программированию
От: MxKazan Португалия  
Дата: 21.01.09 14:14
Оценка:
Здравствуйте, VladD2, Вы писали:

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

Как это не нужна? А события?
Re[2]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.01.09 07:29
Оценка:
Здравствуйте, SuhanovSergey, Вы писали:

SS>
var result = array1.Aggregate((first, second) => first + ", " + second);

SS>Это всё конечно изящно, но оно вылетает с исключением при пустой последовательности.

Есть такая беда. Кроме того код получается весьма не эффективным (циклическая конкатенация строк — плохое решение).
Так что на практике лучше использовать специализированную версию конкатенации. Это же просто примеры.
Задача статьи показать способы обработки данных, а не дать конкретные решения.
Лично я на практике пользуюсь макросом языка Nemerle ($"..$array1") который дает очень компактный синтаксис и максимально эффективное исполнение.

Кроме того нет проблем написать собственную версию Aggregate которая будет возвращать некоторое значение по умолчанию. Это же способ программирования, а не захардкоженая реализация одной функции!
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: LINQ как шаг к функциональному программированию OFF-
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.01.09 07:41
Оценка:
Здравствуйте, Undying, Вы писали:

H>>
H>>SimpleColumn(Caption : "Логин", CharWidth: 16, FontBold: true, BackColor: Color.MistyRose, ForeColor : Color.Black, FrozenColumn: true);
H>>


U>Такое решение неплохое, но у него есть два недостатка: 1) его нельзя расширить внешним образом, при добавлении нового параметра приходется вносить изменения в SimpleColumn


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

U>Сейчас на мой взгляд лучшее решение такое:


U>
U>           new SimpleColumn<RowLink>("Модель",
U>              delegate(RowLink device)
U>              {
U>                return modelBox.GetModel(Passport2.Model.GetValue(device));
U>              },
U>              GridExt.CharWidth(20), GridExt.HAlignment(true),
U>              GridExt.CellFiller(ComboGridCellFiller.Default),
U>              GridExt.ComboItems(modelBox.AllModels)),
U>


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

В данном примере типы неизвестны или частично неизвестны в 19 местах!!!
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: LINQ как шаг к функциональному программированию
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 22.01.09 07:53
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

ЧВV>LINQ как шаг к функциональному программированию
Автор(ы): Чистяков Влад (VladD2)
Дата: 26.01.2009
Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
Кроме того, эта статья дает некоторое понимание того, как работает «LONQ to Object» и на каких принципах он основан.


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


Функциональное вычисление – функция (или если быть точнее – «чистая функция», pure function) – должна принимать некоторые аргументы (входящие данные) на входе, производить вычисление и возвращать некоторый результат. При этом функция не должна создавать никаких побочных эффектов... В общем, функция не имеет право делать ничего, что могло бы изменить состояние чего бы то ни было. Все, что может сделать функция – это произвести вычисления и выдать результат.

У такого подхода есть одна замечательная особенность. Функция всегда должна возвращать один и тот же результат для одних и тех же аргументов.

Если это следствие перечисленного, то неверно, когда функция может читать изменяемые данные (глобальные или в замыкании).

ФЯ развивают эту идею, возводя ее в принцип – функция является в программе таким же полноценным объектом, как и экземпляр любого другого типа (например, экземпляр строки).

Сразу вопросы: можно ли функции сравнивать на равенство? Можно ли их сериализовать в файл? Вычислять хэш? Если нет, то не такие уж и полноценные объекты. Если да, возможно, стоит об этом упомянуть.

Скажем, в С мы можем передать указатель на функцию другой функции, но составить из двух функций третью мы не в силах.


typedef int (*func)(int);
int compose(func a, func b, int x)
{
    return a(b(x));
}



Первое, что требуется для манипуляции функциями – это иметь возможность описать их тип.

Неверно, если речь про ФЯ в целом. Как-то Лисп без этого обошелся.

И пара опечаток:

arg1 => arg2.ToString()

СПИСОК_ПОЛЕ_ПЕРЕЧИСЛЕННЫХ_ЧЕРЕЗ_ЗАПЯТУЮ

Re[10]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 22.01.09 07:56
Оценка:
Здравствуйте, hugo, Вы писали:

U>>проще читается и модифицируется, нежели канонический:

H>Я, наверное, еще очень молодой, но ИМХО этот код не читается вообще .

Объясни почему такой код по-твоему читабелен:

      void CreateHeightModifyPanelSynchronizer()
      {
        LightSynchronizer<int> sync = new LightSynchronizer<int>(this,
          delegate
          {
            return modifyDeviceGridSynch.VisibleDataRegion.Height;
          },
          delegate (int visibleHeight)
          {
            int rowHeight = modifyDeviceGridSynch.RowHeight;
            modifyDevicePanel.Height = modifyDevicePanel.Height + (rowHeight - visibleHeight);
          },
          TimeSpan.FromMilliseconds(100));
      }
...
      CreateHeightModifyPanelSynchronizer();


а такой нет:

      if (true)
      {
        LightSynchronizer<int> heightModifyPanelSync = new LightSynchronizer<int>(this,
          delegate
          {
            return modifyDeviceGridSynch.VisibleDataRegion.Height;
          },
          delegate (int visibleHeight)
          {
            int rowHeight = modifyDeviceGridSynch.RowHeight;
            modifyDevicePanel.Height = modifyDevicePanel.Height + (rowHeight - visibleHeight);
          },
          TimeSpan.FromMilliseconds(100));
      }


Информация тут одна и та же, словесный смысл действия в первом варианте ты получаешь из названия метода, во втором из названия создаваемой переменной.

При этом чтение/модификация кода в первом случае сводится к постоянным Go To Definition и Ctrl+-, а во-втором случае для перемещения по коду достаточно колеса мыши.
Re[11]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 09:28
Оценка:
Здравствуйте, Ziaw, Вы писали:

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


Не понял, почему приходится? Кто-то заставляет? Если не важно, то не думай, в чем проблема?
лэт ми спик фром май харт
Re[12]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 09:29
Оценка:
Здравствуйте, Undying, Вы писали:

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


+1
Причем intellicence доступен далеко не всегда. Например, он недоступен при мержевании, или сравнении версий исходников.
лэт ми спик фром май харт
Re[13]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 09:32
Оценка:
Здравствуйте, MxKazan, Вы писали:

MK>Да, да. И это тоже при-выч-ка. Ну не можешь без точного типа и всё тут. А нужно просто расслабиться и получать удовольствие Просто попробуй не замечать var — ну есть переменная и Слава Богу! Со временем, привычка "искать тип" уйдет и var начнет нравицца


Знание типов необходимо, чтобы знать, что именно делает этот код. Название методов не несет всех требуемых нюансов.
лэт ми спик фром май харт
Re[12]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 22.01.09 09:34
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Не знаю как на счет дураков. Но твой код надо писать уж тогда еще прикольнее:

VD>
VD>delegate
VD>{
VD>  t1 x1 = modifyDeviceGridSynch;
VD>  t2 x2 = x1.VisibleDataRegion;
VD>  int result = x2.Height;
VD>  return result;
VD>}
VD>

VD>Потому как типы всех промежуточных значений так же не известны из контекста.
VD>Паранойя? Однозначно! Но это ваша, сударь, паранойя.

Ты в своем репертуаре
Автор: VoidEx
Дата: 21.01.09
— "давайте доведем мысль оппонента до абсурда, а потом с блеском ее опровергнем".

Я утверждал, что знание типов упрощает понимание кода. Я нигде не утверждал, что любая форма добавления информации о типах в код (например, создание для этого временных переменных) заведомо улучшает читабельность кода.
Re[15]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 09:39
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Я пока мне не докажут обратного, я буду считать, что Шарик собака. Если я узнаю, что в моей программе кто-то назвал кошку Шариком я буду сильно ругаться, вне зависимости, указал он явно что это кошка или это вывел компилятор.


Замени "Шарик" на "Васька".
лэт ми спик фром май харт
Re[15]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 09:40
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Я пока мне не докажут обратного, я буду считать, что Шарик собака.


Из-за этого баг, который сидит где-то в методе кошки, ты будешь упорно и безрезультатно искать в собаке.
лэт ми спик фром май харт
Re[14]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 22.01.09 09:46
Оценка:
Здравствуйте, mrTwister, Вы писали:

Z>>Нам не важен конкретный тип переменной. Нам важен лишь смысл вызовов методов, его можно понять не зная конкретного типа.


T>А если общего смысла недостаточно, а надо знать нюансы, так как где-то баг?


Тогда шаримся в нюансах, дебажим и т.п. Типы переменных на виду это очень незначительная толика нюансов.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[16]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 22.01.09 09:51
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Замени "Шарик" на "Васька".


Нужно учиться писать код, чтобы он не выглядел двусмысленным. Ставить вместо этого подпорки в виде аннотаций типов не имеет никакого смысла.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[17]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 09:51
Оценка:
Здравствуйте, VladD2, Вы писали:

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


Вот пренебрежения правилами читаемости и непротиворечивости текста и вдет к тому, что: "Отладчик — это наше всё!!! "
лэт ми спик фром май харт
Re[16]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 22.01.09 09:54
Оценка:
Здравствуйте, mrTwister, Вы писали:

Z>>Я пока мне не докажут обратного, я буду считать, что Шарик собака.


T>Из-за этого баг, который сидит где-то в методе кошки, ты будешь упорно и безрезультатно искать в собаке.


У меня есть IDE, я сначала попадаю в нужный метод, а потом выясняю какому же классу он принадлежит.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[18]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 22.01.09 09:58
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Вот пренебрежения правилами читаемости и непротиворечивости текста и вдет к тому, что: "Отладчик — это наше всё!!! "


Андаинг приводит такие шедевры читабельности, что просто диву даешься. Может быть у вас найдется хороший пример, где var делает код двусмысленным, а явное указание снимает данный недостаток?
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[13]: LINQ как шаг к функциональному программированию
От: hugo Австрия  
Дата: 22.01.09 10:03
Оценка:
Здравствуйте, Undying, Вы писали:


VD>>Паранойя? Однозначно! Но это ваша, сударь, паранойя.


U>Ты в своем репертуаре
Автор: VoidEx
Дата: 21.01.09
— "давайте доведем мысль оппонента до абсурда, а потом с блеском ее опровергнем".




Ты сам только что сделал что-то похожее здесь
Автор: Undying
Дата: 22.01.09
Re[10]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 10:03
Оценка:
Здравствуйте, Ziggi111, Вы писали:

Z>Можно. Ибо как уже писали выше, если функции обзывать не как попало, то всё понятно и без intellisense. Ну если конечно функция Дай_Хлеб() не возвращает колесо_от_самолёта.


Что возвращает "ExecuteSupercalifragilisticexpialidocious()"?
лэт ми спик фром май харт
Re[10]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 10:06
Оценка:
Здравствуйте, hugo, Вы писали:

H>На Erlang нет ни одного варианта, просто нету анотаций типов. Мне не мешает.


С чего ты взял, что тебе это не мешает, ведь ты не пробовал программировать на эрланге с аннотацией типов?
лэт ми спик фром май харт
Re[19]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 22.01.09 10:08
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>А еще лучше писать так, чтобы ошибку было видно и без отладчика.


Полностью согласен. Только явно указаные типы в этом не помогают никак.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[17]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 10:19
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>У меня есть IDE, я сначала попадаю в нужный метод, а потом выясняю какому же классу он принадлежит.


Отладчик не всегда доступен.
лэт ми спик фром май харт
Re[18]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 22.01.09 10:20
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Ага, это все равно, что написать: "надо учиться писать код, чтобы в нём не было багов. Ставить вместо этого подпорки в виде статической типизации, автоматического управления памятью и пр. не имеет никакого смысла". С идеей, конечно, не поспоришь, но пользы от неё никакой.


Кто-то спорит с пользой статической типизации, сборки мусора и пр.?
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[18]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 22.01.09 10:21
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Отладчик не всегда доступен.


IDE тоже?
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[19]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 10:36
Оценка:
Здравствуйте, Ziaw, Вы писали:

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


var что-то_непонятное = GetЧтоТоНепонятное();
лэт ми спик фром май харт
Re[19]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 10:37
Оценка:
Здравствуйте, Ziaw, Вы писали:

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


T>>Отладчик не всегда доступен.


Z>IDE тоже?


И IDE тоже. Я уже приводил пример: merge/compare
лэт ми спик фром май харт
Re[14]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 22.01.09 10:39
Оценка:
Здравствуйте, hugo, Вы писали:

U>>Ты в своем репертуаре
Автор: VoidEx
Дата: 21.01.09
— "давайте доведем мысль оппонента до абсурда, а потом с блеском ее опровергнем".


H>Ты сам только что сделал что-то похожее здесь
Автор: Undying
Дата: 22.01.09


И в чем это выражалось?
Re[20]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 22.01.09 10:40
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>var что-то_непонятное = GetЧтоТоНепонятное();


Ну будет
ЧтоТоНепонятное что-то_непонятное = GetЧтоТоНепонятное();

Легче стало?
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[11]: LINQ как шаг к функциональному программированию
От: hugo Австрия  
Дата: 22.01.09 10:43
Оценка:
Здравствуйте, mrTwister, Вы писали:

H>>На Erlang нет ни одного варианта, просто нету анотаций типов. Мне не мешает.


T>С чего ты взял, что тебе это не мешает, ведь ты не пробовал программировать на эрланге с аннотацией типов?


А ты пробовал? С чего ты взял, что мне это надо попробовать именно на Erlang? На то есть С++, С#, Obj-C и другие, где есть аннотация типов. Везде синтаксис задания типа практически одинаковый. В чем вообще смысл вопроса?
Re[21]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 10:47
Оценка:
Здравствуйте, Ziaw, Вы писали:

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


T>>var что-то_непонятное = GetЧтоТоНепонятное();


Z>Ну будет

Z>
Z>ЧтоТоНепонятное что-то_непонятное = GetЧтоТоНепонятное();
Z>

Z>Легче стало?

Стало, но не на много. По крайней мере можно открыть ЧтоТоНепонятное.cs и посмотреть, что там внутри.
Но случаи разные бывают. Не всегда имена методов идеальны, или не всегда понятна логика их работы. Вот еще пример:

var result = ValidateOrderLines(order);
Serialize(result);

лэт ми спик фром май харт
Re[12]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 10:49
Оценка:
Здравствуйте, hugo, Вы писали:

T>>С чего ты взял, что тебе это не мешает, ведь ты не пробовал программировать на эрланге с аннотацией типов?


H>А ты пробовал?


Нет, по-этому про эрланг я ничего и не пишу.
лэт ми спик фром май харт
Re[20]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 22.01.09 10:57
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>И IDE тоже. Я уже приводил пример: merge/compare


Вероятность в сложном merge избавиться от загрузки IDE благодаря аннотации типов стремится к нулю.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[22]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 22.01.09 10:57
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>

T>var result = ValidateOrderLines(order);
T>Serialize(result);


А а такой код тебя не смущает?
[с#]
Serialize(ValidateOrderLines(order));
[c#]
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[23]: LINQ как шаг к функциональному программированию
От: mrTwister Россия  
Дата: 22.01.09 11:10
Оценка:
Здравствуйте, Ziaw, Вы писали:

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


T>>

T>>var result = ValidateOrderLines(order);
T>>Serialize(result);


Z>А а такой код тебя не смущает?

Z>[с#]
Z>Serialize(ValidateOrderLines(order));
Z>[c#]

Этот код во-первых, хотя бы очень короткий, а во-вторых, не вводит переменную, которая непонятно как и для чего используется.
лэт ми спик фром май харт
Re[13]: LINQ как шаг к функциональному программированию
От: hugo Австрия  
Дата: 22.01.09 11:19
Оценка:
Здравствуйте, mrTwister, Вы писали:

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


T>>>С чего ты взял, что тебе это не мешает, ведь ты не пробовал программировать на эрланге с аннотацией типов?


H>>А ты пробовал?


T>Нет, по-этому про эрланг я ничего и не пишу.


А про что ты вообще пишешь? Я не понимаю смысла сказанного тобой Мне не нужно использовать аннотацию типов именно на Erlang, чтобы убедиться в том, что ее отсутствие там мне не мешает. Для этого мне достаточно опыта программирования на других языках, где она есть.
Re[24]: LINQ как шаг к функциональному программированию
От: Ziaw Россия  
Дата: 22.01.09 11:21
Оценка:
Здравствуйте, mrTwister, Вы писали:

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


Вот и я говорю, лучше писать короткий и понятный код без аннотаций, чем непонятный и с аннотациями. В понятном коде аннотации больше мешают, в непонятном помогают очень слабо, а зачастую и отвлекают.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[11]: LINQ как шаг к функциональному программированию
От: Aikin Беларусь kavaleu.ru
Дата: 22.01.09 11:28
Оценка:
Здравствуйте, mrTwister, Вы писали:

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


Z>>Можно. Ибо как уже писали выше, если функции обзывать не как попало, то всё понятно и без intellisense. Ну если конечно функция Дай_Хлеб() не возвращает колесо_от_самолёта.


T>Что возвращает "ExecuteSupercalifragilisticexpialidocious()"?

Судя по названию метода void. Иногда может возвращать true/false, как показатель успешности неуспешности выполения.
Re[13]: LINQ как шаг к функциональному программированию
От: drol  
Дата: 22.01.09 14:31
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Причем intellicence доступен далеко не всегда. Например, он недоступен при мержевании, или сравнении версий исходников.


Так вот это и плохо. Все version control операции (merge, compare, review и т.д.) должны выполняться в IDE, и иметь прямую и полную поддержку всех её механизмов.
Re[4]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 23.01.09 09:03
Оценка:
Здравствуйте, VladD2, Вы писали:

U>>
U>>array1.Aggregate("", (first, second) => first + ", " + second);
U>>


U>>Здесь все прозрачно и может корректно работать на любой коллекции.


VD>Лучше говоришь? Ну, тогда попробуй свой вариант в действии. Тебя ждет сюрприз.


Мда... я был лучшего мнения об MS. Разложить столько граблей в одной функции это надо уметь. Считать initialValue по сути первым элементом коллекции это сильно, но мягко говоря неочевидно. Тогда да в реализации от МS нормального решения нет, использовать Aggregate можно только так:

  string result = "";
  if (array1.Count != 0)
    result = array1.Aggregate((first, second) => first + ", " + second));


Что есть ужас.

Тем не менее написать реализацию без граблей вида Aggregate(T startValue, Func<T, T, T> func) вполне можно, но MS это не удалось.
Re[2]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.01.09 16:20
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>

Функциональное вычисление – функция (или если быть точнее – «чистая функция», pure function) – должна принимать некоторые аргументы (входящие данные) на входе, производить вычисление и возвращать некоторый результат. При этом функция не должна создавать никаких побочных эффектов... В общем, функция не имеет право делать ничего, что могло бы изменить состояние чего бы то ни было. Все, что может сделать функция – это произвести вычисления и выдать результат.

DM>У такого подхода есть одна замечательная особенность. Функция всегда должна возвращать один и тот же результат для одних и тех же аргументов.

DM>Если это следствие перечисленного, то неверно, когда функция может читать изменяемые данные (глобальные или в замыкании).

Слона выделенного жирным ты не заметил?

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

DM>

ФЯ развивают эту идею, возводя ее в принцип – функция является в программе таким же полноценным объектом, как и экземпляр любого другого типа (например, экземпляр строки).

DM>Сразу вопросы: можно ли функции сравнивать на равенство?

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

DM>Можно ли их сериализовать в файл?


Потенциально — да, но на практике этого никто не делает, так как это лишено смысла. Сериализация не является обязательной для того чтобы что-то можно было признать первоклассным объектом.

DM>Вычислять хэш?


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

DM>Если нет, то не такие уж и полноценные объекты. Если да, возможно, стоит об этом упомянуть.


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

DM>

Скажем, в С мы можем передать указатель на функцию другой функции, но составить из двух функций третью мы не в силах.


DM>
DM>typedef int (*func)(int);
DM>int compose(func a, func b, int x)
DM>{
DM>    return a(b(x));
DM>}
DM>


Где здесь образована новая функция? Это статически описанная функция принимающая два указателя на функции.
Если бы С поддерживало бы создание функций из других функций, то в нем было бы можно написать такой код:

typedef int (*func)(int);
func compose(func a, func b)
{
    return a + b;
}

func f3 = compose(f1, f2);
f3(2);


DM>

Первое, что требуется для манипуляции функциями – это иметь возможность описать их тип.

DM>Неверно, если речь про ФЯ в целом. Как-то Лисп без этого обошелся.

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

DM>И пара опечаток:

DM>

arg1 => arg2.ToString()

DM>

СПИСОК_ПОЛЕ_ПЕРЕЧИСЛЕННЫХ_ЧЕРЕЗ_ЗАПЯТУЮ


Спасибо. Поправлю.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: LINQ как шаг к функциональному программированию
От: DemAS http://demas.me
Дата: 24.01.09 20:10
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

ЧВV>LINQ как шаг к функциональному программированию
Автор(ы): Чистяков Влад (VladD2)
Дата: 26.01.2009
Цель данной статьи – объяснить читателю незнакомому с ФП, что такое функциональный подход, какие он дает преимущества, и как его можно использовать с помощью LINQ и C# 3.0.
Кроме того, эта статья дает некоторое понимание того, как работает «LONQ to Object» и на каких принципах он основан.


Спасибо. Хорошая статья.
Понравилось, что статья, ориентированная на начинающих, написана простым языком.
Маленькое дополнение — хорошо бы указывать набор ПО, необходимый для того, чтобы воспроизвести данные примеры. Например, номер фреймворка, версию студии и т.д.
Кстати, я правильно понимаю, что в Mono эти возможности пока не реализованы?
Re: LINQ как шаг к функциональному программированию
От: mrUmka  
Дата: 26.01.09 12:21
Оценка:
Материал актуален и интересен, но статья очень сырая:
— Много ошибок разного характера.
— Стиль изложения ни куда негодится, читать очень сложно. Изложение текста должно быть "бесстрасным", а сейвас все выглядит, как попытка показать свое превосходство.

Реккомендация:
— Вычитывать материал несколько раз. Через день другой прочитать еще раз
— Давать читать другим перед публикацией и осмысливать критику
--
То, что вы уникальны еще не значит, что от вас есть толк
Re[2]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.01.09 13:48
Оценка:
Здравствуйте, DemAS, Вы писали:

DAS>Понравилось, что статья, ориентированная на начинающих, написана простым языком.

DAS>Маленькое дополнение — хорошо бы указывать набор ПО, необходимый для того, чтобы воспроизвести данные примеры. Например, номер фреймворка, версию студии и т.д.

ОК. Учту.

DAS>Кстати, я правильно понимаю, что в Mono эти возможности пока не реализованы?


Гарантировать ничего не могу, так как с Моно не занимаюсь. Но вроде как должно работать. Моно вообще довольно живенько за МС бежит.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: LINQ как шаг к функциональному программированию
От: _FRED_ Черногория
Дата: 27.01.09 11:48
Оценка:
Здравствуйте, Undying, Вы писали:

U>И каким образом полноценный string.Join устранит грабли при использовании Aggregate?

VD>>К сожалению именно этого ты и не увидел. Зато усмотрел проблемы у МС. Меж тем в большинстве ФЯ вообще нет аналога Aggregate не принимающего начальное значение. Так что это своего рода расширение.
U>Потому что в большинстве ФЯ решили не добавлять библиотечную функцию с заботливо разложенными граблями, в MS же не додумали. В то время как достаточно было вместо Aggregate(Func<T, T, T> func) сделать такую перегрузку:
U>Aggregate(Func<T, T, T> func, T defaultValue)

U>Такая перегрузка позволила бы прозрачным образом обрабатывать и пустую коллекцию и отсутствие коллекции(null).

Такая перегрузка
public static TAccumulate Aggregate<TSource, TAccumulate>(
    this IEnumerable<TSource> source,
    TAccumulate seed,
    Func<TAccumulate, TSource, TAccumulate> func
)

есть
Help will always be given at Hogwarts to those who ask for it.
Re[8]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 28.01.09 08:07
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>
U>>Aggregate(Func<T, T, T> func, T defaultValue)
_FR>

U>>Такая перегрузка позволила бы прозрачным образом обрабатывать и пустую коллекцию и отсутствие коллекции(null).

_FR>Такая перегрузка

_FR>
_FR>public static TAccumulate Aggregate<TSource, TAccumulate>(
_FR>    this IEnumerable<TSource> source,
_FR>    TAccumulate seed,
_FR>    Func<TAccumulate, TSource, TAccumulate> func
_FR>)
_FR>


Это разные перегрузки. Seed участвует в агрегации, а это не всегда нужно, например, string.Join на перегрузке с seed реализовать нельзя. А defaultValue в агрегации не участвует, оно просто возвращается если данных для агрегации недостаточно (т.е. коллекция пуста или равна null).
Re[9]: LINQ как шаг к функциональному программированию
От: _FRED_ Черногория
Дата: 28.01.09 08:46
Оценка:
Здравствуйте, Undying, Вы писали:

_FR>>Такая перегрузка


U>Это разные перегрузки. Seed участвует в агрегации, а это не всегда нужно, например, string.Join на перегрузке с seed реализовать нельзя.

Можно
Func<IEnumerable<string>, string> join = x => x.Skip(1).Aggregate(x.FirstOrDefault(), (y, z) => y + ", " + z);
Action<Expression<Func<IEnumerable<string>>>> print = x => Debug.Print("Join [{0}] = \"{1}\"", x.Body, join(x.Compile()()));
print(() => new string[0]);
print(() => new[] { "x", });
print(() => new[] { "a", "s", "d", "f", "g", "h" });
Help will always be given at Hogwarts to those who ask for it.
Re[10]: LINQ как шаг к функциональному программированию
От: Undying Россия  
Дата: 28.01.09 12:05
Оценка:
Здравствуйте, _FRED_, Вы писали:

U>>Это разные перегрузки. Seed участвует в агрегации, а это не всегда нужно, например, string.Join на перегрузке с seed реализовать нельзя.


_FR>Можно

_FR>
_FR>Func<IEnumerable<string>, string> join = x => x.Skip(1).Aggregate(x.FirstOrDefault(), (y, z) => y + ", " + z);
_FR>


Шаман, однако. Надеюсь в реальных проектах ты так не пишешь?
Re[11]: LINQ как шаг к функциональному программированию
От: _FRED_ Черногория
Дата: 28.01.09 12:42
Оценка:
Здравствуйте, Undying, Вы писали:

_FR>>Можно

_FR>>Func<IEnumerable<string>, string> join = x => x.Skip(1).Aggregate(x.FirstOrDefault(), (y, z) => y + ", " + z);


U>Шаман, однако. Надеюсь в реальных проектах ты так не пишешь?


Нет, в "реальных" меня устраивает String.Join

Хотя бывают заморочки, когда собрать строку надо не из строк, а из набора произвольных типов:
return Start + String.Join(Separator, Array.ConvertAll(values, value => Convert.ToString(value, provider))) + End;
// илиreturn Start + String.Join(Separator, values.Select(value => Convert.ToString(value, provider)).ToArray()) + End;

Правда сейчас это только в генерируемом коде. Но не вижу причим тому, что бы не допускать подобное и в "рукописном".
Help will always be given at Hogwarts to those who ask for it.
Re[11]: LINQ как шаг к функциональному программированию
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.01.09 04:47
Оценка:
Здравствуйте, Undying, Вы писали:

_FR>>Можно

_FR>>
_FR>>Func<IEnumerable<string>, string> join = x => x.Skip(1).Aggregate(x.FirstOrDefault(), (y, z) => y + ", " + z);
_FR>>


U>Шаман, однако. Надеюсь в реальных проектах ты так не пишешь?


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

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