суббота, 24 октября 2009 г.

[life.foto] Еще одна фотография на тему “Война войной…”

На этот раз Бразилия, во время разборок полиции и наркоторговцев в одной из фавел Рио-Де-Жанейро:

Ну и правильно, пока за углом стреляют, можно и стаканчик пропустить, и свежие новости перетереть. Жизнь-то продолжается.

пятница, 23 октября 2009 г.

[life.photo] Какая разная жизнь…

…или битиё определяет сознание.

Просматривал сегодня WSJ’s Pictures of the Day и буквально выпал в осадок от соседства двух фотографий, идущих одна за другой. Вот они, в том же порядке:

Первая сделана в Минске, на экзамене на получение “крапового берета”. Вторая – в Токио на Токийской Неделе Моды, на праздновании установления дипломатических отношений между Японией и Австрией.

На первой – боль и кровь, на второй – танцы и веселье. И то и другое – жизнь.

PS. Многие из тех, кто пытался заниматься восточными единоборствами в конце 80-х, мечтали сдать тест на краповый берет. Поэтому лично я предпочел бы быть героем первой фотографии, а не второй. Битиё таки определяет сознание.

[life.humour] Забавное объявление на магазинчике

Маленький продуктовый магазинчик на автобусной остановке, на нем объявление:

На круглом штампике надпись “Проверено” – я перепроверять не стал :)

PS. Теперь понимаю, зачем в мобильных телефонах фотокамеры :))

[comp.prog.flame] Заморозят ли развитие языка Python

Новость с OpenNet.ru:

Гвидо ван Россум (Guido van Rossum), великодушный пожизненный диктатор проекта Python, предложил сообществу разработчиков прекратить внесение изменений в грамматику, семантику и встроенные функции языка Python в течение нескольких лет. В качестве причин необходимости заморозки языка называется желание дать возможность создателям альтернативных реализаций языка Python, обеспечить в своих продуктах полную совместимость с классическим CPython.

Вот это я понимаю, вот это правильно. Пока толпы(?) глотающих слюну приверженцев D и Scala с вожделением ждут, когда же их любимые языки устаканятся и придут в состояние enterprise ready, язык Python будет тихо и незаметно использоваться в сотнях и тысячах новых приложений.

Помнится, около двух лет назад, когда в news-группах языка D стали обсуждать выделение ветки D 2.0, не совместимой с D 1.0, я там писал, что это плохо. Что должен быть период в 3-4 года, чтобы появились приложения и инструменты для D 1.0. Что при наличии перспективы выхода версии 2.0 нет серьезных стимулов писать что-то под D 1.0. Тогда этому много возражали. И что в итоге? Где приложения на D? И это не смотря на то, что релиз 1.0 был более двух лет назад. Даже Tango 1.0 так и не вышла… Редиски, короче.

И вот Гвидо говорит о том, о чем я когда-то говорил разработчикам D. Еще бы кто-нибудь сказал об этом Мартину Одерски и Co.

четверг, 22 октября 2009 г.

[comp.prog.flame] Zimbu – новый язык программирования от Брама Мулинара

Не, ну так нельзя – заходишь с утра на LOR и видишь новость о том, что разработчик ViM, Брам Мулинар, затеял создание нового языка программирования – Zimbu. Все, работа встала! :)

Итак, новый язык имеет свой сайт: http://www.zimbu.org

Для чего понадобился новый язык (ёптыть, разве ж не понятно – все остальное писали не мы – прим.eao197)? Вот что пишет автор:

Предположим, что вы хотите написать новую программу, что-нибудь вроде текстового редактора. На каком языке вы будете это делать?
- он должен быть настолько быстрым, насколько это возможно, поэтому интерпретируемые языки не рассматриваются;
- вы не хотите заниматься микроуправлением памятью, поэтому C не рассматриваются;
- вы не хотите, чтобы программистам требовалась ученая степень, поэтому C++ не рассматриваются;
- вы хотите быстрый запуск и не хотите зависимостей от большого run-time, поэтому Java не рассматривается;
- он должен работать на большинстве систем с компилятором C, поэтому D не рассматривается;
- вы хотите получать удовольствие от создания чего-нибудь нового.

Не существует языков, которые действительно удовлетворяют этим требованиям. Поэтому создается новый, который удовлетворяет.

Какие цели преследуются при создании языка?

- легкость чтения кода – код читается в N раз чаще, чем пишется;
- избежание распространенных ошибок – нужно сделать сложным написание плохого кода (но вы можете писать хаки, если вы действительно этого хотите);
- краткость и ясность, не нужно повторять одно и тоже дважды – нет заголовочных файлов, нет повторения спецификации типа;
- эффект выражения должен быть предсказуемым и не должен зависеть от чего-то в другом файле;
- эффективное исполнение: нет задержек при старте, разумное потребление памяти – нет эффектов JIT-компиляции;
- поддержка большого диапазона приложений – Zimbu может быть использован для написания ядра ОС, коротких скриптов и больших GUI приложений;
- переносимость – возможность компиляции и запуска на почти всех системах;
- много стандартных типов, модулей и классов – большинство вещей, которые вам нужны, уже здесь.

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

Какие решения уже были приняты автором языка?

- конвертация программы в C и использование компилятора C для генерации машинного кода (в последствии может быть что-нибудь другое);
- в основном использование статической проверки типов, так же разрешена run-time проверка типов;
- объектно-ориентированность, все данные обрабатываются как объекты, но есть и свободные функции;
- исходные файлы содержат один модуль и несколько классов, каталоги образуют пакеты, один import определяет одно имя;
- стандартные модули и классы доступны без импорта;
- многие модули являются частью языка, они работают одинаково везде;
- все ключевые слова пишутся заглавными буквами, вы можете использовать все остальные имена не беспокоясь о том, что следующие версии языка поломают вашу программу.

Для демонстрации всего сказанного выше несколько примеров.

Вот, какие правила именования используются в языке:

  • ключевые слова записываются только заглавными буквами;
  • функции, методы и переменные начинаются со строчной буквы или подчеркивания: openFile(), getName(), file, name, _msg;
  • классы и перечисления начинаются с заглавной буквы, но имена не могут иметь вид X_ (где X – это любая буква): Node, FilePointer;
  • имена интерфейсов начинаются с I_: I_writer, I_runnable;
  • имена исключений начинаются с E_: E_negativeArg, E_pastEnd.

Блок заканчивается одной(!) закрывающей фигурной скобкой, открывающей скобки не нужно:

FOR arg IN ARG.getAll()
   IF !didFirst && arg == "-n"
     writeNewline = FALSE
   ELSE
     IO.write(sep + arg)
     sep = " "
   }
   didFirst = TRUE
}

Точки с запятой, в конце выражений так же не нужны.

Пробелы в нужных местах, а так же их отсутствие в ненужных, являются частью языка:

Не правильно

Правильно

Объяснение

func (x) func(x) аргументы принадлежат функциям, а не являются самостоятельной сущностью
[ item, item ] [item, item] код должен быть компактным
[item,item] [item, item] пробел после запятой выделяет элементы
if f#comment if f #comment комментарий является отдельным элементом выражения
x=y1+p3*3 x = y1 + p3 * 3 пробелы должны разделять элементы выражения

Операция конкатенации строк, вроде бы, записывается как “a”..”b”, а не “a”+”b”.

Базовыми типами являются: bool, int (64-бит знаковое целое), int8-int64, bigInt, nat (64-бит целое без знака), nat8-nat64, bigNat, float (64-бит с плавающей точкой), float8-float128, fixed1-fixed15.

Составными базовыми типами являются:

  • string (предполагается, что хранит UTF-8, но может хранить любые символы, в том числе и нулевые);
  • массивы (поддерживается операция resize, но она может быть неэффективной, в качестве типа элемента может использоваться ANY):
    int[100] counters
    int[] oneTwoThree = [1, 2, 3]
    string[100] names = ["Monday", "Tuesday"]
  • туплы:
    FUNC tuple<int, string, list<string>> getValues()
      ...
    }
    int n
    string name
    list<string> list
    [n, name, list] = getValues()     # tuple/list/array unpack
    
    # Initializers
    [< 1, "hello", ["a", "b"] >]      # implied types
    tuple<int, string>(123, "foo")
    tuple<ANY, ANY>   # item containing two arbitrary items
  • списки:
    list<string> words  # list of strings
    list<ANY> list      # list of anything
    
    [1, 2, 3]                        # implied type.
    list<float>.NEW([1, 2, 0.3])     # specified type
    list<ANY>.NEW([1, "word", 0.3])  # any type
  • словари:
    dict<string, Int>     # key is string, value is Int
    dict<string, ANY>     # key is string, any type of value
    dict<ANY, ANY>        # key is any type, value is any type
    
    {'a': 1, 'b': 2}                   # use type of first entry, implied type
    dict<string, float>.NEW({'a': 3})  # specified type
    dict<string, ANY>.NEW({'a': 1, 'b': "x"})
  • мульти-словари (несколько значений для одного ключа):
    multiDict<string, string> mdict = NEW()
    mdict.add("Smith", "John")
    mdict.add("Smith", "Peter")
    mdict.count("Smith")   # 2
    list<string> firstNames = mdict.get("Smith")
    mdict.remove("Smith", "Peter")
    mdict.clear("Smith")
  • множества (ключи без связанных с ними значений):
    set mySet = NEW()
    mySet.add("Peter")
    mySet.remove("Peter")  # same as set.clear("Peter")
    bool hasPeter = mySet.has("Peter")
    mySet.get("Peter")     # error
    mySet.count("Peter")   # 0 or 1
    bool hadPeter = mySet.pop("Peter")
    
    ["Peter", "John"] # initializers
  • мульти-множества (повторяющиеся ключи):
    setmultiSet mset = NEW()
    mset.add("Peter")
    mset.add("Peter")
    mset.count("Peter")   # 2
    mset.remove("Peter")
    mset.count("Peter")   # 1
    mset.get("Peter")     # compile Error
    mset.clear("Peter")

Язык объектно-ориентированный. Для чего в языке могут быть объявлены следующие сущности: CLASS (обычный класс, методы могут иметь реализацию), FINAL CLASS (от которого нельзя наследоваться), ABSTRACT CLASS (не имеет части реализации), MIXIN (не очень пока понятно, как это выглядит), INTERFACE (интерфейс, не может иметь реализации).

При переопределении методов в производных классах нужно использовать специальную метку REPLACE (напоминает override в других языках). Для того, чтобы сделать метод виртуальным (т.е. чтобы разрешить его переопределение в производных типах) нужно пометить его с помощью FUNC.default или PROC.default.

Ну а теперь пора смотреть слайды. Слайд-шоу, как водится, начинается с Hello, World:

MAIN()
  IO.write("Hello, World!\n")
}

Точкой входа в программу является функция MAIN. Модуль IO стандартный, поэтому не нужно его импортировать.

Теперь реализация Unix-овой утилиты echo:

MAIN()
  bool    writeNewline = TRUE
  string  sep = ""
  bool    didFirst
  FOR arg IN ARG.getAll()
    IF !didFirst && arg == "-n"
      writeNewline = FALSE
    ELSE
      IO.write(sep + arg)
      sep = " "
    }
    didFirst = TRUE
  }
  IF writeNewline
    IO.write("\n")
  }
}

Ну а на закуску демонстрация объектной-ориентированности:

CLASS Animal
  PROC.default eat()
    IO.writeLine("I eat like a generic Animal.")
  }
}
 
CLASS Wolf EXTENDS Animal
  REPLACE PROC eat()
    IO.writeLine("I eat like a wolf!")
  }
}
 
CLASS Fish EXTENDS Animal
  REPLACE PROC.default eat()
    IO.writeLine("I eat like a fish!")
  }
}
 
CLASS.final GoldFish EXTENDS Fish
  REPLACE PROC eat()
    IO.writeLine("I eat like a goldfish!")
  }
}
 
CLASS OtherAnimal EXTENDS Animal
}
 
MAIN()
  list<animal.i> animals = NEW()
  animals.add(Animal.NEW())
  animals.add(Wolf.NEW())
  animals.add(Fish.NEW())
  animals.add(GoldFish.NEW())
  animals.add(OtherAnimal.NEW())
 
  FOR a IN animals
    a.eat()
  }
}

Такой вот новый язык. Вроде бы компилятор в состоянии компилировать самого себя и несколько примеров.

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

Лично я пока не понял, что там с исключениями. В правилах именования сущностей исключения присутствуют, но вот в описаниях их не видно.

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

Что здесь интригует: Брам Муленар зарекомендовал себя как прагматик, все-таки ViM – это не абы что. Так что, если он взялся, то может и довести до реализации (камешек в огород Вальтера Брайта – прим.eao197). И если он потом на своем языке замутит какой-то новый редактор или новую версию редактора ViM, то это будет серьезным killer application для нового языка.

В общем, хочу пожелать мужику удачи! Больше нативных языков – хороших и разных! :)

Disclaimer: обзор очень и очень поверхностный. Я даже не смог показать вкусности перечислений и новый хитрый тип BITS (http://www.zimbu.org/design/basic-types).

среда, 21 октября 2009 г.

[comp.prog.thoughts] Программирование и писательство – это разные вещи

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

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

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

Грубо говоря, книга может нравится, а может не нравится. Может помочь читателю в чем-то, может изменить его взгляд на что-то, а может и оставить равнодушным. Но все это субъективно. Тогда как (не)работа программы – вещь объективная. Внешний вид аудио-плейера может нравиться или нет, но если плейер ломается на воспроизведении mp3-файла – это объективно. Если файлы не удается извлечь из архива из-за ошибки в архиваторе, если в самолете отключается автопилот из-за ошибки в его программе, если ракета взрывается на старте из-за ошибки в бортовом ПО, если космический аппарат промахивается мимо Марса из-за ошибки в сопряжении программных систем – все это объективно.

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

Вряд ли кто-нибудь может представить себе детектив, в тексте которого разбросаны вставки вида:

Для Иванова Иван Ивановича: он подкрался к приоткрытой двери, стараясь не скрипеть половицами”

Для Сидорова Сидора Сидоровича: стараясь ступать как можно осторожнее он подошел к наполовину открытой двери”

Или даже:

Для Петрова Петра Петровича, когда он читает в библиотеке: дверь была едва приоткрыта и он очень осторожно…”

Для Петрова Петра Петровича, когда он читает в метро: он тихо стал у двери…”

Маразм, да? А ведь в программировании это обычное дело. И почему? Потому, что у писателя и у программиста очень разные цели изначально. Цель писателя – совершенствование своего текста. Цель программиста – прохождение серии объективных испытаний. Книга должна читаться, программа должна работать. В этом суть.

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

PS. В качестве небольшого disclaimer-а. Я не писатель. В моем багаже всего лишь средних размеров руководство по SObjectizer-4, несколько технических статей и порядка 400 страниц внутрикорпоративной технической документации, ну и этот блог. Так что, очень вероятно, я говорю о вещах, в которых не разбираюсь.

PPS. По-моему, писать сложнее, чем программировать.

[life.photo] Классный снимок из серии “Война войной, а харч по рассписанию!”

вторник, 20 октября 2009 г.

[life.puzzles] Коллекция головоломок от Rustan Leino.

Бертранд Мейер в своем блоге поделился ссылкой на коллекцию головоломок: Rustan Leino’s puzzle collection.

Сам я к головомкам равнодушен – под настроение можно и порешать, но вообще я не любитель лишний раз напрягать мозги :) Но я знаю, что в разных компаниях практикуют озадачивание собеседуемого головоломками или им подобными задачками. Например, в Google. Так что, если кто-то хочет потренироваться перед собеседованиями – может попробовать на этих задачках :)

[comp.prog.thoughts] У чтения хорошего кода есть большая проблема

Возвращусь к цитате из интервью Брайана Кернигана о чтении чужого кода:

Чтение чужого кода так же бесценно. Конечно, это подразумевает, что код хорош; я не вижу много пользы от чтения больших объемов плохого кода, разве что научиться не писать так.

Первоначально я перевел ее неправильно, указав, что чтение чужого кода не имеет ценности. По двум причинам:

  • ошибочно решив, что invaluable переводится как “не имеющий практической ценности”, вместо “бесценный”;
  • с чтением хорошего кода связана очень большая проблема.

Я подумал, что Керниган как раз намекает на эту проблему, поэтому-то и не предает значения чтению кода, потому не заглянул в словарь для точного перевода invaluable. :(

Так что же это за проблема такая? Может быть, это отсутствие хорошего кода? Нет. Хороший код встречается, и не так уж редко.

Главная проблема с хорошим кодом в том, что на него не обращаешь внимания. Ведь зачем программисту приходится читать чужой код? Не для того же, чтобы узнать, сколько пробелов используется в отступах (ну такое бывает, но крайне редко). Я читаю чужой код, чтобы понять, как в нем делаются конкретные вещи. Например, как организуется учет тайм-аутов при получении ответа SMTP сервера. Или как формируют HTTP-заголовки в SOAP запросе. Я ищу в коде решение конкретной задачи. И чем проще это решение найти, чем меньше я продираюсь сквозь код, тем код лучше. А вот с плохим кодом ситуация обратная: при попытке найти в коде суть решения основные усилия тратятся на борьбу с кодом. Плохой код, в отличии от хорошего, виден сразу.

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

Чтение плохого кода так же не имеет большого смысла – ведь важно не столько понять, что код плох (это не сложно), и даже не почему он плох (это сложнее, в особенности, если приходится свои выводы оформлять для результатов code review). Самое сложное с плохим кодом – это понять, как же не писать такой код. А понять это – это научиться писать хороший код… Опаньки, а круг-то замкнулся… :)

понедельник, 19 октября 2009 г.

[comp.prog] Новости с LOR-а: GCD во FreeBSD и Qt4 под QNX и VxWorks

Две новости с linux.org.ru, которые меня заинтересовали:

Первая о том, что Grand Central Dispatch от Apple был портирован под FreeBSD. Как я понял, сейчас порт GCD на FreeBSD находися в ранней стадии, но в версии FreeBSD 8.1 ожидается его наличие уже “из коробки”. Видимо, компания Apple заинтересована в том, чтобы ее GCD не стал “чисто MacOS X” примочкой и работал в других Unix-ах. Что позволит разработчикам ПО использовать GCD не опасаясь привязаться только к MacOS X. (О Grand Central Dispatch я уже писал раньше, подробнее об этой технологии можно прочитать, например, здесь (спасибо ув.тов.Korzh Pavel за ссылку)).

Вторая новость о том, что в Qt 4.6 будет добавлена поддержка новых платформ (Windows 7, MacOS X 10.6, QNX, VxWorks и OS S60). Что не может не радовать – больше платформ, хороших и разных! :) Так же, Nokia собирается увеличить бюджет разработчиков Qt на 50%, что опять же не может не радовать.

Новость про Qt интересна мне, в первую очередь, из-за выбора базовой библиотеки для разработки SObjectizer 5. Пока есть всего несколько вариантов: ACE – средняя по размеру, в старом стиле, изрядно поднадоевшая в последнее время; Boost – большая, ориентированная на будущее, но с не очень большим околосистемным функционалом; Qt – громадная библиотека, ориентированная в первую очередь на GUI, но и с неплохи базовым слоем; POCO – небольшая, симпатичная, но несколько “поверхностная”. Выбор пока не сделал, думаю. Но новость о портировании Qt на новые платформы все больше и больше снижает шансы ACE :)

воскресенье, 18 октября 2009 г.

Вопрос к читателям блога: нужна ли моя критика?

Хочу спросить у читателей, нужно ли мне публиковать у себя в блоге заметки вроде таких: “Вот намедни прочитал там-то и там-то вот такую вот фигню. Фигня это, поскольку то-то и то-то” (например, к такого рода заметкам я отношу “На что направлены усилия разработчиков языков программирования?”, “Не могу не процитировать” и “Несколько слов об исключениях”)?

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

PS. За мной еще обещание написать, почему мне не нравится подход Boost.Serialization. Я помню об этом, но не имею достаточно времени, чтобы заново проштудировать документацию. А писать по воспоминаниям двух-трех летней давности не хочется. Но я обязательно сдержу свое обещание.