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: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) на перле :)