Существует разница между самым быстрым и лучшим способом вызова кода в Perl.
Редактировать: см. Также ответ simbabques. Особенно он учитывает различия между # 1 и №3 и почему вы также должны использовать их.
# 1, # 3: вызовы функций
Ваши # 1 и # 3 идентичны: подпрограмма имеет уникальное имя в глобально видимом пространстве имен. Многие имена могут отображаться в одной подпрограмме через псевдонимы или импортировать модуль.
Если имя функции, которую вы вызываете, известно во время компиляции, суб будет разрешено во время компиляции. Это предполагает, что вы не спонтанно не переопределяете свои функции. Если точная функция известна только во время выполнения, это только хэш-поиск.
Существует три способа вызова функций:
foo(@args);
&foo(@args);
@_ = @args; goto &foo;
Номер один (скобки иногда необязательные) является значением по умолчанию и проверяет ваши аргументы против подпротопа (не используйте прототипы). Также создается целый стек стека вызовов (с большой полезной информацией отладки). Это требует времени.
Номер два пропускает проверку protoype и предполагает, что вы знаете, что делаете. Это немного быстрее. Я думаю, что это неряшливый стиль.
Number three is a tail call. This returns from the current sub with the return value of foo
. This is fast, as prototypes are ignored, and the current call stack frame can be reused. This isn't useful very often, and has ugly syntax. Inlining the code is about an order of magnitude faster (i.e. in Perl, we prefer loops over recursion ☹).
# 2: вызов метода
Гибкость OO достигает высокой производительности: поскольку тип объекта, которому вы вызываете сообщение, никогда не известен до времени выполнения, фактический метод может быть разрешен только во время выполнения.
This means that $foo->bar()
looks up the function bar
in the package that $foo
was bless
ed into. If it can't be found there, it will be searched for in parent classes. This is slow. If you want to use OO, pay attention to shallow hierarchies (→ less lookups). Do also note that Perls default Method Resolution Order is unusual.
Обычно вы не можете вызвать вызов метода для вызова функции, даже если вы знаете тип.
Если $ foo
, если из класса Foo
, а Foo :: bar
является sub, то Foo :: bar ($ foo)
пропустит результат метода и может даже работать. Однако это прерывает инкапсуляцию и будет ломаться один раз, когда Foo
подклассы. Кроме того, это не работает, если Foo
не определяет bar
, но метод был определен в родительском классе.
Я вообще поддерживаю объектную ориентацию, пока из тестов не станет ясно, что это не обеспечит требуемую производительность.