И как это я проглядел этот замечательный пост в августе... :)
Отдельного внимания заслуживает война в комментах, на тему какую стрелку куда нарисовать надо было.
Это, конечно, все шуточки, реальная картина вот тут:
И как это я проглядел этот замечательный пост в августе... :)
Posted by lrrr at 9:13 PM 3 comments
В процессе переписывания моей программки с хаскеля на OCaml, обнаружилась замечательная фича окемловского отладчика, выглядит примерно так:
Posted by lrrr at 1:53 PM 9 comments
Why learning Haskell/Python makes you a worse programmer
Отлично написано, читаю и просто таки узнаю себя в каждой строчке (ну разве что C++ вместо C#) -- с некоторых пор пишу на C++ и натурально плачу, плачу и пишу..
Posted by lrrr at 1:38 AM 3 comments
Labels: языки программирования
Написание на хаскеле не миниатюрных экспериментальных примеров, а чего-нить более-менее серьезного и в конкретные сроки оказалось не таким уж простым процессом. Кто бы мог подумать :)
Открытия:
Posted by lrrr at 4:55 PM 6 comments
Labels: haskell, языки программирования
AGEIA со своим хардверным ускорителем физики для игр, имхо, должна щас плакать горючими слезами: с выходом новой замечательной железки от NVidia (и SDK для вычислений на GPU разных неграфических задач) их шансы успешно торговать своим девайсом, кажется, сократились еще сильнее.
Вообще не очень понятно на что они рассчитывали, и аналогия с графическими ускорителями тут не очень уместна: когда появился 3DFX, продавец мог просто показать клиенту наглядно: смотри, дескать, какие тут гладкие текстурки, а тут в квадратиках..
С PPU ничего показать толком нельзя. Выигрыш небольшой, у юзера есть всегда вариант купить более мощный многоядерный процессор или пару видеокарт.
Ageia, похоже, думала что процессоры упрутся-таки в потолок производительности, а производители GPU будут гоняться за количеством треугольников в секунду, а не делать архитектуру видеокарт более обобщенной.
Еще был, и пока еще остается призрачный вариант сделать onboard чип и впарить его какому-нибудь производителю чипсетов. (еще лучше производителю консолей, но поезд уже ушел, XBox360 и Playstation 3 вышли)
Несмотря на это их технологии определенно имеют немаленькую ценность, особенно неплохой кроссплатформенный SDK. Наверняка их обязательно скоро купит кто-нибудь большой, это было б вполне уместно для ATI/AMD.
Nvidia я думаю тож не отказалась бы (с целью устранить конкурента совсем и поиметь их замечательный SDK), но, думаю, тратить стока денег чтоб потом выкинуть разработки по PPU в помойку она не готова морально :)
Posted by lrrr at 9:29 PM 1 comments
Блог чувака по имени Zhanyong Wan' -- он был разработчиком в Visual Studio .net setup team, сейчас в гугле работает. (Неожиданно оказался еще и разработчиком FRP, для тех кто в теме :)
Рекомендую, типа.
Улыбнуло: вот у него здоровый, со вкусом к C++ написанный пост, а-ля Александреску-Саттер "как грамотно получить размер массива в C++". Во, думаю, отличная иллюстрация к тезису о том что C++-разработчик играется с языком вместо того чтоб писать программы.
Ан нет -- через несколько месяцев продолжение, оказывается, грамотный метод тоже работает не всегда, и замечательное резюме:
Posted by lrrr at 6:13 PM 3 comments
Labels: ссылки
Узнал, что у замечательной компании Transmeta совсем плохи дела -- они уже от нечего делать подают в суд на Intel за нарушение патентов в линейке процессоров начиная с Pentium Pro. Акции за пять лет упали более чем в 10 раз..
Жалко -- компания очень интересная. Их технологии трансляции на лету команд x86 в систему команд процессора Transmeta Crusoe и динамической оптимизации кода в свое время на меня произвели большое впечатление -- в плане производительности интерпретируемых языков.
До того как я почитал про HP Dynamo, я смеялся над тестами в которых C# рвал C++ и думал что это невозможно в принципе. (TM наняла кучу народа, работавшего над этим проектом). Однако Dynamo впечатлило -- софтверный интерпретатор команд (виртуальная машина) для процессора PA-8000, работающий на этом же самом процессоре -- обгоняет в тестах нативный код сгенеренный мощным компилятором C++.
Вот что называется just-in-time compilng и динамическая оптимизация, которая может ускорять вещи, в принципе недоступные классическому компилятору.
В качестве примера -- оптимизация виртуальных вызовов. Классический пример -- CObject с чисто виртуальной функцией draw и унаследованные от него CPoint и CLine, реализующие эту функцию.
Как известно, в C++ для реализации этого у объекта есть указатель на vtable в которой лежат указатели на виртуальные функции. Соответственно чтоб вызвать draw() имея указатель на CObject, надо залезть в vtable по указателю, взять из vtable адрес функции и сделать переход туда (либо на CPoint::draw либо на CLine::draw).
..что довольно хреново с точки зрения процессора: он заранее не может понять, куда мы собираемся сделать переход, и поэтому не может сделать prefetch в кэш для кода.
Но если мы используем JIT(компиляцию на лету, как в C#), то JIT-компилятор способен определить, что в 99% случаев реальный тип объекта один и тот же (допустим CPoint), и адрес функции практически всегда один и тот же(CPoint::draw), он сгенерит следующий код:
если (тип_объекта == CPoint) переход на CPoint::draw иначе разруливаем дела с vtable
Posted by lrrr at 8:22 PM 6 comments
Labels: динамические языки
Единственный оператор языка программирования, который вполне заслуживает звания "культового" -- это замечательный оператор call/cc, впервые появившийся в диалекте лиспа, scheme в середине 80-х годов. call/cc -- это call with current continuation. То бишь вызов функции (обычно -- лямбда-функции) с параметром, содержащим как бы контекст выполнения программы в точке вызова, который называется словом continuation. Проще показать :) Пример на ruby, где тоже есть call/cc:
def foo for i = 1..100 c = nil #сюда мы будем сохранять continuation callcc {def |x| c = x} # (**) # в фигурных скобках - # лямбда-функция # сохраняет переданный # ей continuation в # переменную c puts i return c if (i % 3) == 0 # прерываем выполнение # функции и возвращаем # continuation каждые # три итерации end end
> t = foo() 1 2 3 > t.call # вызываем continuation, и выполнение # продолжается с (**) 4 5 6 > t.call # еще разок 7 8 9Если есть call/cc, то можно легко реализовать выходы из середины циклов, исключения, да и сами циклы. Еще стоит упомянуть про Continuation Passing Style, когда функции в качестве аргумента передается некоторый continuation в который она должна по завершении передать результат. Если функциональные языки вам не очень близки, то call/cc это суть coroutines, то бишь функции, которые возвращают значение много раз по ходу выполнения. А coroutines сейчас есть в большинстве мейнстримных языков: итераторы в C# (см. оператор yield), coroutines в lua и python. (А с точки зрения computer science оператор call/cc тесно связан с такой фундаментальной вещью как рекурсивные функции, точнее, с понятнием fixed point combinator). Линки по теме:
Posted by lrrr at 7:15 PM 6 comments
Labels: динамические языки
Вернулся из отпуска, почитал LtU про Aspect-oriented Programming и дотянул наконец руки до AOP. (стыдно, что только сейчас, да :) Впечатления странные -- с одной стороны да, интересно, смысл в таких вещах очевидно есть. Действительно, в жизни встречается дофига этих самых crosscutting roles, т.е. общие.. эээ.. поведения различных объектов. Там классический пример -- куча объектов должны писать лог своих действий -- так вот неплохо когда вся логика писания в лог выносится куда-то отдельно, а объекты сами ничего про него не знают. С другой стороны, основной поинт критиков AOP сразу очевиден -- логика растаскивается по кускам, и отслеживать-поддерживать все это хозяйство сложно. Локальность логики теряется. Да и статья, про которую и был пост на LtU, во многом очень убедительно звучит -- такие системы не особо помогают в декомпозиции самой задачи, т.е. это не к дизайну программ (в высокоуровневом смысле), это решение каких-то сиюминутных программерских проблем.. Будем курить дальше, в AOP должны же быть какие-нить убийственные плюсы, раз все с ним так носятся ;)
Posted by lrrr at 3:35 PM 4 comments
Posted by lrrr at 3:48 PM 2 comments
Labels: C++
Оказывается, C/С++ Users Journal успешно загнулся полгода назад. Я только что из танка, да :)
Posted by lrrr at 12:13 PM 0 comments
Labels: C++
Настоящий гуру должен освоить три известных коммерческих языка программирования:
1. Haskell (варианты: ML/Caml/O'Caml/F#)
2. Lisp (варианты: Common lisp,scheme..)
3. APL (варианты J, K, A+)
Первый пункт я начал выполнять уже давно, второй тоже очень медленно идет в фоне, а вот до третьего руки никак не дотягивались.
Сегодня, кажется, дотянулись до J. Во многом благодаря тому факту, что APL-like языки -- это кажется единственное, на чем можно писать из-под Pocket PC.
Вообще на PPC существуют компиляторы C, lisp, python, есть даже портированый gcc. Но после набирания первых двух строчек на python с помощью экранной клавы стилусом весь энтузиазм пропадает. А посмотрите, как красиво выглядит пересечение множеств (списков) на J:
setintersect =: e. # [
(1 2 3) setintersect (3 4 5)
3
Posted by lrrr at 2:17 PM 0 comments
Labels: языки программирования
В чем заключается индустрия software с технической стороны: программисты пишут программы, пользователи их покупают. Пользователям нравится, когда купленные за эти (зачастую немеряные) деньги программы работали. Желательно всегда.Потому что иначе пользователи начинают терять время и деньги, еще более немеряные. А если у пользователей деньги кончатся, программы они покупать перестанут.
Почему программы не работают? Очень просто. В программах есть баги. Баги доставляют программистам много-много увлекательных минут работы с отладчиком и кучу веселья (ну мне лично, по крайней мере ;), но баги все-таки юзеров очень раздражают, и багов поэтому должно быть поменьше и исправляться они должны побыстрее.
Что является основным источником багов? Нет, не программисты, поскольку программисты тоже люди, они совершают ошибки всегда. Однако ошибки совершать намного сложнее, когда работаешь с простой и насквозь понятной системой. А непонятной и запутанной системой software становится, когда в нем появляются разного рода побочные эффекты. То есть один раз нажимаем пимпу на диалоге -- все хорошо, второй раз нажимаем --программа падает. И, главное, программисту совершенно неясно, почему -- код тот же, данные входные те же(нажатие на кнопку) -- очевидный вывод: что-то где-то изменилось и все пошло не так. Что-то -- это какая-то глобальная переменная, состояние какого-то объекта и т.п. Вникать, что именно, программист будет доолго.
Знакомая ситуация?
Посмотрим теперь на другой аспект, процесс отладки в целом. Что происходит: тестер баг наш нашел, пожаловался и сидит радуется. Что должен сделать программист: повторить баг, под отладчиком, понять, куда ставить брейкпоинт, 250 тыщ раз нажать Step Over/Step Into, следя за тем, что и куда записалось, состояние какой переменной изменилось, и че из этого вышло. Причем связи все эти "что и куда", в программе, написаной на C#/Delphi/C++/Java, нифига не очевидны и хорошо просматриваются только в динамике, когда программа запущена. Программист тратит кучу времени.
А решение этих проблем -- это декларативные, а особенно функциональные языки. Когда все логические связи очевидны, по возможности статичны и строго типизированы. Это позволяет отловить огромную часть ошибок на этапе компиляции. Более того, в таких языках по сути отсутствует понятие порядка выполнения программы. Мы просто описываем связи между данными, преобразования, а интерпретатор вычисляет ответ. Поэтому не надо дебаггером проходить всю программу. Выяснить, какая именно связь не в порядке -- в декларативном языке в разы легче, и связь эту, как правило, можно очень просто отдельно протестировать (unit тесты как будто специально придуманы для ФЯ).
Проблемы -- во-первых, не очень высокая производительность. Но это неважно в большинстве случаев, да и есть ФЯ Ocaml который может поспорить по скорости с C++. Во-вторых -- и это главное -- learning curve тут намного круче. Особенно для программиста, не привыкшего к такому способу мышления. Сейчас, правда, они становятся все популярнее. C# 3.0 заимствует фичи из ФЯ, функциональный язык Nemerle становится, кажется, самой модной темой на рсдн.ру..
Хотя я лично в то, что "скоро не будет ни кино, ни театров, а будут сплошные ФЯ" не верю. Мейнстрим это все-таки промышленный дешевый процесс разработки software руками тысяч гастарбайтеров -- индусов, китайцев, и, может быть, русских. :) Индустриализация, промышленный переворот, от кустарного производства -- к заводам и фабрикам ПО :)
Тем не менее, сложные задачи решать на ФЯ намного удобнее. И самая большая з/п (спускаясь на землю :) -- есть и будет у людей с редкими навыками в специфических областях индустрии.
Примеры успешного применения ФЯ покажу потом :)
Posted by lrrr at 12:00 PM 8 comments
То, что C++ -- это язык с кучей недоразумений, хаков, хаков
над хаками и т.п., я осознал уже довольно-таки давно. Но
больше всего меня расстраивает одна вещь -- вот когда падает
виндовс, можно ругать разработчиков. Когда интернета нету,
я с чистой душой материть админов.
Но вот когда в C++ натыкаешься на очередные грабли, винить
вроде как некого. Страуструп, обычно, не виноват -- он писал
объектно-ориентированную обертку (читай -- "костыли") к
высокоуровневому ассемблеру под названием "C", причем это
было логично, поскольку C был сильно популярен и народ
требовал. А Дениса Ричи обвинять тоже глупо -- ну что можно
взять с ассемблера? Он создавал язык чтоб юникс писать,
низкоуровневое программирование -- порты-регистры, тут ему
просто хотелось что-то чуточку поудобнее, вот и лепил туда,
что в голову взбредет. И у него получился нормальный язык
для своей области.
Я вполне понимаю, почему C++ стал таким, какой он есть, но
вместе с этим эта вот круговая порука -- "никто не виноват" --
больше всего меня раздражает.
Нету, к сожалению, человека, чей портрет я мог бы повесить
на рабочем месте и метать в него зубочистки ;)
Posted by lrrr at 1:35 PM 2 comments
Labels: C++
C++ очень странный язык. В нем если порыться, всегда
можно найти миллион бесполезных фич.
struct A
{
char d :6; // ну это всем понятно
unsigned :4; // опечатки нету ;)
char c :10; // чему равно (x = a.c = 256) ?
unsigned :0; // и еще фокус-покус
} a;
Pure ISO C++ :)
Отличный вопрос для собеседований, по-моему. По
крайней мере по уровню идиотизма -- самое то.
Если хотите быть language lawyer'ом, вот правильные ответы:
unsigned : 4; // просто 4 unused бита в структуре
char c : 10; // char все равно 8 битный,
// а два бита сверху -- просто так :)
unsigned : 0; // тут произойдет выравнивание
// размера структуры до размера,
// кратного allocation unit.
// В конце структуры, правда,
// бессмысленно это вставлять. :)
Posted by lrrr at 8:52 AM 1 comments
Labels: C++
Я вдруг подумал, что во втором посте неплохо б объяснить,
что ж такое, по моему мнению, тру программер. Многие
считают, что тру программеры выглядят как три гика на
той заезженой фотке про вечеринку в IT стиле.
Так вот, имхо -- ничего подобного. Знакомьтесь, тру программер
John Meacham. Автор проекта jhc, компилятора языка Haskell,
кто не знает -- Haskell это само по себе очень тру, нереально
круто, его знание поднимает самооценку до уровня "гуру" и
позволяет обоснованно смотреть на остальных, непосвещенных
свысока... :) (ну эту тему я думаю раскрыть в дальнейшем более
подробно).
Этот человек написал оптимизирующий компилятор языка
Haskell, что подразумевает очень глубокие познания в computer
science, теории типов, всяких там системах term rewriting и т.п.
Действительно мега-программер. Действительно тру.
Posted by lrrr at 11:40 PM 4 comments
Когда я был маленький, то, как работает компутер для меня было тайной, сокрытой за километрами мрака.. черная магия и все такое..
Потом (пропустим тут несколько лет чтения андеграундных хакерских журналов, попыток написания игр, кряков, вирусов, баз данных, отладчиков и полиморфных движков..), так вот, потом, в какой-то момент, я понял, что ПОНЯЛ. Понял, что там внутри, как регистры-счетчики переключаются, конденсаторы заряжаются, конвейер-кэш-фон неймановская архитектура-ассемблер-машина Тьюринга-бейсик-паскаль-сиплюсплюс... Все довольно просто, на самом деле...
Но единственное, что меня до сих пор удивляет во всем этом -- это то, как такие толпы программистов умудряются создавать сложнейшие, при этом вполне работоспособные системы, будучи при этом такими расп%*дяями ... :)
Posted by lrrr at 9:29 PM 0 comments