Навіщо використовувати суворі та застереження?


104

Мені здається, що багато питань у тезі Perl можна було б вирішити, якби люди користувалися:

use strict;
use warnings;

Я думаю, що деякі люди вважають це схожим на тренувальні колеса або непотрібні ускладнення, що, очевидно, не вірно, оскільки їх використовують навіть дуже кваліфіковані програмісти Perl.

Схоже, більшість людей, які володіють Перлом, завжди використовують ці дві прагми, тоді як ті, хто отримає найбільше користь від їх використання, рідко роблять. Отже, я подумав, що було б гарною ідеєю виникнути питання, на яке слід посилатися, коли заохочувати людей до use strictта warnings.

Отже, навіщо розробнику Perl use strictі warnings?


14
Мені завжди цікаво подібне, чому вони не просто роблять це за замовчуванням, і дев фактично повинен активно послаблювати речі, деuse loose;
Пол Тайнг

12
Як і багато цікавих і корисних речей, Perl розпочався як хак, як інструмент для хлопця, який це вигадує. Пізніше він став більш популярним, і все більша кількість некваліфікованих людей почала ним користуватися. Це коли ви починаєте думати щось на кшталт use strictбуло гарною ідеєю, але зворотна сумісність вже стала для вас справжньою проблемою :-(
Daniel Böhmer

14
@JB Nizet, @Paul T. Власне, use strict;за замовчуванням увімкнено, коли ви вимагаєте мови Perl 5.12 (або вище). Спробуйте perl -e"use v5.012; $x=123;". no strict;насправді вимикає.
ikegami

1
Хоча, врешті-решт, ваша думка правдива, чим більше ми говоримо це, можливо, тим більше людей почує. Останнім часом спостерігаються бурхливі спроби зробити більш / кращими / сучасними підручники Perl, і, безумовно, суворі / попередження будуть у верхній частині кожного з них. Щодо мого, я планую ввімкнути ш / б у верхній частині кожного фрагмента, просто так, щоб усі новачки його бачили кожен раз
Джоел Бергер

5
@JoelBerger Ні, насправді це ні до чого. Як я вже казав, у заголовку є лише подібні слова. Це для зворотної сумісності. це перше речення у прийнятій відповіді, як ви пропонуєте те, що стосується мого питання?
TLP

Відповіді:


83

Для початку, use strict;(і в меншій мірі use warnings;) допомагає знаходити друкарські помилки в назвах змінних. Навіть досвідчені програмісти роблять такі помилки. Поширений випадок - це забуття перейменувати екземпляр змінної при очищенні чи рефакторингу коду.

Використання use strict; use warnings;виявляє багато помилок раніше, ніж їх було б виявлено в іншому випадку, що полегшує пошук першопричин помилок. Першопричиною може бути необхідність перевірки помилки або перевірки, і це може статися незалежно від навичок програміста.

Що стосується попереджень Perl, це те, що вони рідко є хибними, тому використання їх майже не коштує.


Пов'язане читання: Навіщо використовувати my?


2
@TLP, я не збираюся робити дослідження, щоб оцінити, наскільки це допомагає. Досить сказати, що вони допомагають беззастережно.
ikegami

1
Чому це робиться необов’язковим, якщо він має стільки переваг? Чому б не включити його за замовчуванням (як хтось прокоментував вище)? Це з міркувань сумісності?
Жан

4
@Jean, зворотна сумісність. Зауважте, що use strict;це увімкнено за умовчанням, якщо ви використовуєте версію 5.12 або новішу мову ( use 5.012;).
ikegami

@Jean, якщо ви пишете простий сценарій, ви насправді не хочете отримувати сповіщення про попередження про імена файлових файлів або за те, що не оголошуєте змінну перед їх використанням :-)
user2676847

28

Мабуть, use strictслід (повинні) використовуватись, коли ви хочете змусити perl правильно кодувати, що може бути примусовим декларуванням, будучи явним для рядків і підпунктів, тобто баревок, або використовуючи рефлекси з обережністю. Примітка: якщо є помилки, використання строгих буде перервати виконання, якщо воно використовується.

Хоча use warnings;ви допоможете знайти помилки введення в програмі, як ви пропустили крапку з комою, ви використовували "elseif", а не "elsif", ви використовуєте застарілий синтаксис або функцію, як би там не було. Примітка: використання попереджень забезпечить лише попередження та продовження виконання, тобто не буде припиняти виконання.

У будь-якому разі, було б краще, якщо ми розберемося в деталях, які я конкретизую нижче

Від perl.com (моя улюблена):

використовувати суворі 'vars';

що означає, що ви завжди повинні оголошувати змінні, перш ніж їх використовувати.

Якщо ви не заявите, ви, ймовірно, отримаєте повідомлення про помилку для незадекларованої змінної

Глобальний символ "$ змінної імені" вимагає явного імені пакета на скрипті scriptname.pl 3

Це застереження означає, що Perl не зовсім зрозумілий, що таке область змінної. Тому вам потрібно чітко вказати свої змінні, що означає або оголосити їх, myщоб вони були обмежені до поточного блоку, або посилалися на них з їх повною мірою ім'я (наприклад, $ MAIN :: ім'я змінної).

Отже, помилка часу компіляції спрацьовує, якщо ви намагаєтеся отримати доступ до змінної, яка не відповідала принаймні одному з наступних критеріїв:

  • Заздалегідь визначений самим Perl, таким як @ARGV,% ENV та всі глобальні пунктуаційні змінні, такі як $. або $ _.

  • Оголошено нашим (для глобального) або моїм (для лексичного).

  • Імпортовано з іншого пакета. (Прагма використання vars підробляє імпорт, але використовуйте нашу замість цього.)

  • Повністю кваліфікований, використовуючи назву пакета та роздільник подвійного двокрапки.

використовувати суворі "підводки";

Розглянемо дві програми

# prog 1
   $a = test_value;
   print "First program: ", $a, "\n";
   sub test_value { return "test passed"; }
 Output: First program's result: test_value

# prog 2
   sub test_value { return "test passed"; }
   $a = test_value;
   print "Second program: ", $a, "\n";
 Output: Second program's result: test passed

В обох випадках у нас є підпрограма test_value (), і ми хочемо поставити його результат у $ a. І все ж, коли ми запускаємо дві програми, ми отримуємо два різні результати:

У першій програмі, в момент, до якого ми дістаємось $a = test_value;, Perl не знає жодного підпрограми test_value (), а test_value інтерпретується як рядок 'test_value'. У другій програмі визначення test_value () постає перед $a = test_value;рядком. Perl вважає test_value як додатковий дзвінок.

Технічний термін для ізольованих слів, таких як test_value, які можуть бути підводними і можуть бути рядками залежно від контексту, до речі, є головною мовою . Поводження Perle з бареворками може бути заплутаним, і це може призвести до помилок у програмі.

Про помилку - це те, з чим ми стикалися в нашій першій програмі. Пам'ятайте, що Perl не буде з нетерпінням чекати test_value(), тому, оскільки він ще не бачив test_value (), він передбачає, що вам потрібна рядок. Тож якщо ви use strict subs;, це призведе до вмирання цієї програми з помилкою:

Баревочка "test_value" не дозволена, тоді як "суворі абонементи" використовуються за адресою ./a6-strictsubs.pl 3.

Вирішення цієї помилки було б
1. Використовуйте круглі дужки, щоб зрозуміти, що ви викликаєте суб. Якщо Perl бачить $ a = test_value () ;,
2. Заявіть про свій підрозділ перед тим, як вперше його використовувати

use strict;
sub test_value;  # Declares that there's a test_value() coming later ...
my $a = test_value;  # ...so Perl will know this line is okay.
.......
sub test_value { return "test_passed"; }

3. І якщо ви хочете використовувати його як рядок, цитуйте його.

Отже, ця стриктура змушує Perl трактувати всі бареври як синтаксичні помилки. * Барево - це будь-яке оголене ім’я або ідентифікатор, який не має іншої інтерпретації, вимушеної контекстом. (Контекст часто вимушений ключовим словом чи лексемою, що знаходиться поблизу, або заздалегідь визначеним словом.) * Отже, якщо ви маєте на увазі використовувати його як рядок, цитуйте його, і якщо ви хочете використовувати його як виклик функції, попередньо визначте його або використовувати дужки.

Бареври небезпечні через таку непередбачувану поведінку. use strict; (or use strict 'subs';)робить їх передбачуваними, тому що босові слова, які можуть спричинити дивну поведінку в майбутньому, змусять вашу програму померти, перш ніж вони можуть завдати шкоди

Є одне місце, де нормально використовувати бареври, навіть коли ви ввімкнули суворі абонементи: коли ви призначаєте хеш-ключі.

$hash{sample} = 6;   # Same as $hash{'sample'} = 6
%other_hash = ( pie => 'apple' );

Бареври в хеш-клавішах завжди інтерпретуються як рядки, тому неоднозначності немає.

використовувати суворі 'refs';

Це створює помилку під час виконання, якщо ви використовуєте символічні посилання навмисно чи іншим чином. Значення, яке не є твердим посиланням, тоді трактується як символічне посилання . Тобто посилання трактується як рядок, що представляє ім'я глобальної змінної.

use strict 'refs';

$ref = \$foo;       # Store "real" (hard) reference.
print $$ref;        # Dereferencing is ok.

$ref = "foo";       # Store name of global (package) variable.
print $$ref;        # WRONG, run-time error under strict refs.

використовувати попередження;

Ця прагма, що охоплюється лексично, дозволяє гнучко контролювати вбудовані попередження Perl, як над тими, що випускаються компілятором, так і з боку системи, що працює під час виконання.

Від perldiag:

Отже, більшістю попереджувальних повідомлень із наведених нижче класифікацій, наприклад W, D&S, можна керувати за допомогою warningsпрагми.

(W) Попередження (необов'язково)
(D) Депресія (увімкнено за замовчуванням)
(S) Суворе попередження (увімкнено за замовчуванням)

Я перерахував деякі повідомлення попереджень, які часто трапляються нижче за класифікаціями. Для отримання більш докладної інформації про них та інші повідомлення , див perldiag

(W) Попередження (необов’язково):

Відсутній аргумент у% s
Відсутній аргумент до -% c
(Ви мали на увазі &% s замість?)
(Ви мали на увазі "локальний" замість "наш"?)
(Ви мали на увазі $ чи @ замість%?)
'% S '- не контрольна
довжина коду (), що використовується для% s
Невмілене _ число

(D) Анулювання (увімкнено за замовчуванням):

визначений (@array) застарілий,
визначений (% хеш), застарілий
Використання мого () у хибних умовних
$ # більше не підтримується

(S) Суворе попередження (увімкнено за замовчуванням)

elseif має бути elsif
% s, коли очікується, що оператор
(Відсутній оператор до% s?)
(Відсутній крапку з комою в попередньому рядку?)
% s ніколи не введено
Оператор або крапка з комою відсутні перед% s
Проблема прецеденту: open% s повинен бути відкритим (% s)
Невідповідність прототипу:% s проти% s
Попередження: Використання "% s" без дужок неоднозначно
Неможливо відкрити% s:% s


10

Ці дві прагми можуть автоматично ідентифікувати помилки у вашому коді.

Я завжди використовую це у своєму коді:

use strict;
use warnings FATAL => 'all';

FATALзмушує код відмирати на попередженнях, як strictі у випадку.

Для отримання додаткової інформації див.: Будьте суворіші з використанням попереджень FATAL => 'all';

Також ... стриктури, за словами Сеуса


Насправді, вам доведеться затримати час FATAL => "all"виконання, призначаючи $SIG{__WARN__} = sub { croak "fatalized warning @_" };або іншим чином ви накручуєте компілятор, намагаючись сказати, що йому потрібно.
tchrist

6
@tchrist: Це завжди працювало для мене як є і як задокументовано. Якщо ви знайшли випадок, коли він не працює як задокументовано, будь ласка, виправляйте документацію за допомогою perlbug.
інструментарій


3

Джерело :: Різні блоги

Використання буде експортувати функції та імена змінних в основний простір імен, викликаючи модулі import ().

Прагма - це модуль, який впливає на деякий аспект часу компіляції або на поведінку часу виконання perl.Pragmas дає підказки компілятору.

Використовуйте попередження - перл скарги на змінні, що використовуються лише один раз, неправильне перетворення рядків у числа,. Спроба запису у файли, які не відкриті. Це відбувається під час компіляції. Вона використовується для контролю попереджень.

Використовуйте строгий - оголошуйте область змінних. Він використовується для встановлення певної дисципліни в сценарії. Якщо барі-слова використовуються в коді, який вони інтерпретуються. Всім змінним слід надати область, як-от моя, наша чи локальна.


1

Директива "використовувати суворо" дозволяє Perl робити додаткову перевірку під час компіляції вашого коду. Використання цієї директиви допоможе вам заощадити час налагодження коду Perl, оскільки він знаходить поширені помилки кодування, які ви можете ігнорувати інакше.


0

Строгі та попередження переконайтеся, що ваші змінні не є глобальними.

Набагато акуратніше мати можливість змінювати унікальні для окремих методів змінні, а не слідкувати за кожним іменем змінної.

$ _ або відсутність змінної для певних функцій також може бути корисно для швидшого написання більш компактного коду.

Однак якщо ви не використовуєте суворі та попередження, $ _ стає глобальним!


0
use strict;
use warnings;

Строгі та попередження - це режим для програми perl. Це дозволяє користувачеві вводити код більш вільно і більше того, що код Perl буде виглядати формальним, а його стандарт кодування буде ефективним.

попередження означає те саме, що і -wв рядку perl shebang, тому він надасть вам попередження, згенеровані програмою perl, відображатиметься в терміналі

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.