December 25th, 2009

glider

Параллелизм мозга

Из литературы или из ad-hoc опыта широко известен факт о том, что human task switches are considered harmful. В моем понимании он является следствием двух вещей: 1) сознание не способно сконцентрироваться на более, чем одной задаче одновременно, 2) переключение сознания между задачами до уровня хорошей эффективности занимает значительное время - у меня на это уходит полчаса или даже больше.

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

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

***

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

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

2. Зачастую текущий таск настолько сильно захватывает, что переключать его очень не хочется. Например, мне тупо нравится программирование как возможность заставить комп делать то, что ты хочешь, и потом наслаждаться созерцанием результатов - поэтому я могу часами заниматься хакингом here and there. Та же фигня и с книжками - сидишь, читаешь и совсем не можешь оторваться.

3. Нежелание что-то делать из-за блокера. Время от времени так случается, что никаких активных тасков нет, но делать все равно ничего не хочется. Дело может быть в банальной усталости (пункт 1) или в том, что переключение на какую-то таску ассоциируется с серьезным психологическим барьером. "То, что надо, не делаю потому, что очень сильно не хочется, а то, что хочется, не делаю потому, что надо делать, то, что надо" - это как раз про такую ситуацию.

***

С трудностями я собираюсь справляться следующим образом - пока что я пробовал только мелкую гранулярность таймфреймов, отводимых на таски, т.е. пытался делить день на 2-3 части. Но, как я помню себя раньше (т.е. до того, как я начал сознательно управлять своими тасками), естественным образом у меня получается работать, разделив неделю на отдельные дни - так собственно и сделаю: 1 день = (в идеале) 1 таска.

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

Наконец, для пункта 3 требуется особый подход - здесь все очень субъективно и зависит от конкретного блокера. Например, омерзение к конкретной задаче по программированию, можно побороть уклонением от нее, а кое-где просто надо включить силу воли. Еще в эту степь мне очень нравится trickle list, идея которого заключается в том, что выделяется список малюсеньких тасков, которые настолько маленькие и простые, что их никогда не будет проблематично сделать. Например - поболтать с народом вокруг, чтобы собрать слухи и интересные факты, сожрать витаминку или на один маленький шажок улучшить дизайн своего сайта.

***

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

Дополнительные проблемы - 1) как в список интересных тасков включить бытовуху, а также возможные неприятные вещи типо необходимости общения с кастомером на работе, 2) как оценивать свой прогресс, 3) как анализировать и корректировать общее направление движения. Но об этом я подумаю уже потом - всего понемножку.
glider

Первый год сознательного творчества

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

Из постов серии можно узнать о следующем: 1) несколько проекций моего видения идеального программирования, 2) описание open-source проектов, которыми я занимался в этом году, 3) саммари моего опыта за этот год (ессно, тут не будет каких-то технологий, ибо это неинтересно, а будут приемы и техники, которыми я обогатил свое видение программирования). Плюс, в конце серии описано интересное исследование, которым сейчас занимаюсь в аспирантуре НАН РБ - разработка кросскомпилятора программ на дотнете в код, исполняемый на видеокартах.

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

Мое видение программирования

Этот пост - одна из частей моего рассказа о том, чем я занимался и чему я научился за 2009й год. В индексном посте серии можно прочитать саммари сгенеренного текста и заиметь линки на отдельные посты.

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

Вот почему я тащусь от квиксорта в две строчки (хоть он и не является хорошим примером функционального программирования - спасибо antilamer за это замечание), функциональной композиции и доменно-специфических языков. И поэтому же терпеть не могу низкоуровневые API, на которых пишут живые люди, текстогенераторы и программирование на XML.

Здесь я очень благодарен Саше, который открыл мне глаза на вещи, которые я считал эталоном хорошего программирования - язык C#, дизайн-паттерны, намеренная verbosity в угоду тому, что так делают все. Оказалось, что в мире программирования есть концепции настолько более изящные, что они ставят под сомнение не только целесообразность, но и вообще существование вещей, упомянутых выше. Жаль, конечно, что в рассказе о красивых вещах приходится идти от противного, но так получится ярче всего.

***

Рассмотрим мирок, который буквально лет 5-10 назад активно пропагандировался идеологами разработки софта (к слову, в нем и по сей день находится куча людей, даже не подозревая о том, что они обмануты). Он выражается несложной формулой - "ООП есть инкапсуляция, наследование и полиморфизм, выраженные в статически типизированном языке" и легко транслируется через бложеки, книжки и туториалы. Вроде бы все ничего - писать программы таким образом можно, кастомеры довольны, и все идет по плану. Но при ближайшем рассмотрении альтернативных концепций становится заметно, что системы, разработанные при помощи мейнстримного "ООП" (пишу в кавычках, ибо такое "ООП" - это совсем не то ООП, которое провозглашал Алан Кей) имеют концептуальные недостатки.

Итак, имеем: грубую гранулярность (идеально гибкими являются лишь сочленения в виде взаимных ссылок объектов, а на уровне отдельных методов композируемость пропадает, подробнее об этом можно почитать вот здесь), а также зачастую для выражения простой мысли необходимо слишком много синтаксического шума - несколько ярких примеров описаны в первом разделе статьи на Haskell wiki.

Соответственно, много эксерсайзов по борьбе с ограничениями "ООП" - абсолютно бессмысленное приложение творческой энергии. При знакомстве в более совершенными концепциями приходит понимание того, что 90% наунов из Джаваланда (очень рекомендую эту ссылку!) отпадают, а набор костылей, широко известный нам под названием Design Patterns, совсем не нужен.

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

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

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

***

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

Если можно не писать класс, а написать лямбду - пишем. Если можно проанализировать код и что-то вывести вместо того, чтобы писать явно - анализируем и генерим (см. мои каменты к посту Аенде - я там постился под именем Eugene). FluentNHibernate прекрасен. Code as data великолепен. Если какой-то фреймворк или тул для разработки не подходит под этот императив, каким бы он ни был известным или типо крутым - он не рулит, думаем, как это исправить.

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

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

***

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

Это объясняет, почему over-engineering может порождать проблемы. Устраненное дублирование через кучу всяких интерфейсиков и классиков, сценарии юнит-тестов, разнесенные по пачке классов и методов - в большинстве случаев они порождают неприятное ощущение не потому, что содержат один из задокументированных в книжке запахов, а просто потому, что не так выразительны, как их возможные аналоги.
glider

Мои проекты за год

Этот пост - одна из частей моего рассказа о том, чем я занимался и чему я научился за 2009й год. В индексном посте серии можно прочитать саммари сгенеренного текста и заиметь линки на отдельные посты.

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

First, and foremost - so far I view my projects as something that releases my internal idea-generator preferably with the least possible effort. They make me learn new practices, make me adopt new ways of thinking about programming, and sometimes get fleshed out as something useful to someone except their author.

My programming guru Alex always told me that it's better to test 10 ideas with rough and ugly code (that however has solid backbone, so that less qualified people can cut out it without breaking the main idea), and crystallize them in a single shiny jewel, rather than materialize 5 ideas in what is commonly considered to be "good" code: 100% coverage, little to no ugliness in the small, perfect architecture in the large.

***Implications***

1) Since most of all I value the ideas and their concise and beautiful expression, this is what gets most of my attention. Other things, like fighting with spaghetti that doesn't stand in the way of my ideas, or splitting code in a set of perfectly coherent and lightly coupled components get secondary priority. After all I have a full-time job and some RL, so unfortunately the time I dedicate to my projects is quite finite.

2) That's why a good percentage of my code might be more or less sloppy, not covered with unit-tests (what's more - since I'm still studying I've yet have to finalize the adoption of unit-testing techniques and integrate them into my development mindset), mostly not thread-safe, often performance-ignorant, and even containing bugs. However, I try to isolate ugly solutions (that come e.g. from harsh deadlines and my inborn weakness in planning) behind thought-out APIs (I can easily spend a day thinking out the best possible way to express the API) and firm architectural foundation. Performance-wise I'm pretty much sure (and this is backed up by my several experiences) that if it becomes necessary I'll be able to tune the speed and memset of the application up to reasonable values.

3) My way of learning something in my life is playing with contrasts so I might be overdoing things I learn, e.g. applying functional-style coding even over common sense. Regarding the example with FP-style, I'd love to refactor some of my code to apply e.g. lambdas and call-chaining in more liberal way, so that it doesn't hinder debuggability and readability, tho I understand that I'll never have time for this. Hope the source code in my projects is understandable to someone except me.

***Show me the code***

Without much ado, here are all of my published OSS projects: http://code.google.com/u/xeno.by/. I'd love to get any feedback, but here are some topics that I'd be especially delighted to hear about: 1) How do you find my programming methodology?, 2) What do you think about ideas behind my projects?, 3) How concise and fun to use do you find APIs that express those ideas?, 4) How would you suggest to improve any of my code: in particular or in general?

Elf4b. I think, this is by far the best of my public projects (I also have a working compiler of C#'s subset that includes such things as custom grammar, overload resolution and type inference, but unfortunately I had to remove it from being publicly accessible). As the project's page states it's a fully-fledged script language that can be both interpreted and compiled to IL. I've also planned to develop its debugger, but later that feature went out of scope. The project also provides multiple ways to put together multiple scripts and data they process into a reusable compound. I consider this piece of software to be finalized.

DataVault. Implements an API and corresponding GUI to access and modify hierarchical storage for arbitrary data with metadata. Storage can use multiple formats that include zip and plain fs styles. It began as a simple utility designed to conveniently store, access, and manually browse complex configs of moderate size. Now it has quite rich feature set and unfortunately quite a convoluted codebase that I think has bogged down in side-effects. However since it had been actively used in several commercial projects, it also has undergone significant testing and performance optimization, and it also has loads of unit-tests that somewhat aid me in not breaking working code every time I introduce something new. What I'd love to improve is to tame side-effects and memory usage, upgrade events API, and to
implement transactions in STM style.

XenoGears My bag of tricks I use in everyday coding. This is quite a mixed up utils library that includes: extensions to SQO, my vision of better events for .NET, better IL emit and parse, weak and observable collections, object graph logger, and actually loads of other stuff. Probably the least structured of my projects, since it's in constant flux due to being used with multiple projects simultaneously. I have no even approximate roadmap on this - well I'd love to add a decompiler there (for using in situations like at 1093th line (omg what a number!) of http://code.google.com/p/vsdslplotter/source/browse/trunk/DslPlotter/Impl/DslModel.cs?r150), but who knows when I will have time to do this.

I'll highlight other projects in much less detail. Rapt was my first ever OSS idea and it's still early in its infancy (SMT solver - one of insane ideas Alex taught me and showed how to use in practice). VsDslPlotter is anAPI to VS 2005/2008 DSL Tools that provides a better way to deal with models and also exposed a reusable winforms control that's capable of reading/writing/presenting DSL diagrams. TeslaDomainModel is a failed attempt to unite DataVault-based storage and DSL-based data design UI.
glider

Саммари практического опыта

Этот пост - одна из частей моего рассказа о том, чем я занимался и чему я научился за 2009й год. В индексном посте серии можно прочитать саммари сгенеренного текста и заиметь линки на отдельные посты.

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

Несколько поинтов ниже - это, по сути, экстракт самых важных мыслей из knowledge base, которую я веду в ВанНоуте. После некоторого размышления я решил запостить ее в паблик - так что, если интересно, можно глянуть: kb по общим вопросам, kb по вопросам архитектуры enterprise программ. Дисклеймер все тот же - текст может быть очень наивным, может тупо не соответствовать истине, за фидбэк скажу спасибо, ругательства не по сути не приветствуются.

Новое для меня отношение к программированию

Я очень рад, что когда-то давно, выбирая между плюсами и дотнетом, я непроизвольно сделал выбор в сторону дотнета. Концепция виртуалки, ила и джита - абсолютно винрарное комбо. Оно делает возможными кучу динамических техник, которые непрактично юзать на плюсах. А это я считаю - будущее программирования. Например, выводить проверки безопасности из статического и динамического анализа кода. Или же профилировать самого себя и по статистике исполнения перегенеривать себя для оптимизации под текущий инвайронмент. Или же обеспечивать транспарентную персистентность не тупым и явным ОРМом, а анализом использований объектного графа доменных сущностей и автоматическим префетчингом связей и коллекций. Тут бездна возможностей.

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

На своем опыте я убедился, что такие идеи ОЧЕНЬ упрощают разработку корпоративного ПО. И они не являются просто мертвыми технологиями ради технологий или ради того, что я недавно почитал научную работу X или увидел фреймворк Y. А почему я щяс могу их генерировать пачками? Я ведь далеко не гений, а просто знаю пару общих вещей, которые служат мне фундаментом. Поразительно, но этого достаточно, чтобы придумывать широчайший спектр идей во всех областях программирования.

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

Да, все это возможно и в плюсах и даже в голом си. Но это так непрактично сложно и неприятно писать руками - просто prohibitively complex. Вот почему хорошая система программирования должна быть достаточно высокоуровневой, чтобы энаблить богатый образ мышления. И вот поэтому я люблю .NET, даже несмотря на то, что 1-2-3 в нем реализуются через жуткую задницу.

Новое для меня видение кодирования

Раньше мое представление хорошего кода было весьма абстрактным и основывалось на общепринятых гайдлайнах. В спринге пишут километровые xml с конфигурацией объектов прилаги - окей, это хороший код. Для вставки в прилагу новой формы нужно определить три класса, два xml-а и зарегать все в конфиге - окей, это хороший код. Ну и так далее.

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

Поэтому в своих проектах я стараюсь: 1) четко определить минимальные границы, в рамках которых может быть выражена идея, 2) задокументировать эти границы в ассертах, чтобы не забыть о них через несколько недель после написания, 3) писать минимальное количество интеграционных тестов, проверяющих корректность функционала (никакой речи не идет ни о TDD, ни о BDD, ни о стопроцентном покрытии - просто прекрасно эту мысль выражает Аенде в посте "Even tests have got to justify themselves").

***

Особенно хочу подчеркнуть важность ассертов, которые убивают сразу несколько зайцев - 1) вместе с каментами (о Боже, он пишет каменты к коду!) рассказывают о мыслях афтара кода, 2) предоставляют программисту легкий способ задокументировать возможные исключительные ситуации в программе (чем больше времени проходит между написанием кода и документацией его возможных крэшей, тем больше будет ошибок в этом процессе; ассерты здесь хороши тем, что легкостью своего написания они поощряют программиста прямо на месте предусмотреть возможные ошибки), 3) при нетривиальных ошибках точно указывают причину, по которой ошибка произошла, 4) в силу пункта #3 являются зародышами качественной обработки и представления ошибок. Вот пример кода с ассертами:

var module = t.Get("m_module").AssertCast<ModuleBuilder>();
var moduleIsCapableOfEmittingDebugInfo = module.GetSymWriter() != null;
emitDebugInfo.AssertImplies(moduleIsCapableOfEmittingDebugInfo);

Такая реализация ассертов (это третья или четвертая моя попытка) мне весьма нравится. Ассерты, объявленные в fluent-стиле в виде икстеншн-методов 1) элементарны в использовании, 2) не прерывают цепочку выражений, 3) не прерывают мысль, будучи объявляемы прямо на месте, 4) привносят минимальный синтаксический шум в кодярник. К сожалению, как бы ни был хорош статический чекер КодеКонтрактсов, я его не буду юзать исключительно по причине шумности и отвлеченности от основного кода.

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

Свой собственный словарик выразительных функций

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

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

Пример. В дотнете нет вариадик темплейтов, поэтому реализовывать таплы (tuples) очень невесело. Как способ реализации таплов, которые бы работали для любого числа параметров, а не как Action или Func, команда CLR предлагает следующий вариант: если тапл содержит более семи итемов, то он выражается таплом из 8 итемов - первые семь итемов обычные, а восьмой рекурсивно упаковывает остаток в еще один тапл. Вот как я реализовал эту логику (обратите внимание на кастомные ФВП, без которых код бы был более толстым и менее понятным):
Copy Source | Copy HTML
public static ITuple New(Object[] items, Type[] types)
{
    Func<IEnumerable<Tuple<Object, Type>>, ITuple> mkTuple = itemSpecs =>
    {
        var factories = typeof(Tuple).GetMethods(BF.PublicStatic).Where(m => m.IsGenericMethod);
        var factory = factories.Single(m => m.GetParameters().Count() == itemSpecs.Count());
        factory = factory.XMakeGenericMethod(itemSpecs.Unzip().Item2);
        return factory.Invoke(null, itemSpecs.Unzip().Item1.ToArray()).AssertCast<ITuple>();
    };
 
    // damn... that's why we need type inference to use functional style
    // upd. with introduction of "types" parameter it only became worse...
    return items.Zip(types).ChopEvery(7).FoldRight((ITuple tuple, IEnumerable<Tuple<Object, Type>> slice) =>
        mkTuple(tuple == null ? slice : slice.Concat(Tuple.New<Object, Type>(tuple, tuple.GetType()))));
}

К сожалению, практическое использование такого подхода зачастую омрачается ограниченностью сишарпа и связанного стека тулов: 1) очень неслабо раздувается список доступных методов, что ударяет по перфомансу интеллисенса студии и решарпера, 2) так как в сишарпе нет мощного тайп-инференса, то обычно приходится объявлять пачку оверлоадов: для Action, для Action<T1>, для Action<T1, T2>, для Action<T1, T2, T3>, ну и так далее пока не надоест, а еще же есть и Func..., 3) пункт #2 еще больше раздувает список методов, 4) иногда для того, чтобы удовлетворить строгую проверку типов сишарпа, приходится объявлять сложные лексические конечные автоматы (термин я выдумал сам - не ищите в нем скрытого смысла), 5) также напрягает отсутствие нативной поддержки многих элементов функционального программирования - богатого тайп-инференса, паттерн-матчинга, удобных таплов и так далее.
glider

Конфлакс

Когда-то обещал рассказать, чем я занимаюсь в аспирантуре, и вот собрался. Мы с коллегами воплощаем в жизнь Конфлакс - оптимизирующий компилятор программ для платформы .NET, который детектит параллелизм, присутствующий в алгоритме, и преобразует параллельные фрагменты в код для видеокарт, после чего выполняет получившуюся смесь на локальном компе или же на гетерогенном кластере (CPU+GPU).

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

upd. Мы уже слабали первую публичную альфа-версию Конфлакса и выложили на http://bitbucket.org/conflux/conflux. По деталям того, что она умеет, я рассказывал на конференции Application Developer Days 2010. В относительно недавнем посте я давал ссылку на слайды презентации и рассказал о том, что в слайды не вошло - например, про демонстрацию.