yorool_gui: (Default)
Michael Ilyin ([personal profile] yorool_gui) wrote2005-03-14 05:10 pm

о Perl

Перл замечательный язык, когда на нем пишу Я. Когда на нем пишут другие -- это кошмар. И подозреваю, что это взаимно.

use strict;
...
no strict 'refs';
...
$self->{LABELS}->{$title} = $3;
$self->{LABELS}->{$title}->{NUM} = $num++;

Это работатет. Но я не понимаю, ради чего надо так извращаться. Это не тот Перл, на котором пишу я. На моем Перле ref $self->{LABELS}->{$title} будет либо SCALAR, либо HASH, но никак не то и другое одновременно. А вот на Перле этого человека в $self->{LABELS}->{$title} хранятся сразу два значения и ему это удобно. Но это другой язык.

[identity profile] sorhed.livejournal.com 2005-03-14 02:21 pm (UTC)(link)
У меня в одном месте no strict таки пользуется. Но я его уберу, если вы скажете, как можно без no strict refs обратиться к $AUTOLOAD :)

[identity profile] blacklion.livejournal.com 2005-03-14 02:23 pm (UTC)(link)
Да, это, пожалуй, единственный пример... Но тут явно не тот случай.

[identity profile] sorhed.livejournal.com 2005-03-14 02:27 pm (UTC)(link)
Ну, не только. Иногда (например, в коде одной извращённой штуки, которая использует собственную нестандартную модель наследования) бывают нужны symbolic references. Случаи, конечно, единичные. Но бывают.

(хотя, конечно, всё равно было бы неплохо, чтобы strict шёл по дефолту, а извращенцы вроде меня использовали бы no strict в специально отведённых местах).

[identity profile] blacklion.livejournal.com 2005-03-14 02:29 pm (UTC)(link)
(например, в коде одной извращённой штуки, которая использует собственную нестандартную модель наследования)
А вот какова необходимость в том, что бы она была такая ивзращенная?

[identity profile] sorhed.livejournal.com 2005-03-14 02:32 pm (UTC)(link)
Очень просто.
Где-то в недрах perldoc perlobj сказано, что если менять @ISA динамически где ни попадя, то ничего хорошего из этого не выйдет, так как оно там кэшируется. А мне как раз надо было динамически. Чтобы если девелопер захотел в живой системе созданный объект унаследовать от чего-нибудь ещё — то нет проблем.

[identity profile] blacklion.livejournal.com 2005-03-14 02:37 pm (UTC)(link)
А может лучше тогда переписать на python? :)
Вообще, плохо понимаю, зачем такое может понадобится и почему тогда это не реализовать через AUTOLOAD в виде модуля Class::DynamicInheritance какого-нибудь, от которого наследоватьв се такие классы...

[identity profile] sorhed.livejournal.com 2005-03-14 02:40 pm (UTC)(link)
Да я так почти и сделал.
Ну, в общем, вот о чём я говорю:

sub AUTOLOAD {
    my ($this) = @_;
    my $method_name = $AUTOLOAD;
    $method_name =~ s/^(.*):://;
    my $class_name = $1;
    $class_name =~ s/^(.*):://;
    my $package_name = $1;
    my $method = $this->get_method($method_name, $class_name);
    if ($method) {
        my $code = $method->{code};
        my $result = eval ($code);
        if ($@) { $this->error($@); }
        return $result; 
    } else {
        $this->error("Method $method_name for $class_name is not found.");
    }
}

sub get_method {
    my ($this, $method_name, $class_name) = @_;
    my $class = $this->{STORAGE}->get_class($class_name);
    my $class_id = $class->{class_id};
    my $method = $this->{STORAGE}->get_object(-name => $method_name,
                                      -class => 'Method', 
                                      -of_class => $class_id);
    if ($method) {
        return $method;
    } else {
        if ($class_name ne 'Object') {
            my $parent_class_id = $class->{parent};
            my $parent_class_name = 
                    $this->{STORAGE}->get_class($parent_class_id)->{name};
            return $this->get_method($method_name, $parent_class_name);
        } else {
            return undef;
        }
    }     
}

[identity profile] blacklion.livejournal.com 2005-03-14 02:46 pm (UTC)(link)
Бррр... Не вижу здесь не-стриктных референсов... Хотя eval($code) не очень понял зачем нужно, почему не $code(). Или там оно действительно строкой хранится?

[identity profile] sorhed.livejournal.com 2005-03-14 02:48 pm (UTC)(link)
Строкой. Из базы же достаётся.
А нестриктные референсы я всё-таки убрал, оказывается :) Блин, вот что значит три месяца в код не заглядывать.

[identity profile] blacklion.livejournal.com 2005-03-14 02:54 pm (UTC)(link)
А, ну из базы -- тогда да :) Это, как ты понимаешь, неочевидно из этого куска кода.

Хотя, производительность так должна страдать...

[identity profile] sorhed.livejournal.com 2005-03-14 02:55 pm (UTC)(link)
Есессно. Но Cache::Memcached никто не отменял.

[identity profile] blacklion.livejournal.com 2005-03-14 02:59 pm (UTC)(link)
Это ничем не поможет тормознутости eval "code"; или ты про кеширование результатов?

[identity profile] sorhed.livejournal.com 2005-03-14 03:00 pm (UTC)(link)
И того, и другого, и можно без хлеба а ещё я где-то слышал, что после эвала можно просто хранить ссылки на code references, только не знаю пока ещё, как :)

[identity profile] blacklion.livejournal.com 2005-03-14 03:09 pm (UTC)(link)
Вот последнее очень интересно. В JavaScript я просто скажу

var code = new Function( "some code; goes; here;" );

А про Perl -- Я как раз только что думал, как бы получить CodeV из eval'а... Вот так, сходу, способа не вижу... Т.е. вижу, но кривой до невозможности:

sub getCode
{
  my $code = $_[0];
  local *F;
  my $name = sprintf( "__getCode_unique_name_0x%08x_%s", $$, md5_hex($code) );
  open(F, "> /var/tmp/$$.pl");
  print F "sub ", $name, " { ";
  print F $code;
  print F "}";
  close(F);
  require "/var/tmp/$$.pl";
###
# DAMN!
  {
    no strict 'ref';
    $code = \&{$name};
  }
###
  unlink("/var/tmp/$$.pl");
  return $code;
}

Но ведь крииииво... И будет ли работать... Ччерт, давно на перле не писал...

[identity profile] sorhed.livejournal.com 2005-03-14 03:14 pm (UTC)(link)
В общем, если нужен источник вдохновения — рекомендую зайти на www.everydevel.com и скачать оттуда Everything Core (на котором, кстати, построен всеми нами любимый perlmonks.org). Я лично уже года два тягаю оттуда идеи :)

[identity profile] blacklion.livejournal.com 2005-03-14 03:19 pm (UTC)(link)
Так не интересно :)

[identity profile] blacklion.livejournal.com 2005-03-14 03:25 pm (UTC)(link)
ХА! Все проще! Прочел perldoc -f do внимательно (придя оттуда из perldoc -f require) и родил слкедюущую работающую конструкцию:


my $codeRef = eval "sub { $codeStr } ";

ВСЕ! Работает!

[identity profile] sorhed.livejournal.com 2005-03-14 03:27 pm (UTC)(link)
Гы, логично :)

[identity profile] co108.livejournal.com 2005-03-15 08:28 am (UTC)(link)
ой, а что вы за гарево-погарево тут делаете если не секрет? пишите перл++ на перле? :))

[identity profile] sorhed.livejournal.com 2005-03-15 11:27 am (UTC)(link)
Хуже. Smalltalk (точнее, Gemstone/S) на перле :)

[identity profile] sorhed.livejournal.com 2005-03-14 02:30 pm (UTC)(link)
Кстати, а за такое тоже убивают? :)

$possibly_unititalized ||= 'default_value';

[identity profile] blacklion.livejournal.com 2005-03-14 02:32 pm (UTC)(link)
Нет, IMHO. Это классический паттерн, вроде "*p++ = *q++;" в C. т.е. хакерство, но уже ставшее идиомой языка.