Модераторы: korob2001, ginnie

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> О скалярных значениях в булевом контексте, это должен помнить каждый :о) 
:(
    Опции темы
ginnie
Дата 3.6.2008, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



Уважаемые коллеги! В разделе вакансий Perl-разработчиков на Яндексе публикуются тестовые задания. Одно из заданий такое

Что напечатает программа?

Код

$a = "000";
if ($a) {
    print "A";
} else {
    print "B";
}


Как обычно, если чем-то часто не пользуешься, то со временем оно забывается. Так и в данном случае из головы выветрилось, какие скалярные значения являются false в булевом контексте.
Цитата из  Уолл Л., Кристиансен Т., Орвант Д. Программирование на Perl (3-е издание):

Цитата

...скалярное значение является истинным, если оно не равно нулевой строке "" или числу 0 (или его строковому эквиваленту, "0"). Ссылка всегда истинна, поскольку представляет адрес, не могущий быть 0. Неопределенное значение (часто обозначаемое undef) всегда ложно, поскольку является "" или 0, в зависимости от того, рассматривается ли это значение как строка или как число...
Поскольку булев (логический) контекст является безразличным контекстом, он не вызывает преобразования скаляров...



Соответственно значение "0" в булевом контексте будет false, а "00" и "000" - true. Из-за подобной забывчивости можно делать ошибки, аналогичные такой:

Код

my $value = $cgi->param('value'); # значение из формы
if ($value) {
    $result = 100 / $value;
}



--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
KSURi
Дата 3.6.2008, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 887
Регистрация: 8.6.2006
Где: Russia

Репутация: 20
Всего: 27



Поэтому я делаю
Код

my $value = $cgi->param('value') || undef;

Но кстати, стоит отметить, что CGI.pm возвращает '' (пустую строку), если параметр в запросе присутствует, но значение у него пустое. А вот если параметра в запросе вообще нет, то тогда вернет undef


--------------------
Died at Life.pl line 21
PM Jabber   Вверх
tolkien
Дата 4.6.2008, 06:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 277
Регистрация: 5.4.2008

Репутация: 4
Всего: 4



Все книги по CGI пестрят рекомендациями о необходимости фильтрации входных данных. В указанном выше примере как раз это не сделанно. 
PM MAIL   Вверх
ginnie
Дата 4.6.2008, 08:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



Уважаемый KSURi, я как раз об этом и написал, что не сразу видно проблему.

Код

my $test = '00';
warn($test || '1');


этот код вернет 00, т.к. он true в булевом контексте


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
Bulat
Дата 4.6.2008, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



Вопрос конечно интересный, и легко ошибиться, только вот интуиция всегда подсказывает, что 0 - это ноль, а "000" - не совсем понятно что, чисто с математической точки зрения. В математике нет такого 000, а значит 000 не равно(не тождественно равно, если угодно) 0, но false только в случае когда 0, и значит вероятнее всего что "000" даст true. Что на практике и оказывается так smile

Может немного сумбурно, но думаю все же понятно smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
ginnie
Дата 4.6.2008, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



Уважаемый Bulat, объяснение очень натянутое, т.к.

Код

my $test = '000';
warn($test == 0 ? 'equal' : 'not equal');


т.к. Perl считает, что "000" и 0 с математической точки зрения (т.е. при приведении к одному типу - числу) тождественно равны.


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
Bulat
Дата 4.6.2008, 09:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



Цитата(ginnie @  4.6.2008,  09:26 Найти цитируемый пост)
Уважаемый Bulat, объяснение очень натянутое, т.к.

Не согласен. 

Цитата(ginnie @  4.6.2008,  09:26 Найти цитируемый пост)
т.к. Perl считает, что "000" и 0 с математической точки зрения (т.е. при приведении к одному типу - числу) тождественно равны. 


Булевая проверка - это одно действие, а приведение к одному типу совсем иное. Разные операции выполняются над одним и тем же объектом, что есс-но может выдать два противоположных результата smile




--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
KSURi
Дата 4.6.2008, 09:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 887
Регистрация: 8.6.2006
Где: Russia

Репутация: 20
Всего: 27



ginnie, вот я видимо не сразу увидел, в чем вы обозначили проблему)
Ни разу просто не сталкивался с ситуацией, когда в параметре "000" передается

Это сообщение отредактировал(а) KSURi - 4.6.2008, 09:54


--------------------
Died at Life.pl line 21
PM Jabber   Вверх
ginnie
Дата 4.6.2008, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



Уважаемый Bulat, давайте пойдем от обратного: возьмем для примера число 0.0, которого, по аналогии с 000 тоже нет. С математической точки зрения, по Вашему алгоритму, оно должно, вероятнее всего, быть true. Но это не так (так-же, как и в случае с 000). True оно будет только если его представить в виде строки "0.0", но это уже не математика  smile Это Perl, где кроме как запомнить, что false в булевом контексте дают только строки "" и "0" других способов я не вижу.


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
Bulat
Дата 4.6.2008, 10:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



ginnie, 0.0 - не являетс переменной типа int smile double - в яве(я этот язык довольно не плохо знаю).

А булевы функции не стоит отождествлять с перлом smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
ginnie
Дата 4.6.2008, 11:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



Уважаемый Bulat, при чем тут int и double? В булевом контексте числа 0, 0.0, 0.00, 00, 000 имеют значение false.

Цитата

А булевы функции не стоит отождествлять с перлом

Мы обсуждаем не булевы функции, а булев контекст. Причем именно применительно к Perl. О каком отождествлении идет речь?


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
Bulat
Дата 4.6.2008, 11:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



ginnie, Булева функция

Мне хотелось бы посмотреть, где  в булевой функции или алгебре вы видели числа 0.0, 000, 0.00 и т.п. smile Там есть только 1 и 0. Да, perl при использовании булевской функции итерпретирует 0.0, 000 и т.п. с 0, НО интерпретирует, а не тождественно равно. 0.0, 000, 0.00 - это совершенно разные числа, не тождественно равные 0. Что наглядно демонстрируется в иных языках, где нужно явно указывать типа любой перемнной, поэтому есть типы int, string, double. Не нужно забывать, что и при 000 и при 0.0 происходит приведение типов, т.е. меняются свойства объекта, а значит уже должен быть повод усомнится в том, будет ли возвращено false, даже если после приведения типов получается 0 smile

Добавлено через 7 минут и 52 секунды
Код

my $a = 0.0;

unless ($a) {
  print $a, "\n";
}


Код

my $a = '000';

if ($a) {
  print $a, "\n";
}


Код

my $a = 0;

unless ($a) {
  print $a, "\n";
}


Обрати внимание что выводится как $a  в каждом из трех примеров. smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
ginnie
Дата 4.6.2008, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



Bulat, спасибо за ссылку, но булевы функции к нашему разговору отношения не имеют. Мы обсуждаем какие значения Perl интерпретирует как true, а какие - false. 
Извините за нескромный вопрос: какой, по Вашему мнению, критерий тождественного равенства двух чисел в конкретном языке программирования? И почему 000 тождественно не равно 0?


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
Bulat
Дата 4.6.2008, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



ginnie, Если начинать размышления не отталкиваясь от перла, а именно от булевских функций, то ошибится сложнее.

В перле нет деления на типы перемнных, есть скаляры. Но в булевом контексте "000" будет интерпретироватся не как числовой тип, а как строковой тип. Поэтому в перл "000" не тождественно равно "0". А что касается других языков, там-то как раз все проще, потому как и "0" числового типа и "000" числового типа действительно тождественно равны, потому что они оба числовые типы(int). Вся суть лишь в том, как интепретирует перл тот или иной скаляр в булевом контексте. Собственно основным критерием как раз и является тип перемнной, в случае с перлом - скаляра. И даже, что касается "0.0", как видно из выше мною приведенных примеров, в булевом контексте опять же "0.0" (тип double) предварительно приводится к типу (int), что подверждает последующий print , где на выходе уже не "0.0", а "0".smile

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

Добавлено через 5 минут и 32 секунды
Проще говоря, в языках где нужно явно указывать тип перемнной, можно присвоить перемнной типа int значение "01", но язык это приведет к виду "1" без 0 идущим перед 1.

Перл же посчитает такой скаляр как строковой, потому как ну не существует просто в математике такого числа 01, есть 1. smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
nitr
Дата 4.6.2008, 12:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



Цитата(Bulat @  4.6.2008,  11:58 Найти цитируемый пост)
где на выходе уже не "0.0", а "0".smile
Bulat, как-то странно ;)
Код

#!perl
print "0.0";

Цитата
0.0





--------------------
PM   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0622 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.