2012-04-18 7 views
4

Я работаю несколько недель, пытаясь сделать работу с программой perl. Кто-то написал это, и с тех пор источник данных был изменен. Я провел несколько недель подряд, проводя учебники. Я застрял. Код говорит @{ $Routings{$Code} }, который имеет список значений [ $ProcessID, $Setup, $Process ], но в нижней части кода, когда foreach (@{ $Routings{$Code} }) {my $ProcessCodeID = @$_[0];}, похоже, не возвращает данные. Если бы кто-нибудь даже помог мне print $ProcessCodeID, чтобы я мог отслеживать данные, это было бы очень полезно.

Также, если вы могли бы объяснить, что представляет собой @{$value{$key}}, это действительно поможет.

Спасибо, кучи.

%Routings =(); 
my $dbh = DBI-> connect('dbi:ODBC:SQL') 
    or die "Couldn't open Databaxe: $DBI::errstr; stopped"; 

my $query= $dbh->prepare("SELECT Code, Setup, Process, ProcessID FROM ROUTING"); 

$query->execute() or die "Couldn't execute statement: $DBI::errstr; stopped"; 

while (my ($Code, $setup, $process, $processid) = $query->fetchrow_array()){ 
    push (@{ $Routings{$Code} }, [ $ProcessID, $Setup, $Process ]); 
} 

foreach (@{ $Routings{$Code} }) { 
    my $ProcessCodeID = @$_[0]; 
    my $SetupMins = @$_[1]; 
    my $ProcessMins = @$_[2]; 
} 

ответ

6

Прежде всего, важно, что вы use strict и use warnings в начале вашей программы, и объявить все переменные в точке они первые используются. Это заставит Perl генерировать очень полезные сообщения, которые позволят выявить множество простых ошибок, которые легко упустить.

В качестве примера, вы назначаете переменные $setup, $process и $processid, но затем толкая $Setup, $Process и $ProcessID на массив. Идентификаторы Perl чувствительны к регистру, поэтому это три разные переменные и на данный момент будут иметь значение undef. use strict напечатал бы ошибку компиляции, заявив, что $ProcessID и т. Д. Не был объявлен. (Если у вас есть выбор, лучше использовать нижний регистр плюс подчеркивание для локальных идентификаторов, подобных этим. Опытные программисты на Perl будут благодарны вам.)

Вы должны поэкспериментировать с Data::Dumper module, в котором будут показаны содержимое и структура сложная вложенная структура данных Perl, подобная этой. После того как вы use Data::Dumper в вашей программе вы можете написать

print Dumper \%Routings 

который покажет содержимое как анонимный хэш.

Значение каждого элемента $Routings{$Code} хеша - это список (ссылка на массив) всех наборов ProcessID, Setup и Process, соответствующих этому значению кода. (Я полагаю, что столбец Code не является уникальным, в противном случае структура данных более сложна, чем должна быть.) Таким образом, первый набор из трех значений для данного $Code находится на $Routings{$Code}[0], а ProcessID для этого набора - $Routings{$Code}[0][0].

Там нет коды, чтобы присвоить значение $Code для контура foreach, и, вероятно, вы хотели бы, чтобы перебрать все ключи от хэша.

Каждый раз в цикле foreach$_ устанавливается ссылка на каждый триплет значений для текущего $Code. Это означает, что @$_ представляет собой трехэлементный массив, но он должен быть проиндексирован с использованием $_->[0] и т. Д. Вместо @$_[0], который является одноэлементным фрагментом массива и плохой практикой кодирования. Код становится более неясным, используя здесь по умолчанию $_, и я пояснил его ниже, используя именованную переменную.

Приведенный ниже код устраняет проблемы, которые я вижу. Пожалуйста, вернитесь, если вам нужна дополнительная помощь.

use strict; 
use warnings; 

use DBI; 

my %Routings; 

my $dbh = DBI-> connect('dbi:ODBC:SQL') 
    or die "Couldn't open Databaxe: $DBI::errstr; stopped"; 

my $query= $dbh->prepare("SELECT Code, Setup, Process, ProcessID FROM ROUTING"); 

$query->execute or die "Couldn't execute statement: $DBI::errstr; stopped"; 

while (my ($Code, $Setup, $Process, $ProcessID) = $query->fetchrow_array){ 
    push @{ $Routings{$Code} }, [ $ProcessID, $Setup, $Process ]; 
} 

for my $Code (keys %Routings) { 
    foreach my $triplet (@{ $Routings{$Code} }) { 
    my $ProcessCodeID = $triplet->[0]; 
    my $SetupMins = $triplet->[1]; 
    my $ProcessMins = $triplet->[2]; 
    print "$Code => ($ProcessCodeID, $SetupMins, $ProcessMins)\n"; 
    } 
} 

Следует отметить, что назначение в цикле foreach можно сделать более четким и кратким, выполняя их все сразу. Как я уже объяснял, @$triplet является массив из трех элементов, так что эквивалентно уступка может быть закодирован как просто

my ($ProcessCodeID, $SetupMins, $ProcessMins) = @$triplet; 

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

+2

Большое вам спасибо. Я пропустил разницу в верхнем и нижнем регистре. Теперь это работает. Я также ценю объяснение и помогаю очистить свой код. Большое спасибо. – user1340197

+0

Если вы не хотите идти на поводу (по общему признанию, очень мало проблем) добавления 'use Data :: Dumper' к вашему коду, вы можете видеть то же самое, проверяя хеши и массивы с помощью команды« x »в perl отладчик. Пройдите код до тех пор, пока соответствующая переменная не будет заполнена, а затем введите 'x @ {$ value {$ key}}'. Отладчик использует Data :: Dumper для отображения структуры массива или хэша (он действительно работает лучше с хеш-ссылками). –

0

Это на самом деле не пытается к return данные - это просто создание переменных с данными, а затем быстро ничего не делать с данными. Попробуйте следующее:

foreach (@{ $Routings{$Code} }) { 
    my $ProcessCodeID = @$_[0]; 
    my $SetupMins = @$_[1]; 
    my $ProcessMins = @$_[2]; 
    print "$Code: $ProcessCodeID, $SetupMins, $ProcessMins\n"; 
} 

Если вы не используете переменные в цикле, его не так много.

Конструкция сложного ish @{ $foo{$bar} } сообщает Perl обрабатывать $foo{$bar} как массив. $foo{$bar} - поиск хэша. (%Routings =(); наверху, который объявляет и инициализирует хэш.)

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

+0

Hi @sarnold, Спасибо за быстрый ответ. Я попробовал линию печати, и она ничего не вернула. Нет новых ошибок, но нет печати/данных. – user1340197

+0

На самом деле Perl точно знает, что это такое в '$ Routings {$ Code}'. Тогда синтаксис 'foreach (@ {$ Routings {$ Code}}) не' foreach ($ Routings {$ Code}) 'потому что' foreach ($ Routings {$ Code}) 'тоже делает. – ikegami

+0

@ikegami: Большое спасибо за Perl-izing мой ответ _and_ коррекция. Оба оценены! – sarnold

5

Код группирует «записи маршрутизации» по «коду».


- это хэш. Он вводится под ключ «код». Каждое значение является ссылкой на массив. Эти массивы автогенерируются push (@{ $Routings{$Code} },, что является сокращением для push (@{ $Routings{$Code} //= [] },.

Каждый из этих массивов содержит несколько «записей». Каждая «запись» является ссылкой на массив из трех элементов («идентификатор процесса», «настройка» и «процесс»). Они создаются по [ $ProcessID, $Setup, $Process ].

дамп будет выглядеть следующим образом:

{ 
    $code0 => [ 
     [ $ProcessID0, $setup0, $Process0 ], 
     [ $ProcessID2, $setup2, $Process2 ], 
     ... 
    ], 
    $code1 => [ 
     [ $ProcessID1, $setup1, $Process1 ], 
     [ $ProcessID5, $setup5, $Process5 ], 
     ... 
    ], 
    $code2 => [ 
     [ $ProcessID3, $setup3, $Process3 ], 
     [ $ProcessID4, $setup4, $Process4 ], 
     ... 
    ], 
    ... 
} 

$Code Если имеет значимое значение — вы не показали, что получение значения — $Routings{$code} бы оценить в одной из этих ссылок на массивы. Из приведенного выше примера,

[ 
    [ $ProcessID0, $setup0, $Process0 ], 
    [ $ProcessID2, $setup2, $Process2 ], 
    ... 
], 

@{ ... } указывает на Perl, который вы хотите derefence что эталонным. Другими словами, он сообщает Perl, что вас интересует сам массив.

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

[ $ProcessID0, $setup0, $Process0 ], 

Во второй раз,

[ $ProcessID2, $setup2, $Process2 ], 

т.д.

@$_[0] (сокращенно @{ $_ }[0], который неправильно используется ${ $_ }[0], который более читаем как $_->[0]) получает первый элемент ссылочного массива ($ProcessID0). Аналогичным образом, @$_[1] и @$_[2] получают $setup0 и $Process0.


Конечно, вы ничего не предпринимаете с данными. Вы, вероятно, имел в виду, чтобы сделать

foreach (@{ $Routings{$Code} }) { 
    my $ProcessCodeID = ${$_}[0]; 
    my $SetupMins  = ${$_}[1]; 
    my $ProcessMins = ${$_}[2]; 
    print("$ProcessCodeID ,$SetupMins, $processMins\n"); 
} 

Подчищены:

foreach (@{ $Routings{$Code} }) { 
    my $ProcessCodeID = $_->[0]; 
    my $SetupMins  = $_->[1]; 
    my $ProcessMins = $_->[2]; 
    print("$ProcessCodeID, $SetupMins, $processMins\n"); 
} 

Вымытый несколько больше:

for (@{ $Routings{$Code} }) { 
    my ($ProcessCodeID, $SetupMins, $ProcessMins) = @$_; 
    print("$ProcessCodeID, $SetupMins, $processMins\n"); 
} 

Технически, вы можете даже сделать

for (@{ $Routings{$Code} }) { 
    print(join(', ', @$_), "\n"); 
} 

или

print(join(', ', @$_), "\n") 
    for @{ $Routings{$Code} }; 
+0

Спасибо, что помогли мне. Ваше объяснение было предельно ясным и действительно помогло мне понять, на что я смотрю. – user1340197

4

Насколько вы знаете о Perl-ссылках? Вы можете посмотреть несколько tutorials на Perl references.

Краткое пособие

Все три основных структур данных в Perl (скаляры, массивы и хэши) предназначены для хранения отдельных значений данных. Например, у меня есть массив сотрудников:

$employee_list[0] = "Bob"; 
$employee_list[1] = "Carol"; 
$employee_list[2] = "Ted"; 
$employee_list[3] = "Alice"; 

Да, есть четыре части данных в моем массиве, но в простом Perl, каждый элемент содержит только одно значение - первое имя. Что мне делать, если мне также нужна фамилия сотрудника или зарплата или должность? Нет простого способа сделать это в базовой структуре данных Perl.

Ссылки - это способ, позволяющий хранить более одной части данных в переменной Perl. Давайте посмотрим на полную запись сотрудника Боба:

$employee{FIRST} = "Bob"; 
$employee{LAST} = "Jones"; 
$employee{PAY} = "1400"; 
$employee{PHONE} = "1234"; 

Теперь, как я могу сжать всю эту информацию в $employee_list[0]? .

Perl позволяет принимать ссылку на этот хэш %employee (главным образом место в памяти, где хранится хэш Вы можете сделать это, поставив обратную косую черту перед ним:

$employee_list[0] = \%employee; 

сейчас в этом один $employee_list[0] слоте, у меня есть ссылка на хэш Perl, который имел все данные сотрудника Боба. Теперь вопрос в том, как я могу получить доступ к этой информации?

я могу получить доступ к информации в моей ссылке на разыменовании это.Вы что, поставив правильный sigil перед ссылкой:

$employee_reference = $employee_list[0]; 
%employee_hash  = %$employee_reference; 
print "Employee name is $employee_hash{FIRST} $employee_hash{LAST}\n"; 

Я сначала получить ссылку, то я могу разыменования его в новый %employee_hash. Как только я это сделаю, я могу использовать информацию, находящуюся в хеше. Это большая работа. Посмотрите на $employee_reference. Все, что я делаю с этим, получает ссылку, поэтому я могу разыменовать ее. Почему бы не вырезать этот шаг и не принять мое различие от $employee_list[0]?

%employee_hash  = %{ $employee_list[0] }; 
print "Employee name is $employee_hash{FIRST} $employee_hash{LAST}\n"; 

Примечание. Я использую фигурные скобки вокруг своей ссылки. Кудрявые скобки напоминают скобки вокруг уравнения. Они позволили Перлу понять, что делать в первую очередь.

Опять же, я ничего не делаю с %employee_hash. Это просто место, где я могу бросить свой хэш, поэтому я могу его распечатать. Почему бы не разыменовать хэш и не получить значение определенного ключа за один шаг? Еще лучше. В одном шаге:

print "Employee name is " 
    . ${ $employee_list[0] }{FIRST} . " " 
    . ${ $employee_list[0] }{LAST} . "\n"; 

Я разыменования $employee_list[0] в хэш и принимая этот хэш, и извлечение значения конкретного ключа все в том же шаге. Обратите внимание, что я использую $ вместо %.

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

print "Employee name is " 
    . $employee_list[0]->{FIRST} . " " 
    . $employee_list[0]->{LAST} . "\n"; 

Оператор -> принимает разыменования для вас.

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

$employee_list[0] = { LAST => "Jones", FIRST => "Bob", 
    SALARY => 1400, PHONE => "1234" } 

Фигурные скобки для анонимных хэшей. Квадратные скобки для анонимные массивы. Они анонимны, потому что они не относятся к переменной, а просто относятся к хешу или массиву.

Data :: Dumper

Как вы можете себе представить, эти структуры данных могут быть довольно сложными. Например, я отслеживаю адрес сотрудника, но адрес состоит из улицы, города, штата и почтового индекса. Иногда на улице есть более одной линии. И что, если есть более одного адреса? Там нет причин, почему хеш или ссылки на массив не может содержать ссылку на другой хэш или массив:

$employee_list[0]->{NAME}->{FIRST} = "Bob"; 
$employee_list[0]->{NAME}->{LAST} = "Jones"; 
$employee_list[0]->{ADDRESS}->[0]->{TYPE} = "Business"; 
$employee_list[0]->{ADDRESS}->[0]->{STREET}->[0] = "123 Mockingbird Lane"; 
$employee_list[0]->{ADDRESS}->[0]->{STREET}->[1] = "Tower 2"; 
$employee_list[0]->{ADDRESS}->[0]->{CITY} = "Beantown"; 
$employee_list[0]->{ADDRESS}->[0]->{STATE} = "MA"; 

Как вы можете видеть $ employee_list [0] указывает на ссылки на хэш сотрудника. Этот хэш имеет «ИМЯ», «АДРЕС» и другие ключи, заполненные данными. Поле NAME является ссылкой на другой хэш, который имеет два ключа: FIRST и LAST. Поле ADDRESS на самом деле является ссылкой на массив адресов. И каждая из этих записей массива является ссылкой на хэш. Представьте, что вы пытаетесь отладить эту структуру данных!

Data::Dumper представляет собой модуль, который будет анализировать через самые сложные структуры данных и распечатать их для вас:

use Data::Dumper; 

[...] 

print "Employee Dump: " . Dumper \@employee . "\n"; 

Это будет печатать всю структуру всех сотрудников в массиве сотрудников.

Если вы не знаете, что @{$value{$key}}, вы можете легко запустить дамп на нем:

print Dumper $value{$key} . "\n"; 

Декодировании Вашей программы

Давайте пройдемся по линиям один за другим:

%Routings =(); 
my $dbh = DBI->connect('dbi:ODBC:SQL') 
    or die "Couldn't open Databaxe: $DBI::errstr; stopped"; 

Вы инициализировали хэш с именем и создали объект DBI, который представляет соединение с вашей базой данных. connect - это подпрограмма, определенная в Perl как часть класса DBI. Все классы состоят из множества подпрограмм Perl, которые работают с объектами, созданными этим классом. Эти подпрограммы делятся на конструкторы и методы. Конструкторы создают ссылку на сложную структуру данных, которая представляет объект. Методы - это подпрограммы, которые могут работать на этом объекте. Представьте себе нашу запись сотрудника:

$employee = Person::Employee->new; 
$employee->first_name("Bob"); 

Первая строка создает $employee объект из моего Person::Employee класса. Это объект $employee - это просто ссылка на хэш, содержащий информацию о моем сотруднике. Итак, моя подпрограмма new является конструктором .

Во второй строке используется подпрограмма first_name, которая позволяет мне установить имя сотрудника. Эта подпрограмма называется Метод или иногда Функция участника.

Итак, возвращаясь к программе, мы создали объект, который представляет наше соединение с базой данных. Если вы хотите, вы можете использовать Data::Dumper, чтобы распечатать структуру этого объекта , если это поможет вам понять его немного лучше. Это просто ссылка на хэш.

my $query= $dbh->prepare("SELECT Code, Setup, Process, ProcessID FROM ROUTING"); 
$query->execute() or die "Couldn't execute statement: $DBI::errstr; stopped"; 

я теперь подготовить мой SQL заявление, которое я хочу выполнить. После того, как я его подготовил, я его выполнил. Выполнение - это действительно то, что попадает в базу данных. Обратите внимание, что мой prepare - это метод для дескриптора базы данных $dbi, но это также конструктор, потому что он создал объект $query.

Я использую этот объект $query для фактического выполнения моего запроса. Опять же, не бойтесь использовать Data::Dumper, чтобы распечатать его.

while (my ($Code, $setup, $process, $processid) = $query->fetchrow_array()){ 
    push (@{ $Routings{$Code} }, [ $ProcessID, $Setup, $Process ]); 
} 

Давайте упростить этот бит:

while (my @fetched_row = $query->fetchrow_array()){ 
    my ($Code, $setup, $process, $processid) = @fetched_row; 
    push (@{ $Routings{$Code} }, [ $ProcessID, $Setup, $Process ]); 
} 

fetchrow_array это подпрограмма, которая выбирает одну строку из моего запроса в виде массива столбцов. Эта подпрограмма представляет собой метод объекта $query, который я создал выше. Все, что я делаю, - это извлекать каждую строку из моей базы данных и помещать ее в четыре скалярные переменные Perl.

Последняя строка немного сложна. Запомнить мой хэш, который я инициализировал? По-видимому, каждый ключ в этом хеше - это ссылка на массив значений. Хэш вводится на основе $Code, который я набрал выше, и это указывает на массив из трех элементов, состоящий из $ProcesssID, $Setup и $Process. Мы могли бы переписать третью строчку так:

my @temp_array = ($ProcessID, $Setup, $Process); 
my @temp_routing_array = @{ $Routings{Code} }; #Dereferencing the $Routing{$Code} array 
push(@temp_routing_array, \@temp_array);  #Pushing a reference into my array 
$Routing{$Code} = \@temp_routing_array; #Creating a reference again 

[ $ProcessID, $Setup, $Process ] является просто создание ссылки на анонимный массив. Это сэкономит нам трудность создания @temp_array, а затем нажав ссылку @temp_array на мой @temp_routing_array.

И, пока мы на нем, произошла ошибка в вашем коде. Я получаю $setup, $process и $processid, но я храню (смотрю корпус с именами переменных) $Setup, $Process и $ProcessID.

Теперь мы добираемся до петли foreach и еще одной ошибки. Какая ценность $Code? Он не имеет значения, поскольку переменная $Code существует только в цикле while выше. Когда вы объявляете переменную с my, значение этой переменной теряется после того, как вы покинете блок кода.

Эта ошибка, и вышеприведенная ошибка могла быть поймана, если у вас были use strict; и use warnings; в верхней части вашей программы.

Давайте посмотрим на эту петлю:

foreach (@{ $Routings{$Code} }) { 
    my $ProcessCodeID = @$_[0]; 
    my $SetupMins = @$_[1]; 
    my $ProcessMins = @$_[2]; 
} 

Этот foreach цикл использует устаревший стиль, в котором вы предполагаете, вы перекручивание через переменную $_. Это сбивает с толку, и большинство людей научились не использовать его. Давайте перепишем его:

my @routing_code_ref_array = @{ $Routings{$Code} }; 

foreach my $routing_array_ref (@routing_code_ref_array) { 
    my @routing_array = @{ $routing_array_ref }; 

    my $ProcessCodeID = $routing_array[0]; 
    my $SetupMins  = $routing_array[1]; 
    my $ProcessMins = $routing_array[2]; 
} 

Помните, что $Routings{$Code} является ссылкой на массив. В моей первой строке я разыгрываю это. В исходном коде разыменование произошло в цикле foreach. Не только было $Routings{$Code} ссылка на массив, но каждая запись в этом массиве была ссылкой на другой массив. Это array of arrays.

Итак, каждая запись в моем @routing_code_ref_array является ссылкой на другой массив, который я разыменовываю еще раз. Теперь я просто беру значения каждого элемента массива и помещаю его в обычные скалярные переменные Perl.

Хватит уже!

Извините за длинное объяснение, но у вас есть код, который затрагивает ссылки, классы, методы, конструкторы, объекты и целую кучу довольно продвинутых тем Perl. Как и несколько ошибок, которые я указал. Ошибки, которые могли быть пойманы с помощью пары стандартных прагм Perl: use strict; и use warnings;.

Если есть все, что вы можете забрать это:

  • Такие вещи, как @$foo{$bar}[4] или @{ $foo{bar} }[4] или (более правильно) ${ $foo{bar} }[4] или (более четко) $foo{bar}->[4] ссылки на более сложные структуры данных. В базовых структурах данных Perl может храниться только один элемент за раз. Используя ссылки на другие структуры данных, вы можете иметь массивы массивов или массивов хешей или хешей хешей или хэшей массивов или даже массивы хешей хешей массивов хешей. Не паникуйте и не пытайтесь разбирать эти вещи изнутри. Иногда бывает проще, если вы можете обрабатывать особенно сложную структуру данных в нескольких строках.
  • Если вы собираетесь столкнуться с сложными структурами, Data::Dumper - ваш друг. Он быстро выявит структуру этих чрезмерно сложных структур и поможет вам отладить проблемы с вашей программой.
  • Используйте strict и warnings в ваших программах. Они заберут много программных ошибок. Как я уже сказал, я нашел два, связанных как с областью действия локальной переменной, так и с ошибкой в ​​случае имен переменных. Это также великая идея стандартизировать имена переменных. Эти два метода - camelCasing и используются только символы подчеркивания и строчные буквы. Таким образом, вы знаете, что это всегда $foo_bar и никогда $Foo_Bar или $FooBar или $fooBar. Старый стандарт был верблюжьим корпусом, первая буква которого была строчной буквой. Новый стандарт использует строчные буквы и подчеркивает только.
+0

Неверный и вводящий в заблуждение * «Этот цикл foreach использует устаревший стиль, в котором вы предполагаете, что вы перебираете переменную $ _. Это запутанно, и большинство людей научились не использовать его». *. Существует место как для имен, так и для переменных управления циклом по умолчанию, и последнее, безусловно, не устарело. – Borodin

+0

@Borodin Damian Conway _Perl Best Practices_, охватывает использование '$ _' в разделе переменных _Iterator_ в главе 6. Он в основном охватывает проблемы ремонтопригодности. Тем не менее, есть также проблема _pooky действия на расстоянии_. У вас есть цикл 'for', и как часть цикла' for' вы вызываете подпрограмму, которая также использует '$ _'. Поскольку '$ _' является глобальным, он будет изменен на вас. Неприемлемое использование этих _Mysterious Moe_ глобальных переменных не улучшает читаемость, путает новых пользователей и является головной болью обслуживания. –

+0

Я знаю, что говорит PBP и соглашается, что могут быть проблемы с использованием '$ _' с чем-то большим, чем обычные циклы, но это эквивалентно использованию местоимений в разговорном языке, который имеет точно такие же проблемы. Я не слышал, чтобы кто-то призывал к отмене слова * это *, и просто заботиться о том, чтобы не быть двусмысленным, достаточно. Это далеко не устаревший стиль * и ни в коем случае не * большинство людей * научились не использовать его. Это даже обязательно при использовании 'map' или' grep'. – Borodin

Смежные вопросы