12 мая я выступил на конференции ADD-3 с докладом об опциональной типизации в динамических языках. Вот слайды доклада (HTML, требуется нормальный браузер) и его аннотация:
Языки со статической и динамической типизацией сосуществуют уже очень долгое время, поскольку у обоих подходов есть свои плюсы и минусы. Динамическая типизация уступает статической по популярности, поскольку обладает рядом известных недостатков. В таких языках больше ошибок происходит во время выполнения, слабее поддержка со стороны IDE, хуже производительность программ.
В докладе рассматривается получающая распространение опциональная типизация, которая поможет сгладить недостатки динамических языков. Описываются способы введения опциональной типизации в динамические языки на примере языков Python, Erlang, Dart. Рассматривается, как применяется опциональная типизация в статическом анализе кода для повышения его производительности и корректности. Даётся обзор инструментов, использующих опциональную типизацию.
Сегодня я выступил на технологическом семинаре в СПбАУ с докладом о статическом анализе в IDE (вот слайды). Основной идеей доклада было рассказать об особенностях анализа в IDE по сравнению с другими инструментами и показать на примерах, как он выполняется.
На мой взгляд, в изложении этой темы ещё есть над чем работать. Получилась слишком большая обзорная часть, мало внимания было уделено конкретным примерам и способам анализа кода.
Спасибо слушателям семинара за внимание и вопросы. Я бы был рад, если бы вы оставили обратную связь по докладу или по слайдам здесь в комментариях. Что вам понравилось, не понравилось, о чём хотелось бы услышать.
Несколько дней назад я начал знакомиться с новым языком Rust, разрабатываемым в Mozilla Labs. В конце января вышла версия 0.1, которую можно скачать и попробовать. Предварительную версию спецификации я прочитал ещё осенью 2011 года и заинтересовался этим языком. Отчасти это связано просто с интересом к новым языкам, отчасти — с некоторым разочарованием в языке Go. Уже прошло два года, а в Go по-прежнему нет generics. К тому же есть много мелочей (например, табуляция вместо пробелов), каждая из которых ни на что не влияет, но вместе они оставляют неприятное впечатление.
К языку Rust у меня наоборот сразу сложилось приятное отношение:
Присутствует в языке Rust и пара изюминок: относительно редкая пока многозадачность через обмен сообщениями без разделяемых данных в стиле Erlang, а также уникальная система typestate — статически проверяемые состояния типов, в которых разрешены те или иные операции с ними. Эта концепция раньше встречалась только в экспериментальных языках. С её помощью можно на пользовательском уровне решать проблемы уникальных указателей, неинициализированных переменных и ряд других. Стоит заметить, что именно эти проблемы решены с помощью typestate внутри компилятора, а для использования на уровне пользователя языка представляется пока лишь некоторая часть возможностей typestate.
Наконец, особенности языка, влияющие на эмоциональное впечатление: приятный краткий синтаксис, хорошие конвенции форматирования кода и именования, аккуратный читаемый код стандартной библиотеки, отзывчивое сообщество.
Думаю, я ещё напишу об этом языке. А пока что для создания первого впечатления
ниже я привожу программу на Rust, вычисляющую с помощью его стандартной
библиотеки std контрольную сумму SHA-1 от файла. Она работает аналогично
стандартной утилите sha1sum.
Вот эта программа, файл sha1sum.rs:
use std;
import std::io;
import result::{ok,err};
import std::sha1::{sha1,mk_sha1};
fn reader_sha1sum(reader: io::reader) -> sha1 {
const bufsize: uint = 4096u;
let sha1 = mk_sha1();
while !reader.eof() {
sha1.input(reader.read_bytes(bufsize));
}
ret sha1;
}
fn main(args: [str]) {
if vec::len(args) != 2u {
fail "usage: sha1sum FILE";
}
let filename = args[1];
alt io::file_reader(filename) {
ok(reader) {
let sha1 = reader_sha1sum(reader);
io::println(#fmt("%s %s", sha1.result_str(), filename));
}
err(msg) { fail msg; }
}
}
#[test]
fn test_sha1_byte_buf() {
let reader = io::string_reader("Привет, мир!");
let expected = "0cb95b7891ff182f0972be8754ec934df65af21c";
let sha1 = reader_sha1sum(reader);
assert sha1.result_str() == expected;
}
Всю работу выполняет функция fn reader_sha1sum(reader: io::reader) -> sha1,
возвращающая объект с хранимой контрольной суммой для входящего файлового
потока. Вообще, интерфейс io::reader здесь немного излишний. Достаточно было
бы интерфейса для итерации по последовательности из байтовых массивов [u8]. В
языке есть средства для этого, но стандартная библиотека итерации ещё не
закончена, а реализовывать этот интерфейс прямо в коде я не стал, чтобы не
усложнять пример.
Можно либо просто скомпилировать программу (тогда будет выполняться fn
main(args: [str])), либо скомпилировать тесты в ней при помощи опции
компилятора --test (тогда выполнятся функции, проаннотированные с помощью
#[test]. Кстати, в стандартной библиотеке есть пока ошибка в получении
строкового представления контрольной суммы, так что тест не пройдёт.
Вот так-то, интересный язык!
Поздравляю всех френдов с Новым годом! Пусть в 2012 году питонисты перейдут на Python 3, джависты — на Kotlin, наша сборная выиграет ЧЕ-2012, а в Россию придёт свобода слова и демократия! :)
Недавно я искал утилиту для визуализации занятого места в файловой системе и нашёл замечательную программу xdu. Так выглядит её интерфейс:

Можно перемещаться между каталогами (зумиться и возвращаться назад) при помощи кликов на прямоугольниках.
xdu решает задачу просмотра занятого места в духе Unix. Поскольку уже есть программа, которая собирает информацию о занятом месте на диске (утилита du), то требуется лишь визуализировать собранные этой программой данные. Пример выходных данных du:
25 /var
15 /var/lib
14 /var/lib/pacman
12 /var/lib/pacman/local
11 /var/cache
6 /var/cache/pacman/pkg
6 /var/cache/pacman
То есть строчки с числом-размером каталога и его названием, где каталоги разделены слэшами. Размер отделяется от названия табуляцией.
xdu читает данные в этом формате, но знает лишь то, что здесь представлено взвешенное дерево. Число в строке — вес ветки дерева, а название — это иерархический путь до этой ветки.
Таким образом, с помощью xdu можно визуализировать любые взвешенные деревья, достаточно представить их в таком формате. Более того, писать программу вычисления дерева можно на любом языке, поскольку визуализатор просто принимает данные со стандартного ввода. Вот как, например, выглядит типичное использование xdu для просмотра занятого места в ФС:
$ du -xm / | xdu -n
Несколько слов о коде программы xdu. Её написал Phillip Dykstra в 1991 году. Последняя версия 3.0 была выпущена в 1994 году. Программа написана на языке C и использует библиотеку X11 Athena Widgets. Для сборки используется imake проекта X11 для генерации Makefiles. В принципе можно собрать её и вручную, указав библиотеки в опциях компилятора. xdu занимает 1300 строк кода:
$ wc -l *.c *.h
770 xdu.c
496 xwin.c
1 patchlevel.h
1 version.h
1268 total
Программа отлично собирается на текущей версии Arch Linux (она есть в AUR) несмотря на свой 20-летний возраст. Некоторые проблемы, связанные с её возрастом, заключаются в том, что она не понимает не-ASCII символов и пробелов в именах веток дерева. В остальном же её можно использовать и по сей день. Я выложил xdu на GitHub на всякий случай.