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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Узнать существуен ли функция, Узнать существуен ли функция 
:(
    Опции темы
alexey9
  Дата 20.3.2007, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Добрый день.
Подскажите как узнать существует ли функция? В кратце:
Код

#!/usr/bin/perl
use strict;
....

  my $someFuncSuff = "testFunc_01";
  my $callBackFn = "functionCallBack_".$someFuncSuffix; 
  {
    no strict;
    &$callBackFn;
    use strict;
 }
....

Так вот собственно как узнать существует ли сама функция под именем $callBackFn и как ей отдать параметры при таком вызове?
Заранее спасибо.

PM MAIL   Вверх
Nab
Дата 20.3.2007, 13:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Параметр как обычно:
Код

&$callBackFn($my_param);

А наличие никак, только по ошибке при вызове:
Код

eval "&$callBackFn($my_param)";
die $@ if $@;



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


Эксперт
***


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

Репутация: 38
Всего: 40



perldoc UNIVERSAL
PM MAIL ICQ   Вверх
Nab
Дата 20.3.2007, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(arto @  20.3.2007,  13:33 Найти цитируемый пост)
perldoc UNIVERSAL

Ну и причем здесь это?
Где говориться о классах, методах, объектах?


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


Эксперт
***


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

Репутация: 38
Всего: 40



# perl -MUNIVERSAL -de0

main::(-e:1):   0
  DB<1> sub AA () { return 1; }

  DB<2> p main->can ("AA")
CODE(0x8eaaac4)
  DB<3> p main->can ("aa")

  DB<4>

PM MAIL ICQ   Вверх
tishaishii
Дата 20.3.2007, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



smile)
Читай.

Вот вариант:
Код
sub d {print @_}
sub AUTOLOAD {+(&UNIVERSAL::can(bless({}), substr $AUTOLOAD, rindex($AUTOLOAD, '::')+2)||sub{})->(@_)}
print int D(1, 2);


Вариант без доработки:
Код

my$hash=\%{+__PACKAGE__.'::'};
print exists $hash->{d}, "\n";
print $_, "\t", $hash->{$_}, "\n" foreach sort keys %$hash;


А это самый простой и надёжный:
Код
sub d {print @_}
print defined &c;


Добавлено @ 16:16 
В общем виде:
Код
sub abc_sub {print @_}
sub DoItifYouCan {
    my$sub=${(shift || (caller)[0] || __PACKAGE__).'::'}{+shift};
     +defined &$sub ? &$sub(@_) : ()
}
&DoItifYouCan(undef=>'abc_sub', 1..3);


Это сообщение отредактировал(а) tishaishii - 20.3.2007, 16:22
PM MAIL ICQ Skype   Вверх
alexey9
Дата 20.3.2007, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Черт, забыл уточнить, извините. Это все еще и касательно класса. Ну то есть так:
Код

sub new {
  ...
}

sub callFunc {
 my $self = shift;
 my $fnSuffix = shift;

 my $fnPreffix = "callBackFN_";
 my $fullFuncName = $fnPreffix.$fnSuffix;
 &$self->fullFuncName;

}






Это сообщение отредактировал(а) alexey9 - 20.3.2007, 17:24
PM MAIL   Вверх
Nab
Дата 20.3.2007, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Нe блин, alexey9, двойка за постановку вопроса.

ответ: метод can базового класса UNIVERSAL, читайте внимательно документацию...

arto, приношу извинения, тами метод can можно применить не только для неприведенной ссылки. Как побочный еффект того что пакет и класс в Perl практически идентичные понятия, то:
Код

sub dd {1}
print "Ok\n" if UNIVERSAL::can(__PACKAGE__,'dd');

вполне рабочий код, и он хоть и не описан в документации, и может в принципе в будущих версиях оказаться не рабочим, я в этом сильно сомневаюсь, уж слишком это все завязано... и думаю это более удобный вариант чем то что привел, tishaishii. А он в своем репертуаре.... без поллитра не разобраться smile Хоть какието коментарии добавляй, а то тяжело следить за "ходом новаторской мысли" © Ильф и Петров "Двенадцать стульев".


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


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


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

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



Поздравляю, Nab, ты лапух.
UNIVERSAL::can работает гоооорааааздо медленнееееее, чем defined. Проверено 10 раз.
Используй defined и будь в моём репертуаре.
PM MAIL ICQ Skype   Вверх
Nab
Дата 20.3.2007, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(tishaishii @  20.3.2007,  16:04 Найти цитируемый пост)
А это самый простой и надёжный:
Код

sub d {print @_}
print defined &c;

О премудрейший tishaishii, есди бы ты научился свой простейший код писать без ошибок, то тебя понимали бы и лопухи типа меня с полу-слова, или полу-взгляда...

А вообще конечно вариант лучший... smile 





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


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


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

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



Nab, хватит ёрничать. Какие-то ошибки придумал себе ещё. Тут ты уже начинаешь, как автор статьи "Про вред "популярного языка программирования Perl" говорить.

Это сообщение отредактировал(а) tishaishii - 21.3.2007, 21:16
PM MAIL ICQ Skype   Вверх
ElectricalStorm
Дата 22.3.2007, 01:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник Клуба
Сообщений: 547
Регистрация: 22.1.2004

Репутация: нет
Всего: 9



арто - отжег...

это мне напоминает одного парня с хпоинта  smile)))


--------------------
Нужно знать инструмент, которым пользуешься
PM MAIL   Вверх
tishaishii
Дата 22.3.2007, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Ну и шо с тем делать?
Придётся ещё подключать консоль для ввода\вывода. Нафига?
PM MAIL ICQ Skype   Вверх
Ramirez
Дата 2.12.2008, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Извиняюсь за некропостерство, но всетаки мой вопрос относится к этой дискуссии:

а что если у меня есть объект, как узнать есть у него метод или нет (кроме как через UNIVERSAL::CAN)?
Хочется использовать defined а никак не могу найти способа использовать его при проверке наличия метода у объекта.

вот единственное что я придумал, но тут eval, a это ГОРАЗДО медленнее can:

Код

my $obj = new MyClass;
my $method = 'method1';

print 'can' if eval 'defined &'.ref($obj).'::'.$method;




вот такой код:

Код

e strict;
use test;
use Benchmark qw(:all);

our $o = new test;

cmpthese (
    100000,
    {
        'can' => sub { print STDERR 'can' if $o->can('test');           },
        'eval' => sub { print STDERR 'can' if eval 'defined &'.ref($o).'::test';        },
    }
);


выдает вот такой удручающий результат:

Код

         Rate eval  can
eval  56388/s   -- -85%
can  387879/s 588%   --




Это сообщение отредактировал(а) Ramirez - 2.12.2008, 14:24
PM ICQ   Вверх
KSURi
Дата 2.12.2008, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 20
Всего: 27



eval придумали для того, чтобы выполнять строки как код, а can придумали для того, чтобы проверять существование ф-ий/м-ов.
Результат вашего бенчмарка это подтверждает (а значит вовсе он и не удручающий).

А кстати, зачем вам вообще здесь eval?

Это сообщение отредактировал(а) KSURi - 2.12.2008, 17:56


--------------------
Died at Life.pl line 21
PM Jabber   Вверх
Ramirez
Дата 8.12.2008, 21:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



А я не знаю другого способа вызвать метод, который динамически задается в процессе выполнения скрипта.

Но в данном примере я хотел только проверить наличие, и обычно пользовался методом CAN. но сравнив насколько UNIVERSAL::CAN проигрывает методу defined захотелось найти альтернативу. но кроме eval ничего в голову не пришло.

дело в том, что у метода UNIVERSAL::CAN есть одно преимущество: имя метода ему передается в переменной.
PM ICQ   Вверх
KSURi
Дата 8.12.2008, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 20
Всего: 27



Код

$ perl -MBenchmark=cmpthese
package Foo;
sub bar { 'bar' }
package main;
$var = bless {}, 'Foo';
print $var->bar, "\n";
cmpthese(
  1_000_000,
  { defined => sub { defined &{ref $var . '::bar' } },
    eval    => sub { eval 'defined &' . ref($var) . '::bar' },
    can     => sub { $var->can('bar') }, },
);
^D
bar
             Rate    eval defined     can
eval      40917/s      --    -97%    -98%
defined 1492537/s   3548%      --    -31%
can     2173913/s   5213%     46%      --
$



Это сообщение отредактировал(а) KSURi - 8.12.2008, 22:37


--------------------
Died at Life.pl line 21
PM Jabber   Вверх
Ramirez
Дата 9.12.2008, 10:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Результаты интересные.

а вот за эту конструкцию, отдельное спасибо. я так и не смог до нее додуматься:

Код

defined &{ref $var . '::bar' }

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


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

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


 




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


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

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