Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Анонимные функции и прототипы


Автор: Logo 17.7.2009, 12:07
Можно ли использовать прототипы с аноноимнными функциями? С одной стороны, записать анонимную функцию с прототипом дозволяется, с другой - как сделать так, чтобы он работал я так и не понял.

Автор: arto 19.7.2009, 10:41
пример?

Автор: Logo 19.7.2009, 11:35
Код

#!/usr/bin/perl

$fnc = sub ($$) {print @_};

&$fnc(1,2,3); #не происходит ошибки, выводит 123
$fnc->(1,2,3); #так тоже
*fnc = $fnc;
fnc(1,2,3);  #и так не помогает

Вот пример. Как ни пробую, прототип анонимной функции не работает, хотя компилятором принимается.

Автор: arto 19.7.2009, 16:10
проверка прототипов происходит во время компиляции.

Автор: Logo 19.7.2009, 16:53
А зачем тогда разрешается указывать прототипы в анонимных функциях?
Кстате так тоже не работает
Код

#!/usr/bin/perl

BEGIN {
$fnc = sub ($$) {print @_};
}
&$fnc(1,2,3); #не происходит ошибки, выводит 123
$fnc->(1,2,3); #так тоже
*fnc = $fnc;
fnc(1,2,3);  #и так не помогает

Автор: sir_nuf_nuf 20.7.2009, 09:32
прототип привязан к имени функции. Т.е. проверка и преобразование агрументов к прототипу происходит на этапе лексического анализа.. (это хак если желаете).

А для анонимных функции просто не стали запрещать, возможно в будущем реализуют.

Вообщем прототипы - довольно редко бывают необходимы.

Автор: Logo 21.7.2009, 05:00
Жаль :(

Автор: sir_nuf_nuf 21.7.2009, 13:31
Logo, чего вам жаль ?
прототипы - это НЕ средство типизации. Перлу они не нужны (по задумке =))
прототипы полезны когда вы хотите дописать функционал на уровне близком к синтаксическому анализу..
т.е. расширить язык. 

Например, вы хотите передавать массив по ссылке, но что бы для пользователя это было красиво (как в push/pop), или хотите передавать ссылку на процедуру, но что бы пользователь писал ее просто как блок кода. Вот тут то и нужны прототипы.

Код

sub do_push (\@;@) {
  my ($ar, @stuff) = @_;
  push @$ar, @stuff;
  return scalar @stuff;
}
do_push @a, @b;  #заметьте @a, а не \@a


См.. Error.pm

Автор: Logo 22.7.2009, 23:11
Вообще-то прототипы предназначены для того, чтобы передавать аргументы как в нормальных языках программирования, т.е. обязательные/необязательные параметры, функция сама знает, взять ей аргумент по ссылке или по значению.

Автор: sir_nuf_nuf 23.7.2009, 10:09
Logo, 
Цитата(Logo @  22.7.2009,  23:11 Найти цитируемый пост)
как в нормальных языках 
 .. это наезд на perl ?  smile 

Цитата(Logo @  22.7.2009,  23:11 Найти цитируемый пост)
функция сама знает, взять ей аргумент по ссылке или по значению. 

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

Обязательные /  необязательные.. опять таки - это того нет по задумке в перле. Все - необязательные.

Автор: Logo 24.7.2009, 13:43
Цитата

Обязательные /  необязательные.. опять таки - это того нет по задумке в перле. Все - необязательные.


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

Цитата

Прототипы только меняю способ синтаксиси передачи параметров.

Ну да, было бы удобно и привычно написать переменную массива, а функция уже сама взяла ссылку, как в остальных языках.

Самое обидное же, что хотя прототипы  в анонимных функциях не работают, их там почему-то можно записать, что оставляет ощущение недоделанности языка.

Автор: sir_nuf_nuf 24.7.2009, 15:52
Цитата(Logo @  24.7.2009,  13:43 Найти цитируемый пост)
Если какие-то параметры не используются
 их надо удалить (см. Фаулер, Рефакторинг). =)


Цитата(Logo @  24.7.2009,  13:43 Найти цитируемый пост)
Ну да, было бы удобно и привычно написать переменную массива, а функция уже сама взяла ссылку, как в остальных языках.

Не заблуждайтесь.. Код самой функции (как текст, так и то, во что оно скомпилируется) не зависит от прототипов самой функции.  От прототипов функции зависит код того, кто ее вызывает.


Цитата(Logo @  24.7.2009,  13:43 Найти цитируемый пост)
оставляет ощущение недоделанности языка. 

 smile У меня perl зачастую вызывает ощущение переделанности =)

А еще в нем можно писать так
Код

my SomeClass $object = SomeClass->new(...);

нафиг надо - тоже не ясно..

Автор: Logo 24.7.2009, 19:24
Цитата(sir_nuf_nuf @  24.7.2009,  15:52 Найти цитируемый пост)
Если какие-то параметры не используются
 их надо удалить (см. Фаулер, Рефакторинг). =)


Но без прототипов perl не скажет о том, что функция принимает параметры, которые все равно не используются.


Цитата

Не заблуждайтесь.. Код самой функции (как текст, так и то, во что оно скомпилируется) не зависит от прототипов самой функции.  От прототипов функции зависит код того, кто ее вызывает.


Ну да - при вызове не надо к примеру писать \ перед переменной - то что функция берет его по ссылке известно из ее обявления, как во всех остальных языках.

Цитата

 У меня perl зачастую вызывает ощущение переделанности =)

А еще в нем можно писать так
Выделить всёкод Perl
1:
    
my SomeClass $object = SomeClass->new(...);

нафиг надо - тоже не ясно.. 


Я включение возможности, которая не работает (сабж), иначе как недоработку не вижу.

Автор: mvsgt 27.7.2009, 11:36
Мой опыт показал, что от прототипов много проблем. Гораздо продуктивней использовать модули - валидаторы, например MooseX::Params::Validate или Params::Validate . Это менее производительно, но во многих отношениях лучше, так как происходит использование функций в более явном виде и без странных преобразований.

Автор: sir_nuf_nuf 27.7.2009, 11:52
mvsgt, +1 - я же и говорю - прототипы не для бизнес логики, а для расширений языка.

Кстати, я думаю, что при проектировании программ нужно учитывать идеологию языка.
То что в перле слабая типизация - намекает на то, что не нужно писать процедуры сильно завязанные на типы. Нужно писать такие которые работают с _простыми_ данными. Вообще стараться
избегать сложных абстракций.

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

Ну к примеру.. функция которая собирает url из частей.
можно написать так:
Код

sub make_http_url ($$;\@$$) {my ($host, $path, $params, $port, $anchor) = @_; bla bla bla}

и тогда программер пока не выучит как ее вызывать каждый раз будет смотреть документацию.. а еще скорее - код, потому, что прототип ($$;\@$$) ничего не говорит ему. Почему это порт идет после параметров запроса ? а потому что юзается редко и что бы не писать каждый раз undef..


Можно так:
Код

=pod
usage: make_http_url(host => 'host', port => 'port', ...)
=cut
sub make_http_url {my %data = @_; return "$data{host}" . bla bla bla}

передача через хеш - запоминается быстрее. А если прогер затупил и забыл передать путь - это он узнает через die.

Если количество параметров становится громадным или его сложно описать в одной строчке - нужно создавать классы.  При таком подходе программеру будет просто неудобно использовать код неправильно.

Автор: mvsgt 27.7.2009, 14:49
Теперь у меня функции оформляются так:


Код


use Moose;
use My::Types;
use MooseX::Params::Validate;


sub getPortByLocode {
    my $self = shift;
    my ( $pointdate, $port ) = validated_list(
        \@_,
        pointdate => { isa => 'Timestamp_Type', optional => 1, default => time() },
        port         => { isa => 'LOCODE_Type', optional => 1, },
    );
... 

$self->getPortByLocode(pointdate =>time(), port=>'123456' );


или так

Код

sub getPortByLocode {
    my $self = shift;
    my ( $pointdate, $port ) = pos_validated_list(
        \@_,
        { isa => 'Timestamp_Type', optional => 1, default => time() },
        { isa => 'LOCODE_Type', optional => 1, },
    );

$self->getPortByLocode(time(), '123456' );



Так как каждый параметр имеет тип, во втором случае можно контролировать и типы, хотя учитывая coerce в Moose это тоже не очень надёжно. Но в большинстве случаев работает.

Автор: Logo 27.7.2009, 15:41
Возможно, так и удобнее, просто пока непривычно.
Но прогу свою я все же на пхп стал писать, достали бесконечные баги.

Автор: sir_nuf_nuf 27.7.2009, 16:00
баги перла ? ну - ну =)

Автор: sir_nuf_nuf 27.7.2009, 16:29
баги перла ? ну - ну =)

Автор: Logo 27.7.2009, 17:27
Ну да=)

Автор: Logo 27.7.2009, 22:39
Вобще мне концепция и многие фитчи Perl очень нравятся, но когда попробовал написать на нем программу для практической задачи, сразу наткнулся на множество непоняток. Для начала в поворачивать картинки на дробный угол GD отказывается http://forum.vingrad.ru/forum/topic-265977.html, причем аналогичная библиотека PHP делает это спокойно. Ладно, берем ImageMagick. Так он отказывается читать файлы  с путями, в которых есть русские буквы. Пришлось открывать файл через open и дескриптор ему уже передавать. Прототипы опять же эти для анонимных функций, вроде они есть, но оказывается не работают. Когда же интерпретатор стал вылетать на одной строке без каких бы то нибыло сообщений об ошибке, мое терпение лопнуло.
Код

  print "--ok"; #здесь ок
  $image->Read(file=>\*InpFile);
  print "--here"; #здесь уже мертвы


Вобщем язык сыроват.

Автор: shamber 27.7.2009, 22:49
Цитата(Logo @  27.7.2009,  22:39 Найти цитируемый пост)
Вобщем язык сыроват. 

пошел плакать

Автор: Logo 29.7.2009, 19:58
Кстате, любопытно что прототип через функцию prototype он видит
Код

#!/usr/bin/perl
$fnc = sub ($$$) {print @_};
print prototype \&$fnc;

Автор: sir_nuf_nuf 30.7.2009, 00:30
Logo, ничего любопытного.. Прототип скорее всего хранится вместе с самой функцией (дерево PP - кодов), а функция prototype обращается к нему..


Цитата(Logo @  27.7.2009,  22:39 Найти цитируемый пост)

Вобщем язык сыроват. 

Не хочу вас переубеждать - дело ваше. Учтите, что перл - это первый язык в своем классе. Python, PHP, Ruby, Lua (?) появились позже, и учитывали опыт перл. Поэтому: 
а) перле много унаследованного, что не могут выкинуть из соображений совместимости
б) перл СТАБИЛЕН. Те баги которые вы привели - это баги не перла, а библиотек.. ну что поделаешь - есть хорошие, а есть и плохие. Это скорее минус перла..
в) В перле (таков уж стиль авторов) мног вещей которые сделаны на будущее. Т.е. то на что компилятор не ругается, но что пока не имеет эффекта. Это НЕ баги. Такие фичи (как и прототипы анонимок) либо не указывают в документации, либо пишут, что это на будущее.

Понимаете какая ситуация - вы началиизучать язык - на глаза вам попалась какая-то фича (которую никто и не использует на практике), которая показалась вам важной, но плохо реализованной - из за этого заключение о всем языке.. 

Автор: Logo 4.8.2009, 16:35
Согласен, разве что за исключением пункта в).

Добавлено через 3 минуты и 35 секунд
Но все равно обидно, что вот по крайней мере обработка изображений так глючит. Идеального инструмента не существует выходит. Ждем перл 6. А пока перл буду попробовать применять в других вещах, когда будет потребность.

Автор: sir_nuf_nuf 5.8.2009, 15:53
Цитата(Logo @  4.8.2009,  16:35 Найти цитируемый пост)
Идеального инструмента не существует выходит.

bingo!

И чем дольше работаешь - тем больше понимаешь, что это общее свойство всего..

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)