Почему назначение переменной Perl foreach изменяет ценности во множестве?

Хорошо, у меня есть следующий кодекс:

use strict;
my @ar = (1, 2, 3);
foreach my $a (@ar)
{
  $a = $a + 1;
}

print join ", ", @ar;

и продукция?

2, 3, 4

Какого черта? Почему это делает это? Это будет всегда происходить? $a не действительно местная переменная? Что, где они взгляды?

18
задан brian d foy 13 January 2010 в 22:52
поделиться

6 ответов

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

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

25
ответ дан 30 November 2019 в 05:57
поделиться

Ваш $ a просто используется в качестве псевдонима для каждого элемента списка, когда вы зацикливаете на нем. Это используется на месте $ _. Вы можете сказать, что $ a не является локальной переменной, потому что она объявляется вне блока.

Более очевидно, зачем присвоение $ a Обращает содержимое списка, если вы думаете об этом как в том, чтобы быть в том, чтобы быть в том, чтобы быть в использовании за $ _ (что это такое). Фактически, $ _ не существует, если вы определяете свой собственный итератор такой.

foreach my $a (1..10)
    print $_; # error
}

Если вам интересно, какова точка зрения, рассмотрите дело:

my @row = (1..10);
my @col = (1..10);

foreach (@row){
    print $_;
    foreach(@col){
        print $_;
    }
}

В этом случае он более читабелен для предоставления имени товарищества за $ _

foreach my $x (@row){
    print $x;
    foreach my $y (@col){
        print $y;
    }
}
0
ответ дан 30 November 2019 в 05:57
поделиться

важное различие здесь заключается в том, что когда вы объявляете мою переменную в разделе инициализации цикла для , кажется, что она имеет некоторые свойства как местных жителей, так и лексических (кто-то, кто больше знает о внутреннем устройстве, хочет прояснить? )

my @src = 1 .. 10;

for my $x (@src) {
    # $x is an alias to elements of @src
}

for (@src) {
    my $x = $_;
    # $_ is an alias but $x is not an alias
}

интересным побочным эффектом этого является то, что в первом случае sub{}, определенный внутри цикла for, является замыкание вокруг любого элемента списка $x, к которому был применен псевдоним. зная это, можно (хотя и немного странно) замыкаться вокруг значения псевдонима, которое может быть даже глобальным, что я не думаю, что возможно с любой другой конструкцией.

our @global = 1 .. 10;
my @subs;
for my $x (@global) { 
    push @subs, sub {++$x}
}

$subs[5](); # modifies the @global array
3
ответ дан 30 November 2019 в 05:57
поделиться

Если у вас где-то есть NSNull, вы, вероятно, используете синтаксический анализатор JSON или CoreData. Когда число в CoreData не установлено, CoreData возвращает NSNull - возможно, то же самое относится и к значениям NSstring в CoreData.

Аналогично, можно получить пустые элементы в JSON, возвращенные с сервера, и некоторые синтаксические анализаторы выдадут их как объект NSNull. Так что в обоих случаях, вы должны быть осторожны, когда вы используете значения, так как то, что вы думали было NSString или NSNumber объект действительно NSNull.

Одним из решений является определение категории в NSNull, которая просто игнорирует все непознанные сообщения, отправленные объекту, в соответствии с кодом ниже. Тогда ваш код будет работать, потому что NSNull.length возвращает 0. Можно включить что-то подобное в файл .pch проекта, который будет включен в каждый файл проекта.

// NSNull+IgnoreMessages.h
@interface NSNull(IgnoreMessages) 
- (void)forwardInvocation:(NSInvocation *)anInvocation;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
@end

//NSNull+IgnoreMessages.m
#import "NSNull+IgnoreMessages.h"
@implementation NSNull(IgnoreMessages)
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ( [self respondsToSelector:[anInvocation selector]] )
      [anInvocation invokeWithTarget:self];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature *sig=[[NSNull class] instanceMethodSignatureForSelector:aSelector];
        // Just return some meaningless signature
    if(sig==nil)
      sig=[NSMethodSignature signatureWithObjCTypes:"@^v^c"];

    return sig;
}
@end
-121--2249361-

Один из недостатков функции ver состоит в том, что она сообщает только то, что установлено , а не то, что имеет доступную лицензию . Можно установить панель инструментов и не иметь лицензии на ее использование (или все доступные лицензии могут быть извлечены другими пользователями). Лучшим выбором является функция license , которая (как вы указали) требует уникального «feature последовательности» для каждой панели инструментов.

Вот более старый список последовательностей функций для различных панелей инструментов, взятых из ныне не существующего потока групп новостей (ссылка теперь мертва):

featureStr = {'Aerospace_Blockset'; ...
              'Aerospace_Toolbox'; ...
              'Bioinformatics_Toolbox'; ...
              'Communication_Blocks'; ...
              'Communication_Toolbox'; ...
              'Compiler'; ...
              'Control_Toolbox'; ...
              'Curve_Fitting_Toolbox'; ...
              'Data_Acq_Toolbox'; ...
              'Database_Toolbox'; ...
              'Datafeed_Toolbox'; ...
              'Dial_and_Gauge_Blocks'; ...
              'Distrib_Computing_Toolbox'; ...
              'Econometrics_Toolbox'; ...
              'EDA_Simulator_Link_DS'; ...
              'Embedded_Target_c166'; ...
              'Embedded_Target_c2000'; ...
              'Embedded_Target_c6000'; ...
              'Embedded_Target_MPC555'; ...
              'Excel_Link'; ...
              'Filter_Design_HDL_Coder'; ...
              'Filter_Design_Toolbox'; ...
              'Fin_Derivatives_Toolbox'; ...
              'Financial_Toolbox'; ...
              'Fixed_Income_Toolbox'; ...
              'Fixed_Point_Toolbox'; ...
              'Fixed-Point_Blocks'; ...
              'Fuzzy_Toolbox'; ...
              'GADS_Toolbox'; ...
              'IDE_Link_MU'; ...
              'Identification_Toolbox'; ...
              'Image_Acquisition_Toolbox'; ...
              'Image_Toolbox'; ...
              'Instr_Control_Toolbox'; ...
              'Link_for_Incisive'; ...
              'Link_for_ModelSim'; ...
              'Link_for_Tasking'; ...
              'Link_for_VisualDSP'; ...
              'MAP_Toolbox'; ...
              'MATLAB'; ...
              'MATLAB_Builder_for_dot_Net'; ...
              'MATLAB_Builder_for_Java'; ...
              'MATLAB_Distrib_Comp_Engine'; ...
              'MATLAB_Excel_Builder'; ...
              'MATLAB_Link_for_CCS'; ...
              'MATLAB_Report_Gen'; ...
              'MBC_Toolbox'; ...
              'MPC_Toolbox'; ...
              'NCD_Toolbox'; ...
              'Neural_Network_Toolbox'; ...
              'OPC_Toolbox'; ...
              'Optimization_Toolbox'; ...
              'PDE_Toolbox'; ...
              'Power_System_Blocks'; ...
              'Real-Time_Win_Target'; ...
              'Real-Time_Workshop'; ...
              'RF_Blockset'; ...
              'RF_Toolbox'; ...
              'Robust_Toolbox'; ...
              'RTW_Embedded_Coder'; ...
              'Signal_Blocks'; ...
              'Signal_Toolbox'; ...
              'SimBiology'; ...
              'SimDriveline'; ...
              'SimElectronics'; ...
              'SimEvents'; ...
              'SimHydraulics'; ...
              'SimMechanics'; ...
              'Simscape'; ...
              'SIMULINK'; ...
              'Simulink_Control_Design'; ...
              'Simulink_Design_Verifier'; ...
              'Simulink_HDL_Coder'; ...
              'Simulink_Param_Estimation'; ...
              'SIMULINK_Report_Gen'; ...
              'SL_Verification_Validation'; ...
              'Spline_Toolbox'; ...
              'Stateflow'; ...
              'Stateflow_Coder'; ...
              'Statistics_Toolbox'; ...
              'Symbolic_Toolbox'; ...
              'SystemTest'; ...
              'Video_and_Image_Blockset'; ...
              'Virtual_Reality_Toolbox'; ...
              'Wavelet_Toolbox'; ...
              'XPC_Embedded_Option'; ...
              'XPC_Target'};

Это охватывает многие из распространенных, но не является исчерпывающим и не включает последовательности функций для новых панелей инструментов. Для всех панелей инструментов MathWorks нет доступного списка текущих последовательностей элементов. Я полагаю, что вы можете найти их в строках «INCREMENT» в файле лицензии, или ( как упоминается в комментарии ) вы можете вызвать функцию из данной панели инструментов, а затем использовать лицензию ('inuse') , чтобы получить последовательность функции из отображаемого списка используемых в настоящее время панелей инструментов. Однако для обоих указанных выше вариантов уже требуется доступная лицензия.

Используя приведенный выше список последовательностей функций и функцию license , можно проверить, какие панели инструментов у вас есть для использования. Следующий код проверяет наличие лицензий для всего приведенного выше списка:

index = cellfun(@(f) license('test', f), featureStr);
availableFeatures = featureStr(logical(index));

Однако приведенное выше только подтверждает, что лицензия существует , а не то, что ее можно извлечь . Возможно, срок действия лицензии истек или все доступные лицензии могут быть извлечены другими пользователями. Чтобы быть абсолютно уверенным, что вы сможете использовать доступные панели инструментов, вы можете на самом деле попытаться проверить лицензию для тех, которые вам нужны и проверить, если вы были успешны. Следующий код пытается проверить лицензию на все доступные панели инструментов, найденные выше:

index = cellfun(@(f) license('checkout', f), availableFeatures);
checkedOutFeatures = availableFeatures(logical(index));

WORD OF WARNING!:

Как упоминает Джейсон S в комментарии ниже , это плохая идея, чтобы проверить лицензии волей-неволей, так как они не будут выпущены, пока вы не закроете MATLAB. Вы должны получить только ту лицензию, которая вам нужна для данного приложения! Обычно лицензии не извлекаются до тех пор, пока вы не попытаетесь использовать функцию из данной панели инструментов. Например:

>> license('inuse')
matlab
>> gaussFilter = fspecial('gaussian');  % An Image Processing Toolbox function
>> license('inuse')
image_toolbox
matlab
-121--1304624-

Как уже говорили другие, это задокументировано.

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

use strict;
use warnings;

use List::MoreUtils qw(apply);

my @array = qw( cat dog horse kanagaroo );

foo(@array);


print join "\n", '', 'foo()', @array;

my @mapped = map { s/oo/ee/g } @array;

print join "\n", '', 'map-array', @array;
print join "\n", '', 'map-mapped', @mapped;

my @applied = apply { s/fee//g } @array;

print join "\n", '', 'apply-array', @array;
print join "\n", '', 'apply-applied', @applied;


sub foo {
   $_ .= 'foo' for @_;
}

Обратите внимание на использование функции List:: MureUtils apply . Он работает как map , но вместо использования ссылки создает копию переменной тематики. Если вы ненавидите написание кода, как:

 my @foo = map { my $f = $_; $f =~ s/foo/bar/ } @bar;

вы будете любить применить , что делает его в:

 my @foo = apply { s/foo/bar/ } @bar;

Что-то, чтобы следить: если вы передаете только для чтения значения в одну из этих конструкций, которая изменяет его входные значения, вы получите ошибку «Изменение только для чтения значение попытка».

perl -e '$_++ for "o"'
4
ответ дан 30 November 2019 в 05:57
поделиться

При краже из этого вопроса можно использовать метод Except < T > () .

-121--2433211-

С LINQ:

var missing = listA.Except(listB).ToList();
-121--2433208-

См. perldoc perlsyn :

Если какой-либо элемент LIST является lvalue, его можно изменить, изменив VAR внутри цикла. И наоборот, если какой-либо элемент LIST НЕ является значением lvalue, любая попытка изменить этот элемент не будет выполнена. Другими словами, переменная индекса цикла foreach является неявным псевдонимом для каждого предмета в списке, по которому выполняется закольцовывание.

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

22
ответ дан 30 November 2019 в 05:57
поделиться

Я отвечу на Ваши обновленные вопросы:

Нужно ли мне писать собственного участника?

Если Вы (а) хотите продолжить использовать проверку подлинности форм и (б) иметь структуру таблицы авторизации, которая не соответствует тем же соглашениям, что и ASPNETDB, то да. Если вам не нужен FormsAuth (см. ниже), то вы можете полностью отказаться от поставщика участия , но я бы не рекомендовал его. Или, если вы используете те же таблицы безопасности, что и ASPNETDB, но хотите указать его на другую базу данных, вы можете продолжить использование поставщика по умолчанию и просто изменить его конфигурацию.

Какие изменения необходимо внести в файл web.config?

Если используется собственный Personnition Provider , необходимо зарегистрировать его в разделе < providers > элемента < membership > и изменить свойство defureProvider . Если используется стандартный AspNetSqlProvider , то, вероятно, необходимо просто изменить последовательность подключения.

Будет ли по-прежнему работать атрибут [Авторизовать], если я пишу собственное решение?

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

Могу ли я использовать автоматически сгенерированный AccountController с некоторыми незначительными изменениями или мне, в основном, нужно переписать контроллер учетной записи с нуля?

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

-121--1458803-

Linux наконечника: Bash параметры и расширения параметров

${PARAMETER##WORD}  Results in removal of the longest matching pattern from the beginning rather than the shortest.
for example
[ian@pinguino ~]$ x="a1 b1 c2 d2"
[ian@pinguino ~]$ echo ${x#*1}
b1 c2 d2
[ian@pinguino ~]$ echo ${x##*1}
c2 d2
[ian@pinguino ~]$ echo ${x%1*}
a1 b
[ian@pinguino ~]$ echo ${x%%1*}
a
[ian@pinguino ~]$ echo ${x/1/3}
a3 b1 c2 d2
[ian@pinguino ~]$ echo ${x//1/3}
a3 b3 c2 d2
[ian@pinguino ~]$ echo ${x//?1/z3}
z3 z3 c2 d2
-121--1258704-

$ a в данном случае является псевдонимом элемента массива. Только не иметь $ a = в коде и вы не будете изменять массив.: -)

Если я правильно помню, map , grep и т.д. все имеют одинаковое поведение наложения.

9
ответ дан 30 November 2019 в 05:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: