Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Что за странная конструкция?! видимо это "замыкания вместо обьектов"? 
:(
    Опции темы
Ramirez
Дата 2.4.2007, 21:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 305
Регистрация: 18.1.2005
Где: Moscow, ExUSSR

Репутация: 4
Всего: 5



Ковырял тут фильтр POE::Filter::JSON т.к. работать он у меня отказался. Ругается на такую строку:

Код

sub get_one_start {
    my ($self, $lines) = @_;
    for (@{ $lines }) {
     push( @{$self->[BUFFER]}, $_ );    
    }
}

а конкретно на строку 4, а имненно на конструкцию @{$self->[BUFFER]}
Код

Can't use string ("") as an ARRAY ref while "strict refs" in use at lib/POE/Filter/JSON.pm line 48.



что это за конструкция такая?! единственное похожее нашел в "рецептах..." под названием  "Применение замыканий вместо обьектов"
Код

@{$self->[BUFFER]}
а точнее как это понимать
$self->[BUFFER]


причем обьявляется эта хрень в начале пакета (класса) вообще странно:
Код

sub BUFFER () { 1 }



конструктор тоже для меня странно выглядит:
Код

sub OBJ    () { 0 }
sub BUFFER () { 1 }
sub PARAMS () { 2 }

sub new {
    my $type = shift;
    croak "$type requires an even number of parameters" if @_ % 2;

    my $self = bless [
        JSON->new(), # OBJ
        ' ',        # BUFFER
        { @_ },      # PARAMS
    ], $type;
    $self;
}

в качестве объекта bless передается, я так понимаю, анонимный массив, который приводится к классу $type
а как это вязано с 
Код

sub OBJ    () { 0 }
sub BUFFER () { 1 }
sub PARAMS () { 2 }


Кто может обьяснить как это работает?

Это сообщение отредактировал(а) Ramirez - 2.4.2007, 23:14
PM ICQ   Вверх
korob2001
Дата 3.4.2007, 02:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 31
Всего: 61



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

sub OBJ    () { 0 }
sub BUFFER () { 1 }
sub PARAMS () { 2 }

Это константы, точнее их подобие. Аналогично можно, а главное нужно, было бы написать так:
Код

use constant OBJ => 0;
use constant BUFFER => 1;
use constant PARAMS => 2;

Тогда бы ни у тебя, ни у кого-то другого не возникло бы вопроса: Что это за хрень?

Теперь перейдём к конструктору:
Код

sub new {
    my $type = shift;
    croak "$type requires an even number of parameters" if @_ % 2;

    my $self = bless [
        JSON->new(), # OBJ
        ' ',        # BUFFER
        { @_ },      # PARAMS
    ], $type;
    $self;
}

Перепишем его в более понятную форму:
Код

sub new {
    my $type = shift;
    croak "$type requires an even number of parameters" if @_ % 2;

    my $self = [
          JSON->new(),  # Первый элемент анонимного массива, индекс 0
          ' ',          # Второй элемент анонимного массива, индекс 1
          { @_ },       # Третий элемент анонимного массива, индекс 2
    ];

    # Посвящаем наш анонимный массив в объекты
    bless($self, $type);

    # Возвращаем созданный объект
    return $self;
}

Теперь обрати внимание на коментарии, которые я прописал напротив каждого элемента, особенно на их индекс, а так же обрати внимание на значение констант:
Код

sub OBJ    () { 0 }
sub BUFFER () { 1 }
sub PARAMS () { 2 }

Думаю ты уже понял, что делает интересующая тебя конструкция.
Код

$self->[BUFFER];    # Равносильно, этому $self->[1], так как константа BUFFER равна единице.

Т.е. мы обращаемся ко второму элементу анонимного массива (index 1 или константа BUFFER), который мы создали в конструкторе и там же посвятили его в объекты.

Теперь можно перейти к самому главному:
Почему же ты получаешь ошибку?
Цитата

Can't use string ("") as an ARRAY ref while "strict refs" in use at lib/POE/Filter/JSON.pm line 48.

Всё станет понятно, если посмотреть на код:
Код

sub get_one_start {
    my ($self, $lines) = @_;
    for (@{ $lines }) {
     push( @{$self->[BUFFER]}, $_ );  # Особенно на эту строку   
    }
}

Здесь метод пытается разименовать ссылку на анонимный массив, вместо которого у нас, в конструкторе, была создана сторока состоящая из пробела.  smile  Вот она:
Код

' ',          # Второй элемент анонимного массива, индекс 1

Собственно здесь и спотыкается программа. Затем код пытается впихнуть, в якобы разименованный массив все элементы, которые были переданы методу get_one_start(), это следующее место где Perl споткнулcя бы, если бы он каким-то образом пропустил разыменование строки, как ссылки на массив.

Исправить этот глюк, можно заменив, строку в теле конструктора:
Код

' ',          # Второй элемент анонимного массива, индекс 1

На такую:
Код

[],          # Второй элемент анонимного массива, индекс 1

Т.е. создав в качестве изначального буфера не строку с пробелом, а пустой анонимный массив.
Вот собственно и всё.

ЗЫ: А вообще, всё что мы здесь проанализировали, написано глючно. И использовать такой класс лучше после полного просмотра и редактирования исходного кода. Разумеется, если отдаёшь себе отчёт в том, что делаешь. Либо попытаться найти что-то аналогичное, но написанное более профессионально.

ЗЗЫ: Я не смотрел исходники этого класса, анализировал только по тому коду, который привёл ты в своём посте.

Это сообщение отредактировал(а) korob2001 - 3.4.2007, 03:12


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Nab
Дата 3.4.2007, 03:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



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

А теперь подробно:

1. В POE как правило объекты реализованы не как приведенный хеш, а как приведенный массив, то есть ссылка на объект это ссылка на массив.
2. В связи с пунктом первым, у полей нет имен, но обращаться к ним всеже удобней не по числовому индексу, а по имени, для того и создаються такие пустышки, функции с порядковыми номерами... как правило в верхнем регистре.
3. Тот же метод имен вместо индексов используеться при передаче параметров:
Код

sub my_event {
    my ($kernel, $heap, $sender, $param0, $param1) = @_[KERNEL, HEAP, SENDER, ARG0, ARG1];
    ...
}

По поводу того что это надо было делать через use const, то ничего не скажу, я не знаю чем руководствовались при выборе такого способа, возможно из-за производительности, возможно из-за памяти, не знаю... 
Но меня такая политика устраивает, и считаю что самое главное, это не каким именно способом реализовано (всеже многовариантность, это фишка Perl), а то что этот способ един и единообразен для всей системы... То есть если человек освоиться с POE, то изучение дополнительных компонентов, не повлечет за собой и изучение нового интерфейса доступа и т.д. Многовариантность, многовариантностью но PerlStyle тоже существует smile


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
korob2001
Дата 3.4.2007, 04:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 31
Всего: 61



Цитата(Nab @  3.4.2007,  00:39 Найти цитируемый пост)
По поводу того что это надо было делать через use const, то ничего не скажу, я не знаю чем руководствовались при выборе такого способа, возможно из-за производительности, возможно из-за памяти, не знаю... 

Ну если бы из-за производительности или памяти, тогда можно было бы использовать идексы вместо констант, в конструкторе можно было бы избавиться от переменной $self, так как bless возвращает посвящённую ссылку.
use constant создаёт ту же функцию без параметров, так что не думаю что последние будут быстрее первых или ресурсов израсходуют меньше. Просто выглядит use constant более понятно.


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Ramirez
Дата 3.4.2007, 05:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 305
Регистрация: 18.1.2005
Где: Moscow, ExUSSR

Репутация: 4
Всего: 5



Цитата(Nab @  3.4.2007,  03:39 Найти цитируемый пост)
...привыкшие к тому что объект это хеш....
...В POE как правило объекты реализованы не как приведенный хеш, а как приведенный массив, то есть ссылка на объект это ссылка на массив.


Действительно, совсем не пришло в голову... тогда все складывается =)


Цитата(korob2001 @  3.4.2007,  02:35 Найти цитируемый пост)
Здесь метод пытается разименовать ссылку на анонимный массив, вместо которого у нас, в конструкторе, была создана сторока состоящая из пробела
 я уж потом тоже методом тыка нашел =)


korob2001, Nab, СПАСИБО! 


Цитата(korob2001 @  3.4.2007,  02:35 Найти цитируемый пост)

ЗЫ: А вообще, всё что мы здесь проанализировали, написано глючно. И использовать такой класс лучше после полного просмотра и редактирования исходного кода. Разумеется, если отдаёшь себе отчёт в том, что делаешь. Либо попытаться найти что-то аналогичное, но написанное более профессионально.
  Модуль похоже действительно придется переписать... много корявых мест...

Это сообщение отредактировал(а) Ramirez - 3.4.2007, 15:04
PM ICQ   Вверх
tishaishii
Дата 3.4.2007, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Создатель
***


Профиль
Группа: Завсегдатай
Сообщений: 1262
Регистрация: 14.2.2006
Где: Москва

Репутация: 4
Всего: 8



Код
sub iter {
    my($from, $for, $mul)=(shift, shift, shift);
    +sub {
        return $from*=$mul if $for-->0;
        +$for=undef
        #+$for-->0?($from*=$mul):($for=undef)
    }
}

my$iter=&iter(1, 10, 2);
print $_, "\n" while $_=$iter->();

PM MAIL ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0497 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.