На днях Саймон Виллисон написал очень хороший пост про node.js. Саймону очень удаётся писать такие intro-посты про технологии, которые очень ясно передают самую суть вещей. Когда-то он так сподвиг меня взяться за изучение Джанго. Пост про node.js тоже хорошо даёт понять, почему это круто, и какое место в современной экосистеме веба он занимает. Кто ещё не слышал про node.js — начинайте читать с этого поста.
Но мой пост не об этом. Просто, одной из своих фраз Саймон напомнил мне о моей собственной мысли, которая давно не даёт мне покоя, но пока всё никак не оформлялась:
Node represents a clean slate. Twisted and EventMachine are hampered by the existence of a large number of blocking libraries for their respective languages.
Это то, почему я без восторга смотрю например на Tornado и на всякие задорные попытки запускать под ним ту же Джангу. Однако пост Саймона что-то вдруг повернул у меня в голове, и то, что раньше казалось мне проблемой, теперь кажется решением :-).
Впрочем, обо всём по порядку. (Осторожно, пост длинный!)
Две многозадачности
Мне известны всего два принципиально разных способа делать многозадачность.
Самый распространённый способ — исполнение кода в виде нескольких процессов или тредов. Неудивительно, что он появился самым первым и стал распространён: большую часть забот по распараллеливанию исполнения программы берёт на себя платформа — ОС или runtime языка. Программист же пишет код в знакомом с детства однопоточном синхронном стиле. Да, конечно есть проблемы с передачей данных между процессами, и проблемы с общими данным в тредах, но мы их как-то с грехом пополам научились решать. По крайней мере в не очень сложных случаях.
Особенно комфортно с этим подходом в веб-программировании, где специфика позволяет вообще не общаться процессам друг с другом иначе как через БД. А это просто. И именно поэтому любой PHP-программист в состоянии написать очень многозадачную программу.
Проблема этого подхода — в производительности. Её, конечно, хватает сейчас почти на всё. Но начиная с какого-то момента многопроцессная система начинает кушать просто очень много памяти. Потому что, крути ни крути, эту память приходится копировать в каждый изолированный процесс (и copy-on-write до конца не спасает). Переключение на треды решает эту проблему, но снова не до конца. С ростом количества тредов система упирается теперь уже в резко возрастающее время простоя на локах, без которых синхронно в тредах программировать невозможно. Многим наверное знакомо типичное поведение веб-систем, запущенных в тредном режиме под нагрузкой: в какой-то момент она внезапно начинает сыпать 500-ми ошибками.
А хочется-то большего. Хочется десятков тысяч одновременных клиентов и тысяч RPS.
С такими нагрузками справляются системы, написанные в асинхронном стиле. Как только мы отдаём IO на откуп ОС и не блокируем свой процесс, у нас высвобождается куча времени: ведь очень много веб-приложений ничего очень долгого и умного не делают, кроме того, что плюют небольшой 20-килобайтный кусочек HTML'а в сокет. И этого "довольно много" на самом деле настолько много, что мы в состоянии обработать тысячи клиентов одним процессом, просто бегая по ним в цикле. И поэтому тривиальные "hello-world'ы" на Tornado уделывают любой многопроцессный сервер.
Проблема асинхронных систем
Но счастья нет и здесь. Проблемы начинаются, когда приложению нет-нет, да и приходится делать что-то сколько-нибудь долгое. Например получить из БД довольно большой и неудобный кусок данных и перегруппировать его императивными средствами. Или ужать картинку. Или обратиться сходить по URL'у на чужой сервер. Или отослать email. Или распарсить большой XML.
Как только однопоточной программе, обслуживающей в цикле десять тысяч клиентов, приходится ради одного из них задержаться на, скажем, секундочку, эту секундочку ждут все остальные. Если таких "требовательных" набрался десяток — всё, ни один клиент не получит ответ раньше, чем через десять секунд. Решение не масштабируется на реальные задачи, как говорят у них в бизнесе.
Обойти это можно, только если любые долгие операции как-то так переписать, чтобы они не блокировали выполнение основной задачи. Причём, как именно это делать, в общем-то, понятно. Можно уводить их в отдельные процессы-обработчики, можно использовать асинхронный IO — всё это уже опробовано. Но штука в том, что тот код, которым мы пользуемся сейчас — наши любимые библиотеки, которые парсят нам XML и отсылают письма, уже написаны в синхронном стиле.
Причём нам тут в вебе ещё повезло, у нас вся архитектура строится вокруг модели коротеньких ответов, и именно поэтому нам до сих пор удавалось держать десятки и сотни RPS с помощью традиционной многопроцессности. А вот если мы посмотрим, например, в сторону десктопного софта, мы увидим, что там похожая проблема стоит ещё острее. Какое-то время назад хардварные ребята показали нам фигу и сказали, что им поднадоело издеваться над кремнием в поисках там ещё бо́льших гигагерц, и единственное, что они могут нам предложить теперь — это 2 (или 4, или 32) параллельных ядра, и если мы хотим, чтобы наши программы работали быстрее, нам придётся придумать, как их использовать.
Однако десктопный мир полон софта, который написан в абсолютно синхронном стиле под один процессор. И от того, что мы запустим, скажем, две копии каталогизатора фотографий, они не прочитают содержимое флешки с фотками в два раза быстрее (сходите проверьте, если не верите).
Все эти наблюдения приводят к одному интересному выводу.
Если мы хотим, чтобы компьютеры работали значительно быстрее, нам придётся всё переписать в асинхронном стиле.
И вот знаете, я теперь как-то думаю, что это не проблема, а как раз решение. Думаю я так, потому что кажется умные дядьки, у которых есть время и способности думать над такими вещами, нащупали то, как именно надо писать многозадачные программы, чтобы программисты при это оставались в здравом рассудке. Поэтому я, чёрт возьми, завидую следующим поколениями программистов. Потому что переписать что-нибудь с нуля мы все иной раз не прочь, но в этом случае у них будут на это реальные основания.
Вот вам прямо из головы задачка: асинхронный параллельный парсинг XML. Как мы сейчас парсим XML:
- Читаем данные из сокета. Как ни странно, это часть всей целиковой задачи по парсингу XML'а, просто по факту того, что в большинстве случаев собственно парсинг и приём случаются в одном и том же месте программы.
- Разбиваем входной поток на лексемы
- Обрабатываем их парсером.
- Строим дерево.
Жутко же неэффективно! Почему лексинг/парсинг уже полученного куска данных должен блокировать получение следующего куска? Почему бы лексинг разных кусков не делать в несколько потоков (map), которые потом объединять в единый парсинг (reduce), причём возможно тоже в несколько потоков? Зачем нам дерево, если в большинстве случаев пользователь всё равно будет на основе дерева составлять свои структуры — давайте придумаем удобную обработку элементов в SAX-стиле.
Всё это не так просто, но кажется очень интересным.
Язык
Я думаю, что большое значение имеет то, какой именно язык выбрать для глобального переписывания всего. Те объектные императивные языки, которыми мы с успехом пользуемся сейчас, кажется, не смогут выжить в новом мире, так же, как, например, C++ не стал мейнстримным языком веб-программирования, когда оно вылезло из коротких штанишек. Да, на Плюсах можно писать веб, никто не спорит. Но это просто неэффективно.
Мой любимый Питон по определению теряет здесь одно из своих больших преимуществ — большое количество написанных библиотек. Как раз потому, что именно их и надо все переписать. Зато его не сильно заметные сейчас недостатки — GIL и отсутствие полноценных анонимных блоков кода — магическим образом вырастают в размерах и вполне могут оказаться решающими.
Так чем тогда пользоваться? У меня в мыслях есть несколько кандидатов, каждый из которых имеет шансы стать Главным Языком Десятилетия. Какой выиграет, сказать не возьмусь, просто потому, что это зависит не только от качеств самих языков, но и просто от того, кому больше повезёт с хайпом, поддержкой и логотипом.
Пользуясь случаем, направляю вас заодно на цикл статей Concur.next, где Тим Брей обсуждает ту же языковую проблему существенно подробней. Собственно, я с ним согласен чуть менее, чем полностью, поэтому мысли мои здесь не оригинальны.
Haskell
Как многие говорят, функциональная природа языка — почти обязательное условие хорошей распараллеливаемости. Как только у вас есть неменяющиеся данные, вы, теоретически, избавляетесь от проблем с традиционным программированием с локами. Опять же теоретически, имея ленивые функции без сторонних эффектов, компилятор может в большой степени сам принимать решения о том, что и как можно параллелить. Я, впрочем, не большой знаток этого аспекта Haskell'а (да и остальных тоже :-)), поэтому могу тут здорово ошибаться.
В минусы языку записывается его большая сложность. Которая, в общем-то, убивает почти вся перспективу: если языком не можем пользоваться мы — туповатые инженеры — то писать и развивать библиотеки для реального мира становится некому.
Erlang
Как и Haskell, Erlang — язык функциональный. Но главное, там всё программирование происходит в терминах создания асинхронных процессов, и поэтому писать на нём асинхронные программы получается естественно.
Язык, однако, архаичен и странен. Кроме того, маленькое коммьюнити тоже не дают думать о том, что он когда-то прочно войдёт в мейнстрим. Впрочем, совсем помереть ему тоже не дадут, хотя бы потому, что CouchDB уже нужна всем, а написана как раз на Erlang.
GCD + Си с блоками
Apple придумала расширение к Си в виде анонимных блоков и сделала работающий общесистемный пул тредов — GCD. А это ключевые компоненты асинхронного программирования. Си — низкоуровневый язык, компилируемый в нативный код, который работает очень быстро. Да и поддержка Apple стоит многого.
Главный же минус Си в том же, в чём и плюс — он низкоуровневый. А также совсем не функциональный, и без автоматического управления памятью. Вполне может оказаться, что на Си с блоками будет программировать одновременно и долго, и сложно, и багоопасно.
Javascript
Удивлены? Я не случайно начал пост со ссылки на пост про node.js. Одна из мыслей Саймона в том, что Javascript совсем неплох, как язык для асинхронного программирования. Анонимные блоки кода там есть. Да и не отнять, что сейчас весь ajax пишется на Javascript именно в асинхронном стиле.
Минусы — та же императивность и, что наверное ещё хуже, отсутствие модульности. Если что и губит этот хороший язык прямо сейчас — это общее глобальное пространство имён и отсутствие стандартного способа сделать импорт библиотеки.
Clojure
И вот оно — моё любимое слово последней недели (кстати, по-русски я её как-то сразу стал называть "кложура" с ударением на последний слог). Про Clojure я узнал у того же Тима Брея. Потом пошёл на сайт, посмотрел на несколько выступлений Рича Хики об этом языке, и всё — по уши в него влюблён. (В язык, не в Рича :-) ).
Clojure — это Лисп. И для меня это плюс. Когда-то я лиспами заинтересовался, и стал тем, кого "скобочки не напрягают", мне очень нравится идея code-as-data. Хотя я понимаю, что это не для всех, но вы, ребята, сами виноваты :-).
Однако, уж если я вменил архаичность Erlang'у, то про Лиспы можно сказать то же самое, если не в большей степени. Но Clojure — это современный Лисп. Там есть не только списки, но и например нативные векторы и словари (задаваемые литерально фигурными скобками). Там нет проблем с юникодом (о чём чуть позже), и там много удобных макросов. То есть это Лисп, который придумали недавно, а не в конце пятидесятых.
Главная же фишка Clojure — это ориентация на многопоточность. Все структуры данных там неизменяемы (да, словари тоже), что даёт возможность распараллеливать доступ к ним вообще без локов. Эти неизменяемые структуры данных умеют очень дёшево дублироваться без использования полного копирования, что делает их быстрыми. И в языке есть несколько синтаксических конструкций, позволяющих явно задавать асинхронное выполнение и транзакции для связанных изменений. Всё это обязательно стоит послушать и посмотреть в оригинале в выступлении Рича Хики про параллельность. Оно длинное, но того стоит — взрывает мозг напрочь!
Хотя есть у Clojure и субъективный минус: она реализована на JVM. С одной стороны это очень практично: куча библиотек, готовая инфраструктура тредов, сборки мусора и JIT-компиляции. Очень правильный юникод, опять же. Но у меня ко всей этой инфраструктуре есть субъективная нелюбовь. Несмотря на то, что JVM уже много лет, она всё ещё вызывает проблемы при установке, всё ещё занимает немеряно ресурсов, и GUI-приложения на ней всё ещё не выглядят адекватно ни в одной десктопной среде (или я ошибаюсь?). Впрочем с практической стороны это всё не так страшно, если вести речь о веб-приложениях. Там все эти потроха пользователям не видны.
Так что официально заявляю, что в будущей гонке за процессорное время мой фаворит — Clojure.
P.S.
Забавно поворачивается история, однако. Когда-то, когда Windows 95 пришла на смену Windows 3.11, одним из главных преимуществ новой архитектуры было то, что вместо кооперативной многозадачности, когда каждое приложение должно было само давать работать другим, применялась вытесняющая многозадачность, когда время на процессы жёстко распределялось системой.
А теперь посмотрите, куда мы пришли. Выясняется, что внешняя система не в состоянии рулить своими процессами максимально эффективно, не зная их семантики. Хочешь независимого исполнения — делай копии всей памяти на каждый процесс, даже если каждому из них нужны лишь мизерные её доли. Жалко памяти — обвешивай доступ к любым системным объектам локами. И не получится оптимизировать раздачу времени процессам так, чтобы они по возможности использовали независимые ресурсы системы. Потому что для этого надо знать, что конкретно процессы собираются сейчас делать.
Поэтому мы снова возвращаемся к тому, что процессы сами должны управлять своим распараллеливанием. А это — та самая кооперативная многозадачность. Хотя, конечно, существенно более сложная и безопасная, чем в Windows 3.11, и с другими языковыми средствами. Но забавно :-).
Комментарии: 88
Очень хорошая заметка :)
А в чем, по вашему, архаичность Эрланга?
Я бы еще в плюсы кложуре записал то, что она может связываться с другими языками, крутящимися поверх JVM, особенно со Scala, который (имхо) тоже имеет большое будущее.
К вопросу о Haskell - без дополнительных действий (явного указания/специальных структур данных) его нельзя параллелить, хотя бы потому что ленивость используется для бесконечных списков.
Вообще асинхронность и тредность - это парадигмы, которые имеют разные области применимости.
Тредность - мало параллельных задач, задачи долгоживущие. Например, необходимость делать долгие вычисления не замораживая пользовательский интерфейс. Т.е. задач априори больше чем процессорного времени, цель - распределить время равномерно, накладные расходы не очень беспокоят.
Асинхронность - много параллельных задач, задачи короткоживущие. Например, вебсервер. Задач меньше чем процессорного времени (иначе покупается еще один сервер), цель - увеличить эффективность использования процессора.
Поэтому обязательно останутся обе парадигмы. Однако в такой специфичной области как веб-программирование очевидно произойдет смена парадигмы с тредной на асинхронную.
Ну, добро пожаловать в клуб :-)
Я с clojure в ленивом режиме уже с пол-года вожусь. Очень хорошая вещь :)
чтобы получить анонимные блоки в питоне надо совсем немного подхачить парсер
Выскажусь в пользу Эрланга (ну делал я на нём диплом, обожаю этот язык :)). Выше уже спросили: в чём, по-вашему, архаичность Эрланга? На мой взгляд это вполне современный язык с достаточным количеством библиотек и более-менее вменяемым Unicode в последних версиях. И обязательно нужно учитывать, что Эрланг это целая платформа OTP, а не только язык. Дело просто в том, что, программируя на Эрланге, следует думать совершенно иначе. Лямбда-исчисление это в первую очередь логичная и аккуратная математика, которую перенесли в высокоуровневый язык программирования. Эрланг очень прост, в нём нет много того лишнего, что есть в других языках (читай: императивных), от этого может показаться, что он беден возможностями и архаичен, но это не так. Вы же не говорите, что HTML архаичен, хотя в сущности он позволяет сделать только одну вещь: описать структуру документа. Эрланг в этом плане такой же. Он очень и очень прост и позволяет сделать только одно: описать желаемый результат. Причём в терминах абсолютной распараллеленности. На мой взгляд, если где и будущее — то именно здесь. Clojure может и крут, но JVM напрочь убивает все плюсы. Виртуальная машина Эрланга же чудовищно надёжна и позволяет делать горячую замену кода (причём даже нативных функций, написанных на С). Всё, чего там не хватает — классного веб-фреймворка а-ля Джанго. А веб-серверы на чистом Эрланге уже есть (целых два) и они показывают отличные результаты, JSON давно присутствует + Mnesia и CouchDB. Ну и возможность удобно и надёжно контролировать всю инфраструктуру.
P.S. Ноги у Эрланга растут из Пролога, кстати. А ещё есть вполне рабочий и живой веб-проект на Эрланге: http://risovaska.ru/
1) Zotonic
2) Chicago Boss
http://narwhaljs.org/modules.html
Этот способ конечно не build-in в самом JS, но сильно лучше чем ничего.
А мне нравится под eventlet писать в синхронном стиле, но IO под капотом асинхронное. В эрланге, хаскеле и node.js это "из коробки", без дополнительных библиотек.
"Писать в асинхронном стиле" это уёбищный Twisted:
Иван, пожалуйста, не надо призывать нас писать в таком нечитаемом стиле. Асинхронными должны быть библиотеки; но это не стиль, это внутреннее устройство библиотеки. А писать как-раз удобно и понятно в синхронном стиле.
Кстати, в eventlet есть т.н. monkey-patching модуля socket. После этого традиционные синхронные либы на чистом питоне (например, urllib, myconnpy, pg8000) работают асинхронно. Да, либы с сишными ускорениями не пропатчишь на лету, увы.
Да, и самое главное, опять же упоминаемые Erlang и Haskell, а также Go, python-stackless, позволяют использовать именно потоки. "Традиционную" многозадачность. И всё нормально, нет проблемы 10к потоков. В двух последних есть проблема 10к connections. Она решается библиотеками.
Если учесть, что это благодаря легким потокам и асинхронному IO в runtime библиотеке языка, будет повтор предыдущего тезиса:
Возможно писать простой и понятный (потоки/процессы) код, который нормально работает с тысячами соединений.
Для этого нужно две вещи: легкие потоки и асинхронное IO. И эти фичи обязательно должны быть совмещены друг с другом на уровне языка, может быть даже синтаксиса. python-stackless даёт одно, а Twisted другое. По отдельности - убожество. А в том же Erlang эти две фичи совмещены, на лицо удобство и радость разработчиков.
P.S.: я не пропогандирую Erlang, мне тоже не нравится его архаичность, отсутствие документации, нормальных map(dict), record и, порой, стрёмные сообщения об ошибках.
что ж, поздравляю, видимо, ты пропустил golang с его goroutines как ещё одно решение проблемы многопоточности.
http://golang.org/doc/effective_go.html#concurrency
Прости, а вариант "посмотрел и не понравилось" не рассматривается? :-).
А еще у эрланга есть rabbit-mq (реализация AMQP)
И этот же AMQP очень помогает распараллеливать задачи используя питон. И есть Thrift. И тот факт, что люди меняют язык не очень охотно, скорее приведет к тому, что появятся библиотеки, помогающие распараллеливать программы намного проще, не меняя язык - надо под два ядра - запусти два питона. Просто может необходимость изучения новых "сложных" библиотек, приведет к росту доли "заточенных" языков.
Хотя это так, абстрактное рассуждение, даже без особого обдумывания темы.
Что понимается под "clean slate" в фразе "Node represents a clean slate"?
А что думаете о языке F#?
Yuri Baburov, в Go просто лёгкие потоки. Как в Erlang, Haskell и python-stackless. Это позволяет моделировать задачи в стиле "на каждый чих по потоку". При наличии хорошего шедулера на реальные OS потоки, это позволяет очень эффективно использовать проц.
Но это пол беды. Для эффективных приложений, которые в ожидании IO проводят больше времени, чем в вычислениях, ещё необходимо использовать асинхронный ввод-вывод; когда вы ждёте не каждый read/write, а сразу большую пачку и обрабатываете тот, который произойдёт раньше. Это позволяет эффективно использовать диск/сетевую карту.
Одно автоматически не означает другое. Например, в python-stackless (если я не ошибаюсь) когда один тасклет начнёт писать в сеть, он заблочит все остальные. Лёгкие потоки есть, а асинхронного IO нет. В nginx, Twisted наоборот. По-моему, в этом Иван слегка ошибся. Кинул в одну кучу наезды на толстые OS потоки и на блокирующийся IO и сделал удобный вывод. А ведь это ортогональные вещи, если рассматривать их отдельно, предложенные выводы не столь очевидны и последовательны.
Насчёт маленькой комьюнити Эрланга это Вы зря, последний год растёт как на дрожжах. Эрланг пиарят все кому не лень, начиная от упомянутой CouchDB и заканчивая 37signals, которые на нём Campfire написали. По популярности, размеру комьюнити и шумихе Erlang уж точно превосходит упомянутых Вами конкурентов (не считая JS конечно:)
Очень задела фраза о том, что JVM - это недостаток :( да это просто "state of art" среди виртуальных машин с лучшим в мире GC.
А питон надо поднимать, потому что нет другого языка, на котором было бы так приятно программировать. Надо срочно брать и писать свою реализацию Python 3k под V8 :)
Сергей, а это: http://posted-stuff.blogspot.com/2009/04/stackless-python-green-threading-and.html ?
Сергей, полностью поддерживаю вас насчёт eventlet, правда я сейчас больше склоняюсь к gevent от Дениса Биленко.
Иван, жаль, что вы не написали, каким образом в Clojure реализует конкурентное исполнение, как в этом ему помогает runtime и прочее.
Насчёт Erlang вы очень неправы — коммьюнити у него совсем не маленькое, да и язык довольно современен, к тому же OTP — это просто отличный фрэймворк для написания распределённых конкурентных приложений.
Кстати хочу заменить, что Erlang и Haskell (я имею ввиду GHC) впервую очередь отличаются и тем, что планировщики там не только коопертивные, но и вытесняющие. Это значит, что долгими вычислениями без I/O не остановить работу других в "потоках" — планировщик вытеснит текущий "поток" после n-го количества редукций в случае с Erlang или после n-ых тиков таймера в GHC.
Для меня java в сравнении с dot net покрылась паутиной :-) А если по теме то F# имеет кучу интересностей в эту сторону типа неизменяемых даннх, асинхроных workflows, мailbox proccessor и т.п. Также для всех языков на дот нет есть Parralel extensions library позволяет декларативно использовать асинхронность. Ну и исследовательский проект от MS под названием Axum. Некоторые отмечают похожесть на Erlang но это немного другая концепция.
Да в догонку Singularity как раз и демонстрировала потенциальную возможность написать все с нуля и продемонстрировать более эффективную асинхронность. Дешевые потоки и т.п.
Интересно, спасибо.
Не увидел упоминания Stackless Python. Там тоже было уделено внимание легковесной многопоточности (greenlets). Когда последний раз смотрел, там даже были какие-то асинхронные обертки над сокетами и, возможно, I/O. Более основательно, по-моему, этими проблемами заняты товарищи из проекта PyPy.
Да, в общем-то, эти возможности сейчас почти в любом новом ЯП есть - Scala actors, Google Go coroutines, ...
Кстати о Haskell. В данный момент разработка этого языка спонсируется Microsoft так как автор трудится над ним в составе MS Research. И позиционируется в первую очередь как экспериментальный не для продакшн. А все продакшн реди фишки будут плавно перекочевывать опять таки в F#. Уфф извините за кучу сообщений, за живое задели :-) я умолкаю.
http://wiki.commonjs.org/wiki/CommonJS — хотя это пока только "начинание"
cybergrind, спасибо, теперь знаю официальную позицию stackless по этому поводу. Так вот, там буквально написано, что вот вам специальный костыль, делайте monkey-patching модуля socket и получите non-blocking IO. То есть в python-stackless поддержки async IO нет и есть средство для решения этой проблемы. А теперь попробуйте придумать причину по которой этот патчинг не делается автоматически и пользователям дают возможность наступить на грабли заблочив все тасклеты без патчинга socket.
Ну и зачем тогда нужен отдельный интерпретатор, если ровно такой же подход работает с обычным CPython + eventlet? Скорость переключения потоков будет такая же, потому что eventlet использует greenlet - выжимку stackless. Сотни-тысячи сокетов eventlet (некоторые хабы) будет обрабатывать намного эффективнее, чем asyncore со своим select.
Hodzanassredin, лично по-моему, много полезных сообщений это хорошо, а MS-промывание-мозгов - плохо.
Java не может сравниваться с .NET. Как ядро Linux с Windows Server. Как Firefox c libcurl. Если у вас есть аргументированное сравнение JVM с .NET CLR - вот это интересно.
Там тоже message-passing и актёры, но немного другой, да? Axum это Erlang с доступом к .NET библиотекам. Вот когда сделали C# - копию жабы, да, надо было отрекаться, потому что скопировали говно. Здесь не надо отрекаться. Хорошую вещь скопировали.
А разработка Python спонсируется Google, т.к. Гвидо там работает, да? Это два разных факта; причинно-следственная связь, мягко говоря, натянута.
P.S.: F# - действительно хорошая, полезная штука. Если C#-говнокодеры выучат immutability, message-passing и монады, может и правда, что-то хорошее выйдет.
P.P.S.: всем остальным: извините, не удержался.
Иван, ещё, кстати, как-то в ЖЖ пролетала такая фраза, что раз в 10 лет надо переписывать заново весь стек: OS, библиотеки, сервисы, прикладные программы, опердень, всё. Тоже думаю, что это скорее не проблема, а решение.
Давайте всё же в конструктивных рамках оставаться.
Дык я о том, что тебе много чего не понравилось, но ты об этих альтернативах написал :)
А вчера сайт лежал что ли? Не мог зайти.
to Сергей Шепелев да промывка мозгов это плохо. Каюсь. Но я дот нет разработчик, я аддиктед :-)
1. Своей фразой про яву и паутину я хотел подчеркнуть свои устаревшие знания в области явы. Прошу прощение за некорректный Русский язык у меня была тройка.
2. Axum это язык который вводит понятие доменов. В пределах домена это обычная работа с объектами в стиле ООП. Но границы домена можно преодолевать только с помощью каналов. Концепция каналов по словам разработчиков была взята ими из самой большой в мире распределённой системы Web :-) Я думаю нет смысла писать подробнее так как любой может пойти на википедию и прочитать более правильное описание.
3. Действительно натянул как то не оттуда и не туда. Этим выражением я хотел подчеркнуть что мс заинтересованна в развитии Haskell и создатель языка тесно работает с ребятами из команды F#. Результаты совместной работы уже можно видеть сейчас например посмотрев на те же async workflows которые появились в f# благодаря влиянию Haskell. Так что можно надеяться что в будущем F# получит довольно интересные способности.
Кстати Simon Peyton-Jones(создатель языка Haskell) совместно с Tim Harris(тоже получает бабло от MS :-) ) трудились над Software Transactional Memory платформой которая в скором времени будет интегрирована в dot net.
Саймон иногда общается с Joe Armstrong вот кстати видео на эту тему http://www.infoq.com/interviews/armstrong-peyton-jones-erlang-haskell просто шикарные дядьки :-)
Также можно взглянуть на:
http://blogs.msdn.com/sos/archive/2009/07/23/Dmitri-Soshnikov-Interviews-Simon-Peyton-Jones-on-Functional-Programming-and-Haskell.aspx
P.S. насчет быдло кодеров: такова участь многих c# программистов в том числе и меня, дрова надо рубить и наточить пилу некогда.
Спасибо за статью. Кажется пришло наконец-то время Лиспа и Ко :-)
Непонятно только почему Erlang назван архаичным.. Странный синтаксис - это да, но архаичность..? Эрланг - сравнительно молодой язык со вполне прозрачным и довольно внятным синтаксисом. Несколько запутаны правила пунктуации, но это не смертельно (особенно по сравнению с Python).
Красота и мощь эрланговской модели не столько в асинхронности, а в том, что она позволяет прозрачно преодолевать сетевой барьер, то есть взаимодействовать с удаленными процессами, как с локальными. Clojure сосредотачивается на жонглировании агентами и отображением их на потоки =>