Wednesday, July 25, 2012

Без названия #1

Мне вдруг сегодня вспомнился один занятный случай из далекого прошлого. Дело было в летнем лагере, мне лет 13. В один из последних дней нам устроили глобальный тимбилдинг, как ныне говорят: всем выдали пачку порезанных ниток и пустые бусы с меленьким навесным замочком и парой ключиков. Один ключ, понятное дело, себе, другой - самому близкому человеку в лагере. А вот ниточки на бусы можно было повязывать кому угодно, только при этом надо было объяснить, с чего вдруг такая вольность в поведении. В тот день я чем-то отравился и довольно долго отлеживался в палате. В итоге бусы к концу дня бусы у меня пустые, ключа два, да еще и пучок ниток. Ну я и пошел всем доказывать, как они мне дороги и как я всем благодарен (сарказма нет, с ребятами из своего отряда я очень подружился). Подхожу к девушке, спрашиваю: "Где, мол, твои бусы?". А она как-то так обрадовалась, удивилась: "Ты хочешь мне повязать?!". Ниточку я успешно отдал, и даже взамен получил, кажется. А сейчас вот вспомнил тот случай и задумался: да что ж в этом было такого? Мы примерно 10 дней целыми сутками все вместе были, сплачивались по полной, а ниточку повязать - это уже слишком? Да я ж там всех любил примерно одинаково, мне это в радость было - дарить ниточки и теплые слова. Вывод тут какой: мы, люди, часто уделяем слишком много внимания совершенно незначительным вещам. А значительность определяем для себя сами.

Что-то затянулось вступление, я ж про другое хотел рассказать. Вот есть в мире масса языков программирования, многие из них очень широко распространены, некоторые я знаю. Больше всего мне приходится писать на Perl'е. Это восхитительно ужасный язык программирования. Столько всего можно сделать в одну строчку и получить от этого такой гиковский кайф, что захочется продолжать и продолжать. Но вот через неделю этот код проще переписать, чем прочитать...
Но если уж писать на перле, то извольте освоить сложные конструкции типа хэша хэшей хэшей. Вот о них и хочу рассказать.
Есть у нас хэш:
my %hash = (
    'first'  => 1,
    'second' => [1..10],
    'third'  => 'string here'
);
Второй элемент есть не что иное как ссылка на массив, т.е. общая структура чуть сложнее самой простой. Напишем простенькую функцию для распечатки такой структуры:
sub print_my_hash($) {
    my $ref = shift;
    map {
        if (ref($ref->{$_}) eq 'ARRAY') {
            print join(', ', @{$ref->{$_}}), "\n";
        } else {
            print $ref->{$_}, "\n";
        }
    } keys %{$ref};
    print "\n";
}
Если обнаруживаем ссылку на массив - обрабатываем отдельно. При распечатке получим вот это:







Пока делал скрин и, не побоюсь этого слова, обрезал его, чуть с ума не сошел: в убунте сначала пришлось найти приложение, которое бы могло это сделать, а потом убедить его работать так, как мне надо, а не так, как создатель пожелал. Уфф, не отвлекаюсь.

Вернемся к коду: все распечаталось как мы ожидали (я-то точно). Теперь скопируем наш хэш в другой:
my %copy = %hash;
Было не сложно, правда? Распечатаем и его:








Ура, отличий нет, копирование прошло успешно.
Теперь возьмем и поменям какой-нибудь элемент массива в новом хэше и распечатаем его:
$copy{'second'}->[4] = 100500;
print_my_hash(\%copy);




Все опять именно так, как ожидалось.

Внимание, сейчас будет развязка. Приготовились? Точно? Уверены? Вопросы уже достали? Ок, заканчиваю издеваться над теми, кто правдами или неправдами дочитал до этого момента: что находится в пятом элементе (индекс = 4) массива в первом хэше?
Вопрос выглядит совершенно по-идиотски, если вы пишете/писали на C. Он даже для опытных перлописцев слишком прост. Но прежде чем назвать меня профнепригодным представьте себе конструкцию из хэша с десятком полей, значениями которого могут быть и скаляры (в перле это и строки и числа), и хэши, и ссылки на массивы и хэши. Скажете, можно без этого? Наверно, но это же перл, это нормально. Правильный ответ, кстати, 100500.

К чему я это? Извольте: все современные фреймверки и языки программирования сильно абстрагируют обычного программиста (меня) от реально происходящих в машине событий. Ничто не заменит мяса в колбасе базовых знаний ОС, структур данных и умения работать с памятью.

Полный код и постскриптумы:
#!/usr/bin/perl

use strict;
use warnings;

sub print_my_hash($) {
    my $ref = shift;
    map {
        if (ref($ref->{$_}) eq 'ARRAY') {
            print join(', ', @{$ref->{$_}}), "\n";
        } else {
            print $ref->{$_}, "\n";
        }
    } keys %{$ref};
    print "\n";
}

my %hash = (
    'first'  => 1,
    'second' => [1..10],
    'third'  => 'string here'
);
print_my_hash(\%hash);

my %copy = %hash;
print_my_hash(\%copy);

$copy{'second'}->[4] = 100500;
print_my_hash(\%copy);

print_my_hash(\%hash);

PS: зачем я объединил два разных поста в один? Не знаю, само собой.
PPS: с описанным примером сталкивался в реальной работе дважды или трижды. Всегда все было не так очевидно, как в описанном здесь примере, и связано было, в основном, с перлофичами.
PPPS: код подсвечен с помощью этого: http://tohtml.com, а написан с помощью Sublim
PPPPS: убунта неприятно удивила, но в венду не перезагружусь
PPPPPS: в блогспоте мне не нравится - неудобно писать свои мысли, настраивать форматирование и пр.

No comments:

Post a Comment