Thursday, August 20, 2009

Perl: прототипы встроенных функций

Функция sprintf при передаче ей массива в качестве аргумента ведет себя не так, как printf:
sub test1 { printf @_        }
sub test2 { print sprintf @_ }

test1 "%s", "ok"; # prints "ok"
test2 "%s", "ok"; # prints "2"

Всё потому, что sprintf в отличие от printf имеет прототип $@:
perl -le 'print "$_ - ".prototype $_ for ("CORE::sprintf", "CORE::printf")'
CORE::sprintf - $@
CORE::printf -


Соответственно, свой первый аргумент sprintf использует в скалярном контексте. Эта особенность упоминается в perldoc:

Unlike printf, sprintf does not do what you probably mean when you pass it an array as your first argument. The array is given scalar context, and instead of using the 0th element of the array as the format, Perl will use the count of elements in the array as the format, which is almost never useful.


Как вариант, вторую функцию можно переписать так:
sub test2 { print sprintf shift, @_ }

No comments:

Post a Comment