Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Загадочная переменная  (Прочитано 21753 раз)
0 Пользователей и 1 Гость смотрят эту тему.
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« : 15-05-2013 13:08 » 

Для освежения понимания «our» запускаю следующий тестовый скрипт:
Код: (Perl)
#!/usr/bin/perl -W

use 5.010;
use strict;
use warnings;

package X;
our $b = 123;

package Y;
our $b = 456;

package Z;
say '$X::b = ', defined($X::b) ? $X::b : 'undef';
say '$Y::b = ', defined($Y::b) ? $Y::b : 'undef';
say '$Z::b = ', defined($Z::b) ? $Z::b : 'undef';
say '$b = ', defined($b) ? $b : 'undef';

$X::b = 123
$Y::b = 456
$Z::b = undef
$b = 456

Странная переменная «$b»: в пространстве имен Z ее нет. Кто-нибудь понимает, что тут происходит?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 15-05-2013 14:18 » 

Мое первое предположение было, что пространства каскадируются. Но что то, его не удалось пока подтвердить Жаль

Добавлено через 14 минут и 40 секунд:
Вот такой код зароботал адекватно Улыбаюсь
Код: (Perl)

#!/usr/bin/perl -W

use 5.010;
use strict;
use warnings;

{
package X;
our $b = 123;
}

{
package Y;
our $b = 456;
}

package Z;
say '$X::b = ', defined($X::b) ? $X::b : 'undef';
say '$Y::b = ', defined($Y::b) ? $Y::b : 'undef';
say '$Z::b = ', defined($Z::b) ? $Z::b : 'undef',
say '$b = ', defined($b) ? $b : 'undef';
$X::b = 123
$Y::b = 456
$b = undef
$Z::b = undef
« Последнее редактирование: 15-05-2013 14:32 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 16-05-2013 06:12 » 

Получается, что переменная пакета отчасти является и лексической, ограничиваясь в моем случае модулем, а в твоем случае — блоком. Еще хуже выглядит картина, если имеется еще и лексическая (my) переменная пакета с тем же именем, объявленная в модуле: в зависимости от порядка выполнения, это может стать одной переменной или двумя, а объявление второй сопровождается предупреждением и в пакете Z тоже происходит путаница.
На практике такого можно легко избежать, разнося пакеты по отдельным модулям и не применяя одноименных переменных для my и our.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 16-05-2013 08:23 » 

RXL, а ещё язык хвалил Улыбаюсь Мрачный он в синтаксическом плане.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 16-05-2013 09:00 » 

Я не прекращаю его хвалить. Достоинств у него хватает, но, да, в тонкостях сложен. На практике в такие дебри, куда я залезаю, никто не полезет. Просто хочу уточнить свое понимание той или иной фичи.
Кстати, платят за него весьма хорошо. Вот подумываю...

Следующий тест.

В Perl 5.10 появились новые фичи. Например, функция IO::Handle::say, как аналог print, но с завершающим строку терминатором. Для текстового вывода это удобно. Также появился оператор на подобии switch, но совсем другой. Называется given/when.

Код: (Perl)
given (EXPR) {
    when (COND1) { ... }
    when (COND2) { ... }
    when (COND3) { ... }
    default { .... }
}

Как водится в Perl, это не единый оператор, а несколько отдельных, совместно выполняющих некую работу. Оператор given производит действие аналогичное

Код: (Perl)
{
    local $_ = EXPR;
    ...
}

Т.е. является оберткой и может быть заменен на любой другой блок (операторы if/unless/elsif/else блоками не являются!), например на блок for.
Оператор when выполняет контекстное преобразование условия в другое выражение. Внутри блока when оператор continue позволяет завершить текущий блок и начать проверку условий в последующих when. Можно сказать, что виртуально получается нечто вроде:

Код: (Perl)
{
    local $_ = EXPR;
    if (NEW_COND1) { ....; last; }
    if (NEW_COND2) { ....; last; }
    if (NEW_COND3) { ....; last; }
    ....; # default
}

Я новых фич 5.10 еще не использовал, довольствуясь классическим (последние лет 15) 5.6. Решил потренироваться.

И так, простой тестик.

Код: (Perl)
#!/usr/bin/perl -W

use 5.010;
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);

for ('a', 1..5, 'b') {
    print 'Value "', $_,'" is ';
    when (!looks_like_number($_)) { say 'not number' }
    when ($_ & 1) { say 'odd number' }
    when (not ($_ & 1)) { say 'even number' }
    default { say 'unknown' }
}
continue {
    say('Number parity test: ', $_ & 1 ? 'odd' : 'even') if (looks_like_number($_));
}

Value "a" is not number
Value "1" is odd number
Number parity test: odd
Value "2" is even number
Number parity test: even
Value "3" is unknown
Number parity test: odd
Value "4" is even number
Number parity test: even
Value "5" is unknown
Number parity test: odd
Value "b" is not number

Это чо?  Не может быть...
Модифицирую: переношу выражение в функцию.

Код: (Perl)
#!/usr/bin/perl -W

use 5.010;
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);

sub is_odd { $_[0] & 1 }

for ('a', 1..5, 'b') {
    print 'Value "', $_,'" is ';
    when (!looks_like_number($_)) { say 'not number' }
    when (is_odd($_)) { say 'odd number' }
    when (!is_odd($_)) { say 'even number' }
    default { say 'unknown' }
}
continue {
    say('Number parity test: ', is_odd($_) ? 'odd' : 'even') if (looks_like_number($_));
}

Value "a" is not number
Value "1" is odd number
Number parity test: odd
Value "2" is even number
Number parity test: even
Value "3" is odd number
Number parity test: odd
Value "4" is even number
Number parity test: even
Value "5" is odd number
Number parity test: odd
Value "b" is not number

Все путем.

Оператор не является аналогом switch. Нужно изучать. man perlsyn
« Последнее редактирование: 16-05-2013 09:04 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 16-05-2013 09:57 » 

Ага: с when довольно просто: это не простое выражение, а так называемый smart matching.

Цитата
      Most of the time, "when(EXPR)" is treated as an implicit smart match of $_, i.e. "$_ ~~ EXPR". (See "Smart matching in detail" for more
       information on smart matching.) But when EXPR is one of the below exceptional cases, it is used directly as a boolean:
       ·   a subroutine or method call
       ·   a regular expression match, i.e. "/REGEX/" or "$foo =~ /REGEX/", or a negated regular expression match ("!/REGEX/" or "$foo !~
           /REGEX/").
       ·   a comparison such as "$_ < 10" or "$x eq "abc"" (or of course "$_ ~~ $c")
       ·   "defined(...)", "exists(...)", or "eof(...)"
       ·   a negated expression "!(...)" or "not (...)", or a logical exclusive-or "(...) xor (...)".
       ·   a filetest operator, with the exception of "-s", "-M", "-A", and "-C", that return numerical values, not boolean ones.
       ·   the ".." and "..." flip-flop operators.
       In those cases the value of EXPR is used directly as a boolean.

       Furthermore:
       ·   If EXPR is "... && ..." or "... and ...", the test is applied recursively to both arguments. If both arguments pass the test, then
           the argument is treated as boolean.
       ·   If EXPR is "... || ...", "... // ..." or "... or ...", the test is applied recursively to the first argument.
       These rules look complicated, but usually they will do what you want. For example you could write:

           when (/^\d+$/ && $_ < 75) { ... }

       Another useful shortcut is that, if you use a literal array or hash as the argument to "given", it is turned into a reference. So
       "given(@foo)" is the same as "given(\@foo)", for example.


Оператора «~~» раньше тоже не было.

Цитата
      Smart matching in detail

       The behaviour of a smart match depends on what type of thing its arguments are. The behaviour is determined by the following table: the
       first row that applies determines the match behaviour (which is thus mostly determined by the type of the right operand). Note that the
       smart match implicitly dereferences any non-blessed hash or array ref, so the "Hash" and "Array" entries apply in those cases. (For
       blessed references, the "Object" entries apply.)

       Note that the "Matching Code" column is not always an exact rendition.  For example, the smart match operator short-circuits whenever
       possible, but "grep" does not.

           $a      $b        Type of Match Implied    Matching Code
           ======  =====     =====================    =============
           Any     undef     undefined                !defined $a

           Any     Object    invokes ~~ overloading on $object, or dies

           Hash    CodeRef   sub truth for each key[1] !grep { !$b->($_) } keys %$a
           Array   CodeRef   sub truth for each elt[1] !grep { !$b->($_) } @$a
           Any     CodeRef   scalar sub truth          $b->($a)

           Hash    Hash      hash keys identical (every key is found in both hashes)
           Array   Hash      hash slice existence     grep { exists $b->{$_} } @$a
           Regex   Hash      hash key grep            grep /$a/, keys %$b
           undef   Hash      always false (undef can't be a key)
           Any     Hash      hash entry existence     exists $b->{$a}

           Hash    Array     hash slice existence     grep { exists $a->{$_} } @$b
           Array   Array     arrays are comparable[2]
           Regex   Array     array grep               grep /$a/, @$b
           undef   Array     array contains undef     grep !defined, @$b
           Any     Array     match against an array element[3]
                                                      grep $a ~~ $_, @$b

           Hash    Regex     hash key grep            grep /$b/, keys %$a
           Array   Regex     array grep               grep /$b/, @$a
           Any     Regex     pattern match            $a =~ /$b/

           Object  Any       invokes ~~ overloading on $object, or falls back:
           Any     Num       numeric equality         $a == $b
           Num     numish[4] numeric equality         $a == $b
           undef   Any       undefined                !defined($b)
           Any     Any       string equality          $a eq $b

        1 - empty hashes or arrays will match.
        2 - that is, each element smart-matches the element of same index in the
            other array. [3]
        3 - If a circular reference is found, we fall back to referential equality.
        4 - either a real number, or a string that looks like a number


Также он может быть перегружен в пакете, как и любой другой оператор.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 16-05-2013 11:29 » 

RXL, это не тонкости, это кошмар - непредсказуемый код. При этом вся работа строится на глобальных переменных типа $_, которые переиспользуются разными блоками, и за порядком должен следить программист. Да ещё и ссылки от значений отличаются. Ну да, опытных программисту на таком языке мало, платить им приходится много, и вот мне как работодателю это всё зачем? Мне надо, чтобы я обезьяну посадил, и она бы не смогла напортачить, а могла бы за дёшево писать достаточно качественно.

Т.е. какие преимущества языка в плане технологии и экономики процесса разработки?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 16-05-2013 12:56 » 

Переменная $_, подмечу, никому не мешает, хотя она даже суперглобальна (всегда находится в таблице символов main). Она динамическая и, если считаешь, что ее надо сохранить до выхода из текущего блока без изменений, объявляешь ключевым словам local. Также ничто не мешает использовать локальные переменные:

for my $var (....) { .... }

или

for (...) { my $var = $_; ... }

Чем тебе не угодили ссылки? Это очень сложно?

Вопрос обезьян меня пока не интересует.

Если кто-то готов платить за повышенные требования, думаю знает, зачем это делает. У меня тоже возник вопрос, не дешевле ли будет перейти на другую платформу. Ответ был, что уже несколько проектов на Perl сделано и отказываться от него не считают нужным.
« Последнее редактирование: 16-05-2013 13:02 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 02-09-2013 19:28 » 

Сбылась, можно сказать, мечта, работаю теперь perl-программером.
Нарыл новую особенность, нехарактерную для других языков осбенность: блок do {} ведь в Perl не является циклом и операторы last/next/redo в нем не работают, а я по привычке ожидал другого поведения. В среде Catalyst run-time ошибки прозрачно подавляются и потратил пару часов на поиск неисправности, пока не додумался соорудить простой тест. Лоханулся чуток. Улыбаюсь
Зато узнал много нового, интересного. После Perl работать с PHP уже как-то неинтересно стало.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines