Отличная картинка:
Думаю, что надписи можно свободно заменить на “Начальник/Подчиненный” и “Заказчик/Исполнитель”.
Найдено тут: http://szymon.tumblr.com/
Размышления и впечатления, которые не хочется держать в себе. О программировании в частности. Ну и о творчестве, и о жизни вообще.
Отличная картинка:
Думаю, что надписи можно свободно заменить на “Начальник/Подчиненный” и “Заказчик/Исполнитель”.
Найдено тут: http://szymon.tumblr.com/
На RSDN появился совершенно загадочный пост Почему монады лучше lvalue (глобальных переменных) (написанное в нем я не понимаю до сих пор, буду признателен, если кто-нибудь его расшифрует). Для того, чтобы понять, о чем же там идет речь, пришлось обратился к первоисточнику: Programming Paradigms for Dummies: What Every Programmer Should Know.
Сегодня с утра я его таки дочитал. И кажется мне, что потраченное на его прочтение время было потрачено зря.
“Научный снобизм”, наверное, не совсем корректная характеристика. Но по ходу чтения я не мог отделаться от мысли, что автор говорит о программировании лишь с точки зрения академического ученого. Отсюда убежденность в непогрешимости функционального подхода. Ну и еще некоторые обобщения. Например, утверждение о том, что записи (record) являются одной из основополагающих концепций и через записи могут быть выведены остальные типы структур, такие как массивы, списки, строки, деревья, hash-таблицы. Или вот это:
Instantiation and genericity, normally associated with object-oriented programming, can be done easily by writing functions that return other functions. In object-oriented programming the first function is called “class” and the second is called an “object”.
Наверное, с точки зрения “высокой научной мысли”, так оно и есть. На практике, однако, удобнее пользоваться массивами и строками, как отдельными понятиями. И не считать, что класс – это функция, которая порождает функции-объекты. Лично мне это напоминает такой апофеоз обобщений, как “очередь с емкостью единица и выталкиванием старого значения при помещении в очередь нового значения” – вот так можно обозвать обычную переменную.
Но больше всего разочаровал пример с демонстрацией того, что наличие named state (т.е. переменных) улучшает модульность. Типа есть модуль, в котором есть функция F. Этим модулем пользуются программисты U1 и U2. Программисту U2 захотелось, чтобы модуль вел подсчет количества обращений к F. Что легко достигается посредством введения в модуль переменной-счетчика. Такое изменение не затрагивает программиста U1, поскольку интерфейс функции F не меняется.
Не знаю как кому, а лично меня такой пример совершенно не убеждает. Кстати, отличная демонстрация того, насколько сложно подбирать реалистичные и минималистичные примеры при написании статей о программировании.
Сухой остаток: статья не понравилась, понимания упомянутого выше поста thesz-а не прибавилось. Времени жалко.
SCOOP, или Simple Concurrent Object-Oriented Programming, – это надстройка над языком Eiffel для конкурентного и распределенного программирования. Разговоры о SCOOP идут уже очень давно. В толмуде Бертрана Мейера об Eiffel SCOOP посвящена изрядная часть. Но до реальной эксплуатации SCOOP-а дело, как я понимаю, так и не дошло и в природе существует только его прототип.
Вспомнить о SCOOP меня заставила недавняя статья “SCOOP: Concurrent Programming Made Easy”. В ней дается короткий, но хороший обзор технологии SCOOP. И, самое важное, в ней был описан механизм дуэлей, о котором я раньше не слышал (или пропустил мимо ушей). Ниже следует очень свободный пересказ содержимого упомянутой статьи. Если кто-то заинтересуется подробностями – пожалуйста к первоисточнику :)
Итак, смысл SCOOP сводится к тому, что объекты разрешается распределять по процессам. Процессом может быть другая нить в том же приложении, другой процесс на этой же машине или же другой процесс на другой машине в сети. Для того, чтобы один процесс мог ссылаться на объекты в другом процессе, вводится новый тип ссылок – separate. Например, метод some_feature получает два аргумента: первый нормальный, а второй – ссылку на объект из другого процесса:
some_feature(a: LOCAL_TYPE; b: separate GLOBAL_TYPE) is
...
end
В принципе, ссылка на любой тип может быть объявлена как separate. Хотя не для всех типов это может иметь смысл. Можно так же описывать классы, помеченные как separate – это будет означать, что ссылки на такие классы будут автоматически считаться separate, а все объекты это типа будут т.н. separate object.
А дальше начинается особая SCOOP-овская магия :)
Все обращения к separate-объекту будут ставиться в FIFO-очередь. За этим будет следить среда исполнения Eiffel-SCOOP. Т.е. separate-объекты автоматически получают внутренний монитор (мутекс) и заботиться внутри separate-объекта о защите от многопоточного доступа к его данным не нужно.
Но для того, чтобы пользователь, владеющий ссылкой на separate-объект, мог обращаться к методам этого объекта, необходимо, чтобы это обращение было завернуто в метод, ссылка на separate-объект в который передается как аргумент. Проще всего это показать на примере. Пусть у нас есть некий класс:
class SAMPLE
feature
-- Вот у нас ссылка на separate-объект.
mailslot: separate MAILSLOT
-- А вот в этом методе мы попытаемся обратиться
-- к separate-объекту.
produce_messages is
do
...
-- Это у нас не получится, поскольку mailslot
-- не является агрументом produce_messages.
mailslot.store (msg) -- ОШИБКА!
-- Зато вот так можно.
store_message (mailslot, msg)
end
-- Этот метод может обращаться к mailslot,
-- поскольку он получает его в качестве аргумента.
store_message(to: separate MAILSLOT,
what: MSG) is
do
to.store (what)
end
end
Такая политика связана с механизмом контроля за целостностью объектов в SCOOP. Поскольку SCOOP сам разруливает синхронизацию доступа к объектам, то ему нужно знать, в какой момент нужно захватывать монитор объекта. Таким моментом как раз является вызов метода, в который аргументом передается separate-объект. (Мой склероз может мне изменять, но мне кажется, что таким образом SCOOP может отслеживать вложенные вызовы функций с передачей того же самого объекта – он повторно уже не будет захватываться). Так же такая политика, по мнению разработчиков SCOOP, позволяет избегать тупиковых ситуаций.
Если SCOOP-процессы работают в рамках одного приложения, то обращение к separate-объекту будет происходить просто как вызов метода с необходимыми блокировками. Но если SCOOP-процессы разнесены по разным физическим процессам или даже узлам сети, то SCOOP берет на себя задачу создания proxy-объектов и маршалинг/демаршалинг вызовов.
А дальше начинается самое интересное. Ведь Eiffel – это язык, построенный на использовании Design By Contract. И оказывается, что в SCOOP контракты задействованы достаточно оригинальным образом. В частности, предусловия играют роль condition variable. Т.е. предикаты, которые записываются в секции require делятся на две категории: те, которые можно проверить немедленно и те, которые зависят от внешних условий. Например, приведенный выше метод store_message может быть записан с предусловиями:
store_message(to: separate MAILSLOT,
what: MSG) is
require
-- Это условие вычисляется сразу.
mailslot_specified: to /= Void
-- А вот это может проверяться неоднократно.
mailslot_has_free_space: to.free_ceils > 0
do
to.store (what)
end
Так вот, когда в программе произойдет вызов store_message, то среда исполнения проверит, что возвращает метод free_ceils у separate-объекта. И если это значение равно нулю, то значит предусловия не выполнены и нужно уснуть, пока они не будут выполнены.
Никаких condition variable в SCOOP не видно. Зато на предусловиях их можно имитировать. Не понятно правда, как сделать ожидание, ограниченное по времени (что-то типа cond_timedwait).
Еще одна черта SCOOP – распараллеливание вычислений. Тут, однако, нужно вспомнить про Command Query Separation Principle. Команда должна модифицировать состояние объекта, но не должна возвращать результата. А запрос не должен модифицировать объект, но должен возвращать результат. По сути, запрос должен быть функцией без побочных эффектов.
Итак, допустим, у нас есть ссылка на separate-объект A. Мы можем вызывать несколько команд у него. Это не может быть распараллелено, т.к. все команды будут поставлены в FIFO очередь объекта A. Аналогично и с запросами к объекту A.
Но вот если у нас есть ссылки на разные separate-объекты A, B и C, то обращения к ним могут распараллеливаться. Точкой синхронизации будет первое обращение с запросом к объекту. Например:
some_feature(
a: separate A;
b: separate B;
c: separate C) is
do
a.do_something
b.do_something
c.do_something
-- Все три задействованные выше команды могут
-- выполняться параллельно. Зато здесь произойдет
-- синхронизация действий над объектами a и b.
if a.result /= Void and b.result /= Void then
-- До сих пор вычисления для c могли идти независимо.
-- Но сейчас произойдет синхронизация.
a.result.attach (c.result)
end
end
А теперь пара слов о дуэлях (в упомянутой статье им уделено мало внимания, к сожалению). Итак, есть объект, который называется holder. Он владеет неким separate-объектом b, поскольку успел войти в какой-то свой метод r(b) (т.е. b передан в r как аргумент). И тут на арену выходит другой объект, называемый challenger, которому так же нужен объект b. Но объект b сейчас захвачен holder-ом и challenger-у нужно ожидать завершения r. Если же такое ожидание нежелательно, то можно применять дуэли.
Объект holder может использовать два специальных вызова: yeild (который говорит, что holder готов отдать владение объектом challenger-у) и retain (который говорит, что holder не желает отдавать владение). У объекта challenger-а есть набор из трех методов: demand (потребовать немедленное владение объектом), insist (попробовать получить владение объектом) и wait_turn (ожидать хода от holder-а). Поведение holder-а и challenger-а в этих условиях демонстрируется следующей таблицей:
wait_turn | demand | insist | |
retain | challenger ждет | Исключение у challenger-а | challenger ждет |
yeild | challenger ждет | Исключение у holder-а | Исключение у holder-а |
Т.е., происходить может следующее. Объект holder захватывает какой-то объект и начинает длительную операцию. Где-то на ее середине holder понимает, что критически-важные действия, способные нарушить инварианты объектов, он уже выполнил. Поэтому, если кто-то нуждается в захваченном объекте, то holder может отдать ему владение. Для этого holder вызывает метод yeild. Если после этого challenger вызовет demand или insist, то challenger получит владение над объектом, а у holder-а возникнет исключение.
Если же holder не хочет отдавать владение объектом, то он вызывает retain (или ничего не вызывает, т.к. политика retain используется по умолчанию). И если challenger обращается к demand, то у holder-а ничего не происходит, зато у challenger-а выскакивает исключение. Если же challenger вызывает insist, то challenger засыпает до освобождения объекта.
Как я понимаю, механизм дуэлей нужен для использования SCOOP в real-time проектах. Тогда какой-нибудь низкоприоритетный holder сможет работать с неким важным объектом лишь до тех пор, пока не возникнет более высокоприоритетное событие, обработкой которого занимается challenger. Объект challenger вызывает demand, у holder-а выскакивает исключение, а chellenger получает в свое распоряжение нужный ему объект. Правда, я сомневаюсь, что разработка корректного кода с использованием дуэлей будет простой – уж очень внимательно нужно расставлять в коде retain/yeild и demand/insist. Да и получить в произвольный момент времени исключение, как следствие yeild/demand, хорошего мало, на мой взгляд.
Делать маршрутизацию и рассылку миллионов SMS – это, конечно, интересно. Но я бы с удовольствием попрограммировал бы начинку этих роботов…
Сегодня впечатления от “громких” фильмов.
По ходу просмотра фильма возникали различные вопросы “почему” и “зачем”. Ну, например, почему в CERN-е при проведении серьезнейшего эксперимента оказался католический священник? Он, типа, не только продвинутый священник, но еще и выдающийся ученый? Какой смысл был давать в помощь главному герою женщину? Ведь никакой романтической линии между ними так и не возникло. Какой-нибудь тщедушный физик (типичный такой “ботаник”) в этой роли смотрелся бы, на мой взгляд, более естественно. Еще вопрос – есть ли в природе квантовые биофизики (если я правильно помню, именно такая специализация была у героини)? А то ведь не понятно, откуда она такая вся умная и грамотная – и физик, и медик, и батарейки в контейнере с антиматерией менять умеет, да еще и знает, кто такой Бернини ;)
Но финал всего этого фантастического действа подвела одна фраза. Которая меня лично убила на повал. Итак, почти в конце фильма главный злодей бежит к вертолету, чтобы в последние мгновения перед взрывом вывести взрывоопасный контейнер подальше от Ватикана. Выгоняет пилота вертолета и сам садится за штурвал. Все вокруг шумят, что-то кричат. И вдруг кто-то успокаивающим тоном произносит: “У него есть лицензия!” Мол, все нормально, за штурвал вертолета злодей садиться может и право поднимать машину в воздух имеет.
Ну ёпть, раз лицензия есть, значит может лететь. Иначе бы ему взлететь не позволили, ну никак. То, что остаются десятки секунд до пятикилонного взрыва – это все фигня. Ведь главное, чтобы лицензия пилота была!
В общем, туфта редкая. Но дорогая и качественно снятая. И если правда, что Том Хэнкс получил за эту роль 50 миллионов долларов, то остается только восхититься и сказать: “Ай Хэнкс, ай молодца!”
Об этом фильме было много сказано на сайте Гоблина (он же и делал перевод этого фильма, но мне попался вариант, в котором текст читал не Гоблин). Еще до просмотра я читал в отзывах зрителей, что у фильма очень неожиданный финал…
В общем, с этим фильмом произошло полное несовпадение ожиданий и реальности. Я думал, что будет боевик, в котором Иствуд будет громить черных бандитов. Оказалось, что не черных, а азиатских. И не громить, а пытаться напугать. Чтобы затем принести себя в жертву и спасти тем самым своих новых друзей-соседей. Такие вот дела, ожидал крутой боевик, получил драму. Поэтому предупреждаю – это не боевик.
С неожиданным финалом так же не срослось. Как сейчас удобно говорить, “фильм был немного предсказуем” :) Где-то к середине фильма стало понятно, что герой Иствуда уже не жилец. И что его роскошный Гран Торино достанется пацану-азиату. Так оно и вышло. Хотя я думал, что героя Иствуда убьют бандиты в перестрелке уже после того, как он успеет замочить парочку-другую отморозков. Оказалось поинтереснее.
По ходу просмотра фильма складывается достаточно однозначное впечатление “Не верю”. Как-то все предсказуемо и стереотипно. Особенно неправдоподобными мне показались азиаты-бандиты. Все из себя такие крутые, а когда старикан их несколько раз обломал, они почему-то ничего с ним не сделали.
Самое лучшее в фильме – это сам Иствуд и специфическое чувство юмора его героя. На мой взгляд именно это и вытягивает весь фильм. Так что времени, потраченного на просмотр не жалко, хоть фильм и не шедевр. Клинт Иствуд – просто феномен, время над ним, похоже, не властно.
Реанимированный после многих лет забвения один из самых забойных ужастиков моей молодости. Очень добротно снятое мочилово. Выключаешь мозги и наблюдаешь, насколько за последние 15-20 лет киноиндустрия продвинулась в съемке натуралистических эффектов.
Самое важное – мозги перед просмотром нужно выключать. Это фильм такой, чисто визуальный.
Неприятный осадок оставили последние кадры фильма, когда сброшенный в озеро труп Джейсона вдруг оживает, выскакивает из воды и хватает таки многострадальную главную героиню. Т.е. я понимаю, что авторам нужно было как-то дать себе возможность снять продолжение. Но все таки выключить собственные мозги до такой степени я не могу (в детстве получалось, сейчас нет). Ведь убили же Джейсона, убили. Даже трепанацию черепа дереводробильным станком сделали. А он все равно живее всех живых. Нет чтобы сделать так, чтобы Джейсон всех сам замочил и жив остался для следующих серий без волшебного воскрешения. Редиски, короче. Испортили “удовольствие” от просмотра :)