Comments 65
Хм. Спасибо за статью.
-3
Позволю себе высказать две мысли.
1) Я понимаю, что присвоения в while и прочих «if»-ах — это общепринятая практика. Но на самом деле этот подход находится в прямом конфликте с концепцией структурного программирования. Присвоение, в данном случае, является side-effect-ом, и использование таких конструкций ни чем ну лучше (и не хуже) использования goto.
2) Perl — такой Perl :-)
В можете написать
open $fh, "/etc/passwd";
print join("", <$fh>);
но вы не можете использовать $fh внутри объекта.
Вот это сработает:
open $fh, "/etc/passwd";
$a->{'file'}=$fh;
А вот это — не сработает:
print join("", <$a->{'file'}>)'
Я очень люблю Perl :-) Могу ещё таких примеров накидать :-)
1) Я понимаю, что присвоения в while и прочих «if»-ах — это общепринятая практика. Но на самом деле этот подход находится в прямом конфликте с концепцией структурного программирования. Присвоение, в данном случае, является side-effect-ом, и использование таких конструкций ни чем ну лучше (и не хуже) использования goto.
2) Perl — такой Perl :-)
В можете написать
open $fh, "/etc/passwd";
print join("", <$fh>);
но вы не можете использовать $fh внутри объекта.
Вот это сработает:
open $fh, "/etc/passwd";
$a->{'file'}=$fh;
А вот это — не сработает:
print join("", <$a->{'file'}>)'
Я очень люблю Perl :-) Могу ещё таких примеров накидать :-)
-1
Возможно, проблема в том, что обращение $a->{file} содержит закрывающую стрелку?
0
Нет. Если написать my %a; $a{'file'} = $fh; … <$a{'file'}>; то тоже не работает.
0
ага! и скобки не помогают :-)
Perl — это просто бразец того, каким не должен быть язык.
Вот ещё пример (из любимого :-)):
Perl — это просто бразец того, каким не должен быть язык.
Вот ещё пример (из любимого :-)):
$ perl -MData::Dumper -e '@a = map { {$_ => $_} } qw/a b/; print Dumper(\@a)' $VAR1 = [ { 'a' => 'a' }, { 'b' => 'b' } ]; $ perl -MData::Dumper -e '@a = map { $x = $_; {$x => $x} } qw/a b/; print Dumper(\@a)' $VAR1 = [ 'a', 'a', 'b', 'b' ];Кто бы мог подумать, что резльтат будет разным! :-)
+1
Хорошее слово: бразец. Надо запомнить! :)
+3
А вот еще загадка из моих любимых (отвечать вслух необязательно): почему не мрет? ;-)
use strict;
$a = $a+1;
use strict;
$a = $a+1;
-1
$ perl -MData::Dumper -e '@a = map { $x = $_; +{$x => $x} } qw/a b/; print Dumper(\@a)'
Есть разница между блоком кода и ссылкой на хеш ;)
+3
Cразу видно человека не разбирающегося в Perl, во втором примере "=>" обозначает запятую, т.е. вы пытаетесь вернуть {} блок кода в котором возвращаются 2 переменные, потому переменные и удваиваются.
Стыдно, товарищ… в любом языке незнание синтаксиса приводит к подобным недопониманиям.
Стыдно, товарищ… в любом языке незнание синтаксиса приводит к подобным недопониманиям.
0
"=>" обозначает запятую…
+2
Да это всё понятно. Я даже не против плюсика перед фигурными скобками. Не против не потому, что считаю это решение хорошим (весь map в Perl реализован как коллекция уродств, кои можно перечислять бесконечно), а потому, что плюсик хоть где-то отражён в документации. В своих комментариях, я не хотел рассказать вам то, что и без того есть в perldoc (я же понимаю, с какими гениальными перловиками я рискую общаться). Я хотел рассказать то, что не описано в документации. То, что можно узнать только почитав исходники и рассуждения самого Лари. Я предлагаю удивиться тому, что точка с запятой перед (!) конструкцией, полностью меняет смысл этой конструкции! Тогда как по документации точка с запятой полностью нейтральна. Вот эти две программы работаю совершенно по-разному :-)
1) @a = map {{$_ => $_} } qw/a b/;
2) @a = map {;{$_ => $_} } qw/a b/;
Где про это сказано в документации? ,-)
1) @a = map {{$_ => $_} } qw/a b/;
2) @a = map {;{$_ => $_} } qw/a b/;
Где про это сказано в документации? ,-)
+1
Ладно, насчёт незнания Perl, я наверное погорячился. Посмотрел Devel::Deparse, в примере явно видно что меняется контекст. На самом деле это не является уродством ни в коей мере, просто все эти микрооптимизации и фишечки — это и есть то самое почему Perl интересный и очень сильный язык программирования и в документации это называется не иначе как «магия» =)
Perl прошёл очень долгий путь от продукта для микроавтоматизаций до уже серьёзного языка на котором можно уже делать всё что угодно, поэтому в нём так много синтаксического сахара и всяких фишек которые не понятны людям со стороны. Какие-то из этих нюансов очень упрощают написание небольших скриптов (тот же «даймонд» — ), какие-то наоборот раскрываются только в крупных проектах (синтаксический сахар Moose), я знаком с Perl уже много лет и ни на одну из грабель (даже наподобие) что вы указали не наступал, про многие такие нюансы знаю, но если быть честными они есть во всех языках. Опять же в С++ есть куча кода в котором «без пузыря не разберёшься», но это не значит что язык уродский и непонятный, мало того в нём же есть примеры которые дают разный результат при одном и том же коде.
Просто если тебе нравиться язык и ты понимаешь что ты делаешь — в разумной мере можно пользоваться этими нюансами, но Perl настолько гибкий, что всё очень просто и лаконично реализуется и нормальными документированными возможностями. А если надо разбирать чужой код есть мощные инструменты для помощи разбора непонятных участков кода (Perl::Tidy, Devel::Deparse).
Не нравиться — не пользуйся, всё просто, но не надо таких громких слов только из-за того что есть недопонимание в концепции языка, либо она каким либо образом не нравиться лично вам.
Perl прошёл очень долгий путь от продукта для микроавтоматизаций до уже серьёзного языка на котором можно уже делать всё что угодно, поэтому в нём так много синтаксического сахара и всяких фишек которые не понятны людям со стороны. Какие-то из этих нюансов очень упрощают написание небольших скриптов (тот же «даймонд» — ), какие-то наоборот раскрываются только в крупных проектах (синтаксический сахар Moose), я знаком с Perl уже много лет и ни на одну из грабель (даже наподобие) что вы указали не наступал, про многие такие нюансы знаю, но если быть честными они есть во всех языках. Опять же в С++ есть куча кода в котором «без пузыря не разберёшься», но это не значит что язык уродский и непонятный, мало того в нём же есть примеры которые дают разный результат при одном и том же коде.
Просто если тебе нравиться язык и ты понимаешь что ты делаешь — в разумной мере можно пользоваться этими нюансами, но Perl настолько гибкий, что всё очень просто и лаконично реализуется и нормальными документированными возможностями. А если надо разбирать чужой код есть мощные инструменты для помощи разбора непонятных участков кода (Perl::Tidy, Devel::Deparse).
Не нравиться — не пользуйся, всё просто, но не надо таких громких слов только из-за того что есть недопонимание в концепции языка, либо она каким либо образом не нравиться лично вам.
+2
Это есть в документации по map + необходимо понимать что такое контексты и как используются (это основное знание языка Perl).
0
Читайте мануалы :) В первом случае перл понимает скобки как ссылку на хеш, во втором — как блок ;)
Правильно будет:
perl -MData::Dumper -e '@a = map { my $x = $_; +{$x => $x} } qw/a b/; print Dumper(\@a)'
Правильно будет:
perl -MData::Dumper -e '@a = map { my $x = $_; +{$x => $x} } qw/a b/; print Dumper(\@a)'
0
про это написано в perldoc.perl.org
У map есть две формы
и
Когда perl встречает {, он не знает, это начало блока или начало ссылки на хэш.
Перл анализирует код после {, если там встречаться хотя бы точка запятой, то перл понимает, что это блок.
Видимо перл, видя код
но делает это он так:
Чтобы второй пример работал как первый поставьте плюс перед {$x => $x}:
Вообщем помогайте перлу явно показывать, что вы хотите вернуть.
У map есть две формы
map <блок> <список>
ии
map <выражение>, список
Когда perl встречает {, он не знает, это начало блока или начало ссылки на хэш.
Перл анализирует код после {, если там встречаться хотя бы точка запятой, то перл понимает, что это блок.
perl -MO=Deparse -MData::Dumper -e "@a = map {{$_ => $_}} qw/a b/; print Dumper(\@a)"
=======================================================
use Data::Dumper;
@a = map({+{$_, $_};} 'a', 'b');
print Dumper(\@a);
-e syntax OK
Видимо перл, видя код
map {{$_ => $_}} <список>
пытается привести его к коду map +{$_ => $_}, <список>
но делает это он так:
map {+{$_ => $_}} <список>
Чтобы второй пример работал как первый поставьте плюс перед {$x => $x}:
perl -MData::Dumper -e "@a = map {$x = $_; +{$x => $x}; } qw/a b/; print Dumper(\@a)"
$VAR1 = [
{
'a' => 'a'
},
{
'b' => 'b'
}
];
Вообщем помогайте перлу явно показывать, что вы хотите вернуть.
0
UFO just landed and posted this here
If what's within the angle brackets is neither a filehandle nor a simple scalar variable containing a filehandle name, typeglob, or typeglob reference, it is interpreted as a filename pattern to be globbed, and either a list of filenames or the next filename in the list is returned, depending on context.
Грубый перевод: Если в угловых скобках не filehandle или не простой скаляр, содержащий filehandle или typeglob или ссылку на typeglob, то содержимое будет проинтерпретировано как паттер который будет развернут в командной строке. Результатом разворачивания будет или список имен файлов или следующий файл в списке(определяется контекстом).
+1
Все верно, работа оператора <> зависит от контекста
когда внутри $переменная то она интерполируется и вызывается чтение
Остальное <$a->{'file'}> уже воспринимается как TYPEGLOB
когда внутри $переменная то она интерполируется и вызывается чтение
Остальное <$a->{'file'}> уже воспринимается как TYPEGLOB
0
Не-а, в данном случае TYPEGLOB не причём :-)
Проблема глубже. Вкратце, дело в том, что все языки разбираются двумя анализаторами: лексическим и синтаксическим. Первый — простой — разбирает текст на слова. Второй — на много сложнее — разбирает последовательность слов на набор вложенных конструкций. Когда Лари начал писать Perl, он честно реализовал только лексический анализатор. Поковырявшись с синтаксическим, он решил, что это зло (не могу найти ссылку на эту эпическую его статью). Он провозгласил, что систематический подход, используемый для построения непротиворечивых языков — это детский сад. А он — Лари — напишет язык без всякого синтаксиса, без BNF нотации, и будет этот язык прекрасен. Сказано — сделано :-) Поэтому в перле есть внутренние противоречия. И это одно из них. Оно возникает до того, как на сцену выходят TYPEGLOBы.
(у 5.10, вроде, всё же сделали BNF нотацию, но я её не видел)
Проблема глубже. Вкратце, дело в том, что все языки разбираются двумя анализаторами: лексическим и синтаксическим. Первый — простой — разбирает текст на слова. Второй — на много сложнее — разбирает последовательность слов на набор вложенных конструкций. Когда Лари начал писать Perl, он честно реализовал только лексический анализатор. Поковырявшись с синтаксическим, он решил, что это зло (не могу найти ссылку на эту эпическую его статью). Он провозгласил, что систематический подход, используемый для построения непротиворечивых языков — это детский сад. А он — Лари — напишет язык без всякого синтаксиса, без BNF нотации, и будет этот язык прекрасен. Сказано — сделано :-) Поэтому в перле есть внутренние противоречия. И это одно из них. Оно возникает до того, как на сцену выходят TYPEGLOBы.
(у 5.10, вроде, всё же сделали BNF нотацию, но я её не видел)
0
Тут достаточно вспомнить, что <> — это шорткат к readline (или к glob в зависимости от параметра) и в сложных случаях писать полностью. Такой код работает:
print join("", readline($a->{'file'}))
0
В Perl всегда есть второе решение… на случай, если первое не работает :-)
0
И это здорово, чёрт подери!!! Никогда не возникает тупиковых позиций. Не понимаешь как сделать одним способом — реализуй другим и будь счастлив!
0
Проблема не в избыточной гибкости, а в том, что Perl делает массу не-очевидных вещей и никак об этом не предупреждает. И без средств типа Devel::Deparse разобраться невозможно. Читать код становится невозможно. Даже свой :-)
Вот ещё примерчик:
$ perl -e 'print 1?$x=1:$x=2;'
$ perl -e 'print (1)?$x=1:$x=2;'
$ perl -e 'print ((1)?$x=1:$x=2);'
$ perl -e 'print (1?$x=1:$x=2);'
Один из вариантов работает не как другие — какой? Можете легко это понять, не запуская и не раздумывая десять минут над четырьмя простенькими строчками? Я — скажу честно — не могу :-)
прочесть белые буквы после отгадывания: если вы не только отгадали, но и поняли, на чём я хочу вас подловить, перечисляя не все варианты расстановки скобок, то (1) я снимаю перед вами шляпу, и (2) могу сказать, где вас с радостью возьмут на работу и оценят ваши таланты примерно в 100К, если интересует :-)
Я избегаю перла там, где надо чтобы работало надёжно и предсказуемо. Мне перл нравится только для «поковыряться на досуге».
Люблю перл за три вещи:
1) В перле прекрасно сделаны мелочи. На пример сортировка — просто учебник, как правильно делать сортировку.
2) В исходниках перла много любопытных комментариев. Не редко попадаются интересные цитаты из книжек, фильмов… Просто интересно почитать :-)
3) Глобально пел сделано без всякой системы. Это жуткое нагромождение заплаток, костылей, подпорок… Грандиозная развалюха! Это впечатляет! Смотришь и думаешь: «ого! как же всё стройно в моих проектах». И тихо радуешься :-)
Вот ещё примерчик:
$ perl -e 'print 1?$x=1:$x=2;'
$ perl -e 'print (1)?$x=1:$x=2;'
$ perl -e 'print ((1)?$x=1:$x=2);'
$ perl -e 'print (1?$x=1:$x=2);'
Один из вариантов работает не как другие — какой? Можете легко это понять, не запуская и не раздумывая десять минут над четырьмя простенькими строчками? Я — скажу честно — не могу :-)
прочесть белые буквы после отгадывания: если вы не только отгадали, но и поняли, на чём я хочу вас подловить, перечисляя не все варианты расстановки скобок, то (1) я снимаю перед вами шляпу, и (2) могу сказать, где вас с радостью возьмут на работу и оценят ваши таланты примерно в 100К, если интересует :-)
Я избегаю перла там, где надо чтобы работало надёжно и предсказуемо. Мне перл нравится только для «поковыряться на досуге».
Люблю перл за три вещи:
1) В перле прекрасно сделаны мелочи. На пример сортировка — просто учебник, как правильно делать сортировку.
2) В исходниках перла много любопытных комментариев. Не редко попадаются интересные цитаты из книжек, фильмов… Просто интересно почитать :-)
3) Глобально пел сделано без всякой системы. Это жуткое нагромождение заплаток, костылей, подпорок… Грандиозная развалюха! Это впечатляет! Смотришь и думаешь: «ого! как же всё стройно в моих проектах». И тихо радуешься :-)
0
Не хотелось бы показаться занудой, но и этот вариант в perldoc'е есть (причём тщательно описан) =) хехе
Для того чтобы всё работало нажёдно и предсказуемого просто надо придерживаться правильного стиля написания программ и это проблема не языка, а программиста, просто у Perl слишком много свобод и у многих людей голова идёт кругом и они начинают лепить что попало (опять же много примеров якобы говнокода, но они в основном высосаны из пальца). А на самом деле в той же документации есть советы по написанию программ и если им придерживаться код будет абсолютно понятен и всегда будет работать так как надо. И там рекомендуют обрамлять выражения в скобочки.
Для того чтобы всё работало нажёдно и предсказуемого просто надо придерживаться правильного стиля написания программ и это проблема не языка, а программиста, просто у Perl слишком много свобод и у многих людей голова идёт кругом и они начинают лепить что попало (опять же много примеров якобы говнокода, но они в основном высосаны из пальца). А на самом деле в той же документации есть советы по написанию программ и если им придерживаться код будет абсолютно понятен и всегда будет работать так как надо. И там рекомендуют обрамлять выражения в скобочки.
0
Интересно сосуществование двух тезисов: «хороший Perl-программист знает все возможности Perl» и «хороший Perl-программист не использует все возможности Perl» :-) Те, кто усматривают в этом противоречие (я — в их числе) — программируют на Python :-)
0
«Хороший Perl-программист знает какие возможности использовать в проектах какого типа», Ларри Уолл говорил: «Простые вещи должны быть простыми, а сложные — возможными». Т.е. для простых небольших скриптов мы используем всю мощь Perl, а для сложных проектов соответстенно вспоминаем все рекомендации по написанию красивого и грамотного кода и пишем хороший код.
Конечно если люди сами не могут разрешить противоречия подобного плана они выбирают другой вариант (в данном случае Python), ваше право. Лично я для себя это противоречие разрешил и очень счастлив этому.
Конечно если люди сами не могут разрешить противоречия подобного плана они выбирают другой вариант (в данном случае Python), ваше право. Лично я для себя это противоречие разрешил и очень счастлив этому.
0
Спасибо за очень интересную дискуссию. Призовая игра специально для вас:
работает (хотя не верно):
perl -e 'map {last, last} ()'
не работает (хотя тоже самое) (компилируется, но слетает в tuntime):
perl -e 'map {last, last} (1)'
все точно также, если добавлять скобок типа такого:
perl -e 'map {{{last, last}}} ()'
но как только появляются ';' начинаются полнейшие чудеса:
вот это работает:
perl -e 'map {;{last, last}} (1)'
это компилится, но слетает в runtime:
perl -e 'map {{last, last};} (1)'
это не компилится — «syntax error»(!!!):
perl -e 'map {{{last, last};}} ()'
хотя, казалось бы, в чём тут синтаксическая неверность, если считать, что прошлые примеры верны?.. ,-)
Можете самостоятельно поиграться с return — он тоже работает не в любых блоках.
А сколько радости могут могут доставить примеры из серии:
perl -e 'map {{last => 0}} (1)'
vs
perl -e 'map {{last, 0}} (1)'
…
О!.. я обожаю Perl :-)
работает (хотя не верно):
perl -e 'map {last, last} ()'
не работает (хотя тоже самое) (компилируется, но слетает в tuntime):
perl -e 'map {last, last} (1)'
все точно также, если добавлять скобок типа такого:
perl -e 'map {{{last, last}}} ()'
но как только появляются ';' начинаются полнейшие чудеса:
вот это работает:
perl -e 'map {;{last, last}} (1)'
это компилится, но слетает в runtime:
perl -e 'map {{last, last};} (1)'
это не компилится — «syntax error»(!!!):
perl -e 'map {{{last, last};}} ()'
хотя, казалось бы, в чём тут синтаксическая неверность, если считать, что прошлые примеры верны?.. ,-)
Можете самостоятельно поиграться с return — он тоже работает не в любых блоках.
А сколько радости могут могут доставить примеры из серии:
perl -e 'map {{last => 0}} (1)'
vs
perl -e 'map {{last, 0}} (1)'
…
О!.. я обожаю Perl :-)
0
Наверное стоит Perl обновить, у меня 5.10.1 часть примеров тихо выполнились, а те что с ошибками написали Can't «Last» outside a loop block at -e line 1
Эти примеры вообще нереально увидеть вживую, т.к. last должна использоваться только в циклах, а map циклом не является.
Я не вижу проблем в том что код который и не должен работать не работает.
Эти примеры вообще нереально увидеть вживую, т.к. last должна использоваться только в циклах, а map циклом не является.
Я не вижу проблем в том что код который и не должен работать не работает.
0
Ну я снимаю шляпу! Вы меня раскусили!
Последнее время я забросил перл и как раз мои знания остановились на 5.8, а 5.10, мне кажется, должны были очень сильно доработать в вопросах парсинга и диагностики. Вы подтвердили мои подозрения :-)
Последнее время я забросил перл и как раз мои знания остановились на 5.8, а 5.10, мне кажется, должны были очень сильно доработать в вопросах парсинга и диагностики. Вы подтвердили мои подозрения :-)
0
Кстати, last не должна использоваться только в циклах. Даже родная документация говорит об использовании last для выхода из блока
perl -e '{print 1; last if (1); print 2}'
perl -e '{print 1; last if (0); print 2}'
я не могу удержаться, понимаю, что мелочно это, но почитайте документацию на перл — вы не дочитали два слова:
«last» cannot be used to exit a block which returns a value such as «eval {}», «sub {}» or «do {}», and should not be used to exit a grep() or map() operation.
стыдно товарищ!? © :-)))
perl -e '{print 1; last if (1); print 2}'
perl -e '{print 1; last if (0); print 2}'
я не могу удержаться, понимаю, что мелочно это, но почитайте документацию на перл — вы не дочитали два слова:
«last» cannot be used to exit a block which returns a value such as «eval {}», «sub {}» or «do {}», and should not be used to exit a grep() or map() operation.
стыдно товарищ!? © :-)))
0
Что-то я не пойму где вы шутите %)
Если что, то для меня все примеры понятны :)
Поигравшись с last (кстати next ведет себя так же в ваших примерах и коментариях ниже) сообразил для себя прикольный финт ушами :)
if (1) {{
print 1;
next if 1;
print 2;
}};
Мне всегда не хватало такой конструкции )))
Если что, то для меня все примеры понятны :)
Поигравшись с last (кстати next ведет себя так же в ваших примерах и коментариях ниже) сообразил для себя прикольный финт ушами :)
if (1) {{
print 1;
next if 1;
print 2;
}};
Мне всегда не хватало такой конструкции )))
0
Вот еще:
perl -MData::Dumper -e 'warn Dumper [map {$_ if $_ == 4} 1..10];'
Без интерпретатора не так просто угадать результат )))
Из той же оперы:
sub some {return 'A' if 0} что вернет?
Или еще из прекрасного )))
sub some {return}
warn Dumper {
some => some,
some => some,
};
warn Dumper {
some, some,
some, some,
};
Продолжать можно долго )))))
perl -MData::Dumper -e 'warn Dumper [map {$_ if $_ == 4} 1..10];'
Без интерпретатора не так просто угадать результат )))
Из той же оперы:
sub some {return 'A' if 0} что вернет?
Или еще из прекрасного )))
sub some {return}
warn Dumper {
some => some,
some => some,
};
warn Dumper {
some, some,
some, some,
};
Продолжать можно долго )))))
0
Не перестаю удивляться!
$ perl -MO=Deparse -e 'map {$_ if $_ == 4} 1..10'
map {$_ if $_ == 4;} 1..10;
-e syntax OK
$ perl -MO=Deparse,-p -e 'map {$_ if $_ == 4} 1..10'
map({(($_ == 4) and $_);} (1..10));
-e syntax OK
сюрприз!?
$ perl -MO=Deparse -e 'map {$_ if $_ == 4} 1..10'
map {$_ if $_ == 4;} 1..10;
-e syntax OK
$ perl -MO=Deparse,-p -e 'map {$_ if $_ == 4} 1..10'
map({(($_ == 4) and $_);} (1..10));
-e syntax OK
сюрприз!?
0
Ну как сказать :)
TMTOWTDI во всей красе ))
Второй вариант кстати проще к понимаю что происходит. Конечно при условии, что знаешь, что не истинное логическое выражение возвращает пустую строку, а истинное единицу )))
Я не люблю строить такие логические цепочки. Хотя вру. Люблю, но только с || или or ))) Они как-то понятнее смотрятся ) Да и применение находят чаще )
TMTOWTDI во всей красе ))
Второй вариант кстати проще к понимаю что происходит. Конечно при условии, что знаешь, что не истинное логическое выражение возвращает пустую строку, а истинное единицу )))
Я не люблю строить такие логические цепочки. Хотя вру. Люблю, но только с || или or ))) Они как-то понятнее смотрятся ) Да и применение находят чаще )
0
Так не понятно, что же происходит на самом деле! :-) Perl превращает if в and?
Я всегда думал, что программа должна парситься однозначно (пусть непредсказемо для программиста, но хотя бы однозначно для самого перла), а тут… просто не слов! Perl не раскрывает своих загадок никогда :-)
Похоже, что в этом случае действильно есть неоднозначность. Обычно интерпретация одинакова (независимо от того, просим мы показывать скобки или нет):
Я всегда думал, что программа должна парситься однозначно (пусть непредсказемо для программиста, но хотя бы однозначно для самого перла), а тут… просто не слов! Perl не раскрывает своих загадок никогда :-)
Похоже, что в этом случае действильно есть неоднозначность. Обычно интерпретация одинакова (независимо от того, просим мы показывать скобки или нет):
~$ perl -MO=Deparse, -e 'map {if ($_ == 4) {$_}} 1..10' map {if ($_ == 4) { $_; }} 1..10; -e syntax OK ~$ perl -MO=Deparse,-p -e 'map {if ($_ == 4) {$_}} 1..10' map({if (($_ == 4)) { $_; }} (1..10)); -e syntax OK
0
Я был уверен, что Perl все условия раскрывает как тернарный оператор. ))
Я не экспериментировал с депарсом. Но что-то мне теперь подсказывает, что постфиксные условия Deparse раскрывает через логические операторы ))
Я and гарантированно использую в одном случае, когда не хочется отдельно объявлять переменную, а в одну строчку нельзя.
Писать
my $var = 'some' if $a == $b;
не есть правильно.
Я пишу
my $var = $a == $b && 'some'; # and писать нельзя! ))
Конечно при условии, что тут не получится откровенной фигни )))
Что-то мне подсказывает, что Perl поступил бы примерно так же ))
А вообще да, тут есть неоднозначность. Вернее сказать, неоднозначность для неопытного программиста )) Думаю большинство предположат, что мап сформирует список из одного элемента. Здесь же мап, в случаях, когда $_ != 4, вставит пустую строку, т.к. пустая строка есть последнее вычисленное значение внутри блока.
Хрупкий, хрупкий мир.
Я не экспериментировал с депарсом. Но что-то мне теперь подсказывает, что постфиксные условия Deparse раскрывает через логические операторы ))
Я and гарантированно использую в одном случае, когда не хочется отдельно объявлять переменную, а в одну строчку нельзя.
Писать
my $var = 'some' if $a == $b;
не есть правильно.
Я пишу
my $var = $a == $b && 'some'; # and писать нельзя! ))
Конечно при условии, что тут не получится откровенной фигни )))
Что-то мне подсказывает, что Perl поступил бы примерно так же ))
А вообще да, тут есть неоднозначность. Вернее сказать, неоднозначность для неопытного программиста )) Думаю большинство предположат, что мап сформирует список из одного элемента. Здесь же мап, в случаях, когда $_ != 4, вставит пустую строку, т.к. пустая строка есть последнее вычисленное значение внутри блока.
Хрупкий, хрупкий мир.
0
спасибо, я наблюдал такое же поведение во многих своих проектах, меня это смущало, но затем я решил что миру довольно много придётся усмехаться над многообразием командного оператора, который так и не научился ценить человеческую жизнь забывая напрочь о приделах разумной логики и здравого смысла.
Мне помогло обрести понимание в данном вопросе.
Мне помогло обрести понимание в данном вопросе.
0
К.О.?
-4
Только если заранее знаешь об этом. Для меня в своё время обнаружение сей неприметной особенности было откровением.
0
Если память не изменяет, то в perl cookbook это подробно расписано
0
В ламабуке — точно))) И там ещё ЕМНИП написано что <> пишется в $_ только внутри условия while)))
0
Ну встречал я людей которые учили perl интуитивно и всяческие ламабуки не читали… А зачем? Зато потом сильно удивляются когда встречают всякие «недокументированные» особенности языка. :(
Никто не говорит, что perl лёгкий язык, но и не такой уж запутанный каким некоторые граждане пытаются его представить. Хотя… Те кто сначала «учит» php, а затем садиться за perl он может показаться нагромождением непонятностей :(
Лично мне pel, несмотря ни на что, нравится. :)
Никто не говорит, что perl лёгкий язык, но и не такой уж запутанный каким некоторые граждане пытаются его представить. Хотя… Те кто сначала «учит» php, а затем садиться за perl он может показаться нагромождением непонятностей :(
Лично мне pel, несмотря ни на что, нравится. :)
0
Дык стоп, кто говорит про недокументированные особенности? Всё прекрасно документировано, были б глаза прочитать. Перл очень прост и изящен, а главное — выразителен. Просто он находится в несколько другой нише, нежели большинство остальных языков. К нему надо привыкнуть. Прочувствовать его внутреннюю структуру. Тогда будет интуитовно понятно, почему ваша конструкция работает именно так, а не как вы хотели бы чтоб она работала)))
+2
для чтения строки лучше использовать
my $line = readline($fh)
my $line = readline($fh)
-1
А что тут загадочного? Прочитайте любой мануал по работе условных конструкций.
0
Я реально напарывался на подобную ситуацию, когда итерации идут по результату запроса к базе данных:
Здесь всё хорошо, потому что в
А когда в результате оказывается 0 (а он, как назло, почему-то не встретился в тестах, а встретился только в продакшне), тут и начинаются интересности.
while(my $ref = $sth->fetchrow_hashref()) {
}
Здесь всё хорошо, потому что в
$ref
— хэш. А потом делаешь запрос в одну колонку и думаешь, зачем тебе хэш, когда можно просто в строку читать? Ага:while(my $str = $sth->fetchrow()) {
}
А когда в результате оказывается 0 (а он, как назло, почему-то не встретился в тестах, а встретился только в продакшне), тут и начинаются интересности.
0
Ну уж это результат грубого нечтения документации. Вот с map пример очень хороший…
0
заключай $str в скобки:
while(my ($str) = $sth->fetchrow()) {
}
тогда таких проблем не будет. Будет списочный контекст.
while(my ($str) = $sth->fetchrow()) {
}
тогда таких проблем не будет. Будет списочный контекст.
+1
Легко понять, что делает перл с помощью модуля B::Deparse
perl -MO=Deparse -e 'while ($line = <STDIN>) {}'
---------------------------------------------------------------------------------
while (defined($line = <STDIN>)) {
();
}
+1
Sign up to leave a comment.
Этот загадочный while…