суббота, 25 апреля 2009 г.

Switch

м... как оказалось, в Python нет оператора switch, как собственно и тернарного оператора. Но явное отсутствие последнего ещё как-то можно пережить, но вот реализовывать switch(){} через такое...:

{
'option' : fun1,
'option2' : fun3,
'option3' : fun4
}['option']()

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

Перехват потока вывода в Ruby

Ну вот таки добрался до писанины, и вы читаете эти страдания полуношника (чёрт! быква "ш" опять с трудом набирается...).

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

Итак, буффер стандартного потока вывода в Ruby определяется глобальной переменной $std_out. Она используется ядром для основного процесса вывода. По природе своей она значением содержит экземпляр объекта StringIO ( константа - STDOUT), который и поставляет разнообразнейшие методы для реализации буфера хранения потоковых данных и их выброса куда вам необходимо. Его декларация содержится в файле stringio.

Описанная же в начале проблема решается довольно просто, как, вероятно, многие из читателей уже смогли понять - назначением $std_out пользовательского объекта типа StringIO, в который и будет отвечать за буфферизацию всего, что будет выброшено в поток до того момента, пока не будет вновь назначен в качестве основного стандартный поток (STDOUT).

Вот что у меня получилось:
# output_handling.rb
# Подключаем файл поставляющий класс StringIO
require "stringio"
# Создаём промежуточный буффер
temp_output = StringIO.new();
# Указываем созданный нами буффер в качестве основного
$std_output = temp_output;
# Выводим некоторые данные в поток
puts "I hate you! I hate you! I hate you!!!!!!!";

# Вновь указывает стандартный поток вывода в качестве основного
$std_output = STDOUT;

# Переводим указатель смещения на начало
temp_output.rewind();
# Выводим содержимое временного буффера
puts tmp_output.read();


Вообще, наверное не стоит рассказывать о всей пользе подобной возможности. Однако спорный момент "хорошести" подобного подхода. Так, при переопределении потока вывода вы это делаете для области всей программы, что не хорошо в контексте многопоточности. Эта проблема довольно хорошо решается в том же PHP, где перехват данных потока осуществляется с помощью возможностей платформы (ob_start() и ob_end()).

Ruby

Ах... какое же тёплое одеяло =))

Вот потратил таки сегодня целых 6 часов на такую вещь как Ruby, в результате чего почти свободно могу на нём писать. Язык по себе довольно приятный, удобные, до безобразия объектный, лаконичный и т.д. и т.п. Чтобы понять все аспекты некоторого языка, вполне достаточно написать на нём более ли менее полновесную MVC-систему. Написал =) При этом столкнулся с множеством "бяк", среди которых наиболее мерзкие:
1. Абсолютно непонятная система подключения классов по требованию (аналог PHPшному __autoload'у)
2. Если и существует метод перехвата потока вывода до того, как он будет "выведен", то я его пока не нашёл =(
3. Возможность встраивания Ruby-paste'ов непосредственно в HTML не поерживается на уровне платформы и посему приходится извращаться, а учитывая п.2, создание методов обработки .rhtml-файлов превращаются в достаточно медитативную задачу.
4. Нет нормального трэйсера для объектов - аналога help() в Python или там разных var_dump/print_r в РНР. Использовать деббагер? Ммм... ну как вариант, но я это делал досточно редко за свою жизнь, разве что только в плане runtime-отладки в C++.

Вообщем, если выбирать между PHP И Ruby, то я безусловно за Ruby, поскольку он явно не хуже первого, хотя в некотором плане и немного менее удобный. А вот если сравнивать с Питоном, то я всё-таки склоняюсь в сторону последнего. Поскольку Python хоть и так же половинчатый - двупарадигменный - что меня всегда бесило, но в нём всё как-то более явно, наглядно, когда на нём пишешь не так часто приходится копаться в документации, чтобы понять, как реализовать банальные вещи.