| читал "Практику функционального программирования" #2. основное, что вынес для себя пока что - демонстрация качественных различий между созданием промышленной инфраструктуры на высокоуровневом статически типизированном языке и высокоуроовневом динамическом языке. В интернетах эта тема обходится стороной или сопровождается кривыми мордами. Оказывается, на вопрос "почему не стоит писать то-то и то-то на Питоне", существуют вполне конкретные ответы и измеримые доводы, а не только идеологические. (статья про сотовую инфраструктуру и статья про изобретение велосипеда автокода для gps-приемников... кстати, в чем-то подобном я когда-то хотел искать себе работу, ИУ2 же)
Похоже, статическая типизация реабилитирует себя как инструмент обеспечения надежности, а не инструмент пыток, противоречащий венской конвенции. Все благодаря внедрению систем автоматического вывода типов, которые нынче есть у каждого языка и его собаки.
Надо будет осилть статью про АТД. Она неожиданно человечная, но почему-то в голове почти ничего не задержалось...
Posted via mobilebloger | comments: 10 комментариев or Оставить комментарий  |
| «Нежное введение» доставило:
So, in the end, has Haskell simply re-invented the imperative wheel? In some sense, yes.
Видимо, к достоинствам ФЯ нужно добавить ещё «честность» :) Я понимаешь только успел подумать, что стоило из монад на ввод-вывод огород городить (отличная скороговорка), если в итоге получается откровенный императивняк, но НВ меня тут же поправило: это не собственно императивняк, а безопасный и семантически последовательный эмулятор императивняка (но вообще, не будь я подготовлен тем блогпостом, хрен бы я понял, о чем вообще идет речь, да... «Monad is a monoid in the field of endofunctors, what's the problem?»©). Т.е., оказывается, даже «инструкции» на самом деле являются функциями (некими «монадами» вроде, но неважно). Хинт: Lambda the ultimate kitchen utensil says: всё - функция. даже «x = 1» (а ведь доходит-то медленно...) Очень непривычно видеть структуры управления потоком (которые собственно не, потому что никакого потока-то нет, всё так лениво) в виде выражений, например do как часть сложного выражения в круглых скобках - мозг таки клинит. Ну а «инструкции» ввода-вывода возвращают в обязательном порядке тип с признаком IO. Что не возвращает IO, не имеет права претендовать на ввод/вывод (все ради гарантии детерминированности и отсутствия побочных эффектов, правильно =). Вообще система типов великолепна.
Пример с шашками (разработка сверху-вниз) порадовал - меня всегда раздражало, что мы вынуждены ставить всю несущественную лабудень прежде самого главного, а тут можно не только писать main в самом начале, но и собственно, начинать писать с неё, оставляя всю дребедень на потом =) Фашистская автоматическая типизация фактически гарантирует, что ты пишешь правильный код - даже если его ещё нет :)
До конца не разобрался с индентом. | comments: 4 комментария or Оставить комментарий  |
| Читал сначала «Практику функционального программирования №1», потом туториалы. Пробовал погонять ghci. К концу дня был по уши в кирпичах. Куча отличных идей (ради которых, собственно, и стоит учить ФЯ) сочетается с омега-странным синтаксисом. Надо учить IO и начинать применять на практике. А оно - такой себе serious business (мама, вторичные эффекты, страшно).
Отдельный луч земляники со сливками руководствам и терминологии: Какие "клозы"? Какие "сравнения с образцами"? Какое "частичное применение"?! Ребята, вы что, сдурели? Мне, честно, не дано понять, почему никто даже не пытается воспользоваться системой абстракций, уже имеющейся в наших головах. Перегрузка понятий и терминологии должна быть объявлена мыслепреступлением (хотя, я сам, помнится, очень ратовал за "функция-член класса"... мнда... потом таки сдался). «Сравнение с образцами» (сравнение чего? с какими образцами?) на самом деле, оказывается, представляет из себя решение системы символьных уравнений в общем виде. Частичное применение - это "замена переменной", "подстановка параметра" или «при а = 0» (фиксация параметра, вообще не имеет специального термина), и результатом будет «частный случай» или «упрощение», а не «кастрированная функция».
В общем, нелегко. Особенно — думать. Как всегда :) | comments: 28 комментариев or Оставить комментарий  |
| Вчера мы с hakubo обсуждали Хаскель. Ну, обсуждали - это сильно сказано, обычно он присылает мне интересные ссылки на про языки программирования или аугментированную реальность, а я что-нибудь не слишком осмысленное пишу в эвей обратно, т.к. наши часы присутствия в онлайне сильно не совпадают.
Вообще я иногда до обидного медленно соображаю. Я бы и рад взяться за изучение чего-нибудь действительно нового и интересного (каждый, кто сидит в питоне дольше двух дней, уже заметил, что, собственно говоря, его целью не является быть интересным — он успехом занял место прагматичного и предельно простого в использовании повседневного инструмента для того, чтобы заставить компьютер делать нужное тебе, а не наоборот - и при этом не дискриминируя людей по платформе, господа юниксшеллофаги), но само осознание того, что на усвоение простейших концепций я потрачу минимум полгода, совершенно не взбадривает.
Но обратно к Хаскелю. Мне все больше начинает казаться, что функциональные языки скрывают кучу стройных, красивых и простых концепций за отвратительнейшим синтаксисом, как будто нарочно пытаясь нас запутать.
Ради интереса полез посмотреть ,как у хаскеля с гуями (т.е. может ли он использоваться для чего-то кроме консольных программ или библиотек). И меня сразу же потрясла одна вещь - wxHaskell уже реализует почти буквально вон тот декларативный гуевый велосипед, что я придумал на досуге. Да простят мне бесстыдный и бесконечный самопиар, я так редко придумываю достойные идеи, что искренне радуюсь, когда их, оказывается, уже сделали.
hello
= do f <- frame [text := "Hello!"]
quit <- button f [text := "Quit", on command := close f]
set f [layout := widget quit]
Вот это я называю «выразительность». Что (не)удивительно, этот код полностью понятен даже без какого бы то ни было знания Хаскеля, функциональных языков или принципов работы гуя на событийной основе.
Я по-прежнему боюсь тыкать палочкой Хаскель. Не могу представить, как лично мне его применить на практике, и хотя в теории это лечится чтением ртфм, на практике фм по нему часто запутан ещё больше, чем сам язык. Из других языков я, возможно, соберусь когда-нибудь потыкать палочкой Руби и Скалу. В Руби привлекает, по-видимому, большая гибкость и расширямость языка, полезная при создании кавайных, претенциозных и совершенно бесполезных маленьких DSL на месте. Чем хороша Скала, всем известно, хотя явовское наследие настораживает. | comments: 22 комментария or Оставить комментарий  |
| Проблема в разделении. С одной тсороны, суровое и серъёзное отношение питона к типу информации в строках более чем оправдано. Мы хотим быть уверены, что наши алгоритмы обрабатывают строки корректно, и что в каждый конкретный момент времени тсрока гарантирует осмысленность своего содержимого и возможность его интерпретации. С другой, вывод в консоль, исторически используемый для дебага, а в гуевых программах - исключительно для сбрасывания дебаг-мусора. И требования к этому практически нулевые, более того, что это за дебаг, если он наоборот вызывает баги? Но разделить их с точки зрения грамматики-то уже невозможно. Кто поределит, является ли данный вызов str() фрагментом гениального алгоритма или участвует в очередном print "%s" ? Технологически, это можно было бы сделать, оставив особый грамматический статус print как инструкции и вызывая в пределах её действия прощающую версию str(). Звучит как ересь, однако, до сих пор скользкие религиозные вопросы не мешали питону быть фактически эталоном прагматизма. В случае с print же, как мне лично кажется, идеологический маразм перевесил разумные соображения. Каков смысл делать print функцией? Четкой мотивации ни от Гвидо, ни от кого-либо ещё лично я не видел. Унификация ради унификаци? О какой унификации может идти речь, если эта консоль работает по-своему (по-своему криво) на каждой из платформ? Или что, кто-то и вправду использует перенаправление вывода print? смешно же. | comments: Оставить комментарий  |
| | Интересно, насколько недырява абстракция генераторов? Приемлемо ли использовать генераторы в 2.5 как процедуры с сохранением состояния в общем случае - допустим, может ли метод гуевого класса использовать yield? | comments: 7 комментариев or Оставить комментарий  |
| Все мы помним, какая хорошая это идея — архитектура Model-View и её вариации, и какое дикое количество геморроя она вызывает на практике. Связано это с тем, что она никак принципиально не решает проблему переплетения кода модели и кода представления, не убирает этот беспорядок, а всего лишь дает возможность в нем ориентироваться. На гордое звание решения могут претендовать лишь инструменты, избавляющие нас от хаоса. Об разделении business-кода и интерфейсов много говорили, и иногда по делу, но в итоге все сводилось к вписыванию кода в обработчики событий и бесчиаленные вызовы TextCtrl1.GetText(). Просто вместо хардкода последовательности инициализации интерфейсов хранились в отдельных файлах и представлялись в виде xml — этакий психологичеcкий трюк, чтоб относиться к ним, как данным. И если для компилируемых языков это было критично, то для, скажем, Питона уже никакой разницы между трансляцией xml-файла в интерфейсный код и собственно подгрузкой и непосредственным исполнением файла с уже имеющимся интерфейсным кодом в принципе не существует.
Эти жалкие полумеры меня не могли радовать. Идеальная система, как я её себе воображал, выглядела примерно так: берется алгоритм, где все инструкции вида print(x) или Label.SetText(x) убираются, а вместо них в начале ставятся, «watch(x) as Label»; а всякие словоблудия типа TextCtrl.GetText(s) заменяются на «reflect(s) as TextCtrl». Странные термины были выбраны специально, чтобы подчеркнуть декларативность стиля, вневременность и внеконтекстность связей: мы, Человек, должны только высказать, что хотим отображать переменную или знать значение текстбокса, а остальное - проблемы роботов.
Оказалось, что похожая штука существует: http://avc.inrim.it/ Именно (почти) об этом я мечтал. Это, товарищи, потрясающе. Эта штука автоматически связывает извлекаемые из ресурсов гуи и переменные в коде. Но мало того, по сути дела это ещё и мета-тулкит. Можно писать код, абсолютно агностичный не только к платформе, не только к конкретному тулкиту, — но и к гую как таковому в принципе.
От моей конепции AVC отличается тем, явно что использует xml и редакторы гуя. Это разумное решение - опираться на уже имеющиеся инструменты. А взамен на это она вообще избавляет нас от необходимости явно декларировать, что мы хотим отображать или знать - достаточно просто дать контролам имена соответсвующих переменных. Теоретически, на базе этого легко можно построить предложенную мной систему, которая будет ещё проще и примитивнее, но зато позволит быстро и в два слова писать истинно декларативный гуй от руки. А для случаев посложнее по-прежнему грузить интерфейсные файлы или читать конфигурацию раскладки шуевых элементов из строки с подобием вики-таблицы. Ну это все теоретически, на практике-то у меня кишка тонка такое кодить.
Картинка.
Рабочий код идентичен для любого из пяти тулкитов. Последовательности инициализации и внешний вид, как и следовало ожидать, немного отличаются - и даже этого бойлерплейта можно было избежать, добавив дополнительные обертки и конфигураторы отдельно для каждого тулкита, а также упростить обработку сложных типов (выводить голые словари и списки без требуемого специального форматирования).
P.S. Ещё один похожий концепт был в экспериментальном интерфейсно-остроумном тулките Shoes для Руби, но для написания стандартного интерфейс он не подходил, да и не ставил перед собой такую задачу. | comments: 3 комментария or Оставить комментарий  |
| каждый битый плюсами гражданин знает, что без перегрузки конструкторов нам не жить. ну вот настала и моя очередь: я уткнулся в то, что ни в одном доке или туториале перегрузка как она понимается в С++ просто не упоминается. Ну логично, да — питону ведь плевать на типы ваших аргументов, хотим - можем хоть весь исполняемый код вместе с интерпретатором в качестве аргумента сунуть. Но что делать, если мы хотим создавать объект нашего класса из разных источников? поискал-поискал, нашел варианты с статик классметодами, банальной проверкой типа, и кучей шаманства. Совершенно ненамеренно я стал вчитываться в шаманство, и меня осенило: а ведь всё это просто... не нужно. Если наши источники разнородны, то и семантика объектов разнородна. Тогда и их интерфейсы разнородны, и мы имеем два законно разных класса =) Что в питоне, с его минимумом писанины, да ещё и в комоде, с его автодополнением скобочек и всех слов по табу, сделать ничуть не напряжнее, чем один. Гвидо опять оказался умнее :) Я сразу увидел свет, и всё расплывалось и превращалось в атомы, и затем в байт-код, и даже небо, даже аллах и посмотрел на свой код, и понял, что отравленный ядовитыми флюидами ООП мозг пытался сунуть в один класс совершенно не относящиеся друг к другу сущности... | comments: 6 комментариев or Оставить комментарий  |
| | Совершенно случайно (ну не совсем, конечно, но всё же) наткнулся на ресурс того самого чувака, что написал «Cathedral and Bazaar». Если честно, я с некоторым снобизмом отношусь к амерканскому популизму. Кто читал то, что я имею в виду (статьи того самого роквелла или например free-culture.cc - хороший пример) поймут меня. Этот стиль "для идиотов", с многократным разжёвыванием и повторением, пrотивен нашей кльтуrной душонке. Или, например, взять RMS. Мужик прост как топор, и какие бы правильные вещи он ни говорил, читать его не слишком интересно. Потому я решил потыкать веточкой что-нибудь помельче, а именно пафосно названную «Месть Хакеров». Каково же было моё огромное удивление, когда я обнаружил потрясающе чёткое, сжатое и динамичное чтиво, в чуть ли не каждом предложении открывавшее новый взгляд или идею. Антрополог по самоопределению, ESR и вправду оказался действительно скорее публицистом и историком, чем программистом или активистом. Мне почти удалось поверить в ту грандиозную картину эпической битвы идей (гиасс отдыхает) на поле PR, технологий, капризной прессы и безжалостных гигантов бизнеса. Может быть, так оно и было, но это настолько красиво, что российскому инженеру, знакомому со стандартной судьбой блестящих идей в нашей стране, поверить в это реально трудно. Но даже в качестве белетристики этот чел омега-жжот. | comments: 10 комментариев or Оставить комментарий  |
| Как сказал Роквелл, "Есть два типа любителей фотографии: любители фотографировать и любители потрепаться." Ну так вот я скорее во вторую категорию попадаю. Не то чтобы это очень плохо (я предпочитаю ассоциировать себя с тем человеком из «игры в бисер», который Игру очень любил, но играть не мог и не умел)... о чём это я. А, так вот, о нашей Игре. Тут меня ласково упрекнули в незнании матчасти. В принципе, до того, что С++ является не то что не лучшим языком для решения конкретных задач, но вообще абсолютно неподходящим языком для решения каких-то ни было задач, я догадался давно. Но я продолжал восхищаться сложностью структуры и эстетически цельной системой противоречий, заложенной в язык. Для меня он был скорее любимой собакой, чем ездовой. Однако недавно я на практике убедился в том, почему промышленную разработку ПО ведут на том же C#: по-видимому, в отличие идейного (крайне левого) фронта С++, поставившего перед собой во многом нереализуемый и противоречивый идеал развития, центристские платформы разработки типа .NET более приземлены, либеральны то есть по уши коммерциализированы, и ставят своей основной целью решать проблемы, а не их создавать. Какие из этого выводы?... Страуструп как-то говорил о более простом и гениальном языке, который пытается вылезти на свет из С++. Ну так вот, тот язык, похоже, безнадёжно опоздал... | comments: Оставить комментарий  |
| Это маленькая гуй-программа с таблицей и несколькими подсчётами и пересчётами. Я и не подозревал, как я на самом деле ненавижу С++. Все эти скобочки (всё равно все, всё и всегда выделяют отступами!), несистематические точки с запятой (тысячи их!), двойные объявления (зачем?!), необходимость помнить, понимать и учитывать разницу между инициализацией, копированием и присваиванием; невозможность перегрузить точку (а значит, все умные указатели в борланде и не только пишутся через ->); кучи словесного мусора — по два указания на тип в одной инструкции там, где нам вообще всё равно, какого оно будет типа — это нормально? десятки строк только для того, чтобы воспользоваться парочкой шаблонов и опреаций над ними — это нормально?! Ненависть, ненависть!!
Особенно после питона, который ставит одной из своих первейших по важности задач избавить человека от этой бурды, никоим образом не относящейся к собственно написанию программ.
Позабавило, каким хреновым программистом я оказался. Я всегда объяснял всем вокруг, как надо хорошо и правильно писать программы, но сам допускаю такие глупости, что потом, — а глупости в программировании имеют циничное свойство всплывать потом, — в ужасе хватаюсь за голову. Впрочем, как я уже убедился, с повышением уровня сама необходимость делать эти глупости во многом пропадает. Большая часть проблем решается улучшением доступности средств высокого уровня. Сегодня цена использования инфраструктуры STL в С++ — это страницы лишнего кода. Цена использования её аналога в питоне равна нулю, все основные средства встроены в язык. Сравнение основного инструмента работы с контейнерами, цикла перебора — в С++ for(sequence<type>::iterator i= seq.begin(); i!=seq.end(); ++i) c питонским for i in seq: говорит само за себя более чем убедительно.
Интересно только, почему я не убедился лет на пять раньше? Инерция мышления — страшная штука. | comments: 15 комментариев or Оставить комментарий  |
| сколько раз встречал в сети и книжках рассуждения в виде "добавить функцию вывода нашего класса мы в std::ostream, к сожалению, не можем...". каким надо идиотом быть ,чтоб не понимать, что это разделение не только естестенно, но и необходимо? что сама суть ostream - потоковый вывод строк символов, а не каких-то классов, и он предоставляет этот функциональный интерфейс в виде набора стандартных operator<< . И если класс хочет выводить себя туда, — даже не именно туда, а вооббще куда-то, — он должен предоставить внешнее представление, соответствующее интерфейсу - ведь он сам отвечает за свою семантику. Добавление автоматического преобразования типа к строке operator<std::string> спасёт любой класс, желающий выводить себя в поток. Написание дополнительных внешних operator<< или субклассирование std::ostream — это фгм терминальной стадии.
по-моему, за всей этой объектной мишурой мы начинаем часто забывать, что она создавалась для облегчения написания программ. | comments: Оставить комментарий  |
| В контексте проблемы гуя мне уже несколько раз упоминали про WPF. несмотря на то, там много как интересных решений (доведение до ума слоя абсракций между прикладным кодом и системой), так и серьёзных минусов (огромность и неподъёмность, проприетарная идеология), нас интересует один чисто технологический аспект: а именно, XAML. По заявлениям эта фиговина обеспечивает полностью декларативное написание гуёв и чистое, как никогда раньше, разделение функционального («бизнес», май эсс) кода и gui-кода, и ещё много прочего бла. К сожалению, при ближашем рассмотрении эта хрень оказалась старым добрым XML, т.е. никаких принципиальных изменений в парадигме написания интерфейсов не произошло - просто вызовы api в очередной раз спрятали ещё глубже и укутали слоями абстракции и задолбавшего X*L. Более того, с точки зрения человека XML, будь он хоть сто раз декларативный, в сотню раз хуже императивного гуя на тулкитах - ибо работать с XML можно только с помощью костылей, ведь это фактически антипаттерн человекочитаемости. Я допускаю, что там будет реализован какой-то более чёткий и ясный механизм связывания функциональности гуя и функциональности кода, но, используя презумпцию виновности, получаем вывод: это просто майкрософтовская реализация QtDesigner / Glade для очередных Foundation Classes, обвешанная пышными слоганами.
«Пастернака не читал, но осуждаю»© :D | comments: 1 комментарий or Оставить комментарий  |
| |