AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 15.04.2009, 11:20   #1  
cerbo is offline
cerbo
Участник
 
25 / 11 (1) +
Регистрация: 02.10.2008
! Будьте осторожны со сложными условиями
Неявное преобразование происходит не только из int в boolean, но и наоборот:
X++:
    int d= 10;
    boolean t= false;
    ;

    t= d == (5 || 10);  // false    
    t= d == (5 && 10);  // false
    d= t;               // 0
Проблема в том, что компилятор пропускает такое без звука в отличии от, например, C++ или C#. В сложном условии легко что-то не заметить и потом потратить очень много времени на отладку, как это произошло со мной . MSSQL ведет себя так же (про других врать не буду), а т.к. у нас один и тот же логический аппарат используется и во встроеных запросах и в простых расчетах, то может от сюда ноги ростут?

К стати первая строчка могла бы стать элегантной заменой этому:
X++:
    t= (d == 5 || d == 10); // true
__________________
Dynamics AX 4.0.2501.122 SP2, kernel 4.0.2163.0, MS SQL 2005
Старый 15.04.2009, 11:24   #2  
oip is offline
oip
Axapta
Лучший по профессии 2014
 
2,564 / 1416 (53) ++++++++
Регистрация: 28.11.2005
Записей в блоге: 1
Цитата:
Сообщение от cerbo Посмотреть сообщение
Неявное преобразование происходит не только из int в boolean, но и наоборот
Dev Guide.
Цитата:
Automatic conversions
Since the internal representation of booleans is integer, booleans are automatically converted into integers and reals.
Старый 15.04.2009, 11:38   #3  
cerbo is offline
cerbo
Участник
 
25 / 11 (1) +
Регистрация: 02.10.2008
Получается, опять баго-фича
__________________
Dynamics AX 4.0.2501.122 SP2, kernel 4.0.2163.0, MS SQL 2005
Старый 15.04.2009, 11:39   #4  
Sada is offline
Sada
Программатор
Аватар для Sada
 
1,450 / 153 (8) ++++++
Регистрация: 29.03.2005
Адрес: Толи Барнаул, толи Москва
Если говорить про элегантность кода, то достаточно объявить
boolean t;
и она по умолчанию будет false
И не забываем ставить пробелы в нужных местах
Старый 15.04.2009, 11:46   #5  
oip is offline
oip
Axapta
Лучший по профессии 2014
 
2,564 / 1416 (53) ++++++++
Регистрация: 28.11.2005
Записей в блоге: 1
Цитата:
Сообщение от cerbo Посмотреть сообщение
Получается, опять баго-фича
Может я чего не понимаю, но в чем бага?
Старый 15.04.2009, 12:22   #6  
DSPIC is offline
DSPIC
Боец
 
1,077 / 1243 (44) ++++++++
Регистрация: 11.04.2008
Условия
X++:
t= d == (5 || 10); // false
и
X++:
t= (d == 5 || d == 10); // true
Отличаются далеко не элегантностью, а принципиальностью. В обоих случаях сис-ма посчитала логически правильно. Разберите выражения внимательно.

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

X++:
if (d == 5 || d == 10)
 t = true;
Чуть длинее, за то понятнее.

Последний раз редактировалось DSPIC; 15.04.2009 в 12:27.
Старый 15.04.2009, 12:27   #7  
cerbo is offline
cerbo
Участник
 
25 / 11 (1) +
Регистрация: 02.10.2008
X++:
if(   (a==10)
   || (a==25)
   || (b != c)
   //  ... еше много похожих на эти строчки
   && (d < a) )
{
// ...
}
Такие штуки я назвал "сложными условиями".

Так вот в рабочем цейтноте можно сделать так:
X++:
if(   a== 10
   || (a==  (b != c
   //  ... еше много похожих на эти строчки
   && d < a) )
{
// ...
}
Но компилятор здесь промолчит.

Возьму свои слова обратно- на баго-фичу не тянет. Но про тонкость эту надо помнить.
__________________
Dynamics AX 4.0.2501.122 SP2, kernel 4.0.2163.0, MS SQL 2005
Старый 15.04.2009, 12:45   #8  
cerbo is offline
cerbo
Участник
 
25 / 11 (1) +
Регистрация: 02.10.2008
Цитата:
Сообщение от DSPIC Посмотреть сообщение
Условия
X++:
t= d == (5 || 10); // false
и
X++:
t= (d == 5 || d == 10); // true
Отличаются далеко не элегантностью, а принципиальностью. В обоих случаях сис-ма посчитала логически правильно. Разберите выражения внимательно.

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

X++:
if (d == 5 || d == 10)
 t = true;
Чуть длинее, за то понятнее.
Я думаю красота этого:
X++:
t= d == (5 || 10);
перевешивает приимущества неявных преобразований.

И назидательный тон ваш совсем не уместен, эти примеры я сам написал и поэтому хорошо знаю и понимаю что в них написано.
__________________
Dynamics AX 4.0.2501.122 SP2, kernel 4.0.2163.0, MS SQL 2005

Последний раз редактировалось cerbo; 15.04.2009 в 12:46. Причина: очепятка
Старый 15.04.2009, 13:00   #9  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от cerbo Посмотреть сообщение
Я думаю красота этого:
X++:
t= d == (5 || 10);
перевешивает приимущества неявных преобразований.

И назидательный тон ваш совсем не уместен, эти примеры я сам написал и поэтому хорошо знаю и понимаю что в них написано.
определитие семантику || и == которая будет поддерживать это?
Это какая-то PHP-красота

Лучше как в питогне

X++:
t = d in [5, 10]
Можно сделать функцию in типа:
X++:
boolean in(AnyType _value, container _container)
{
     return conFind(_container, _value) ? true : false;
}

t = in(d, [5, 10]);

А неявное преобразование сделано для проверки непутоты

X++:
if (table1.Qty1 ||  table1.Qty2)
{
     ....
}
else
{
   warning("No qty!!!")
}
Старый 15.04.2009, 13:04   #10  
plumbum is offline
plumbum
Участник
Соотечественники
 
182 / 86 (3) ++++
Регистрация: 07.12.2007
Адрес: Vienna, AT
Цитата:
Сообщение от cerbo Посмотреть сообщение
t= d == (5 || 10); // false
t= d == (5 && 10); // false
d= t; // 0

К стати первая строчка могла бы стать элегантной заменой этому:
X++:
    t= (d == 5 || d == 10); // true
Это совсем не одно и тоже:

t= d == (5 || 10); // false
Если учесть преобразования boolean в int, 5 = 0101 а 10 = 1010. Соответственно сложив младшие биты получим 1 - значение в скобках будет true, далее сравниеваем этот 1 (приведенный из true в int) с 10 и получаем конечно же false

во втором варианте происходит сравнение 2-х чисел int - конечно тут будет true, поскольку d == 10.

Важно что выражение в скобках вернет приведенный к boolean результат!
Если бы было так:
X++:
int c = 5 | 10;
тогда бы с было равно 15 - результат сразу идет в int.
И в С++ тоже так!
__________________
http://www.axdevposts.blogspot.com
Пришел, уведел.... отойди, дай другому увидеть!
Старый 15.04.2009, 13:11   #11  
leva is offline
leva
Участник
 
52 / 36 (2) +++
Регистрация: 03.08.2005
Да какая красота и элегантность?

Ну и какому числу должно быть равно булевское значение после преобразования в int? 1? 5? -1? "Элегантно" заглядывать в документацию каждый раз как встретишь (если это там вообще определено)? Надеятся, что в следующей версии компилятора эту "красоту" не испорятят?

Для справки:
1. В С и С++ нет булевского типа. Есть понятие "0 "и "не 0", со всеми вытекающими.
2. В Java такие трюки вообще запрещены. И правильно.

В одном вы правы - надо быть осторожней и НЕ использовать такие финты.
Старый 15.04.2009, 13:42   #12  
DSPIC is offline
DSPIC
Боец
 
1,077 / 1243 (44) ++++++++
Регистрация: 11.04.2008
Цитата:
Сообщение от cerbo Посмотреть сообщение
Я думаю красота этого:
X++:
t= d == (5 || 10);
перевешивает приимущества неявных преобразований.

И назидательный тон ваш совсем не уместен, эти примеры я сам написал и поэтому хорошо знаю и понимаю что в них написано.
Простите, больше не повторится.
Старый 15.04.2009, 14:06   #13  
cerbo is offline
cerbo
Участник
 
25 / 11 (1) +
Регистрация: 02.10.2008
Цитата:
Сообщение от belugin Посмотреть сообщение
А неявное преобразование сделано для проверки непутоты

X++:
if (table1.Qty1 ||  table1.Qty2)
{
     ....
}
else
{
   warning("No qty!!!")
}
А зачем тогда нужно из boolean в int?
__________________
Dynamics AX 4.0.2501.122 SP2, kernel 4.0.2163.0, MS SQL 2005
Старый 15.04.2009, 14:41   #14  
tourist is offline
tourist
Участник
 
21 / 14 (1) ++
Регистрация: 03.05.2006
Цитата:
Сообщение от cerbo Посмотреть сообщение
А зачем тогда нужно из boolean в int?
Например, чтобы присваивать значение выражения типа boolean полю с типом NoYes
Старый 15.04.2009, 15:11   #15  
leva is offline
leva
Участник
 
52 / 36 (2) +++
Регистрация: 03.08.2005
Цитата:
Сообщение от tourist Посмотреть сообщение
Например, чтобы присваивать значение выражения типа boolean полю с типом NoYes
Да. И мне кажется других реальных потребностей нет.

Соответсвенно в аксапте на самом деле true преобразовывается в 1, а false в 0. Поэтому собственно код автора выдавал false, ибо 10 не равно 1.

Лично я всё равно избегаю таких неявных преобразований ибо от лукавого
Старый 15.04.2009, 16:11   #16  
cerbo is offline
cerbo
Участник
 
25 / 11 (1) +
Регистрация: 02.10.2008
Цитата:
Сообщение от leva Посмотреть сообщение
Для справки:
1. В С и С++ нет булевского типа. Есть понятие "0 "и "не 0", со всеми вытекающими.
Для справки, в C++ есть тип bool
__________________
Dynamics AX 4.0.2501.122 SP2, kernel 4.0.2163.0, MS SQL 2005
Старый 15.04.2009, 16:21   #17  
oip is offline
oip
Axapta
Лучший по профессии 2014
 
2,564 / 1416 (53) ++++++++
Регистрация: 28.11.2005
Записей в блоге: 1
Цитата:
Сообщение от leva Посмотреть сообщение
И мне кажется других реальных потребностей нет.
Еще если, например, надо, чтобы из трех условий было выполнено два, то можно делать так:
X++:
if (((a>b) + (a>c) + (a>d)) == 2)
{
    ...
}
Старый 15.04.2009, 16:45   #18  
leva is offline
leva
Участник
 
52 / 36 (2) +++
Регистрация: 03.08.2005
Цитата:
Сообщение от cerbo Посмотреть сообщение
Для справки, в C++ есть тип bool
Точно, был не прав. В C++ есть, в C нет.

Цитата:
Сообщение от oip Посмотреть сообщение
Еще если, например, надо, чтобы из трех условий было выполнено два, то можно делать так:
Интересно. Хотя конечно поостерёгся бы по тем же причинам.


Кстати нашёл в wiki как boolean реализуется в разных языках.
Старый 15.04.2009, 17:35   #19  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
в принципе, автоконфертация AnyType -> bool полезна - оня является отражением соглашения про то что некоторые значения - null.

bool -> int, я думаю, вредна. Надо просто сделать bool отдельным типом от enum и сделать автоконыертацию строго для NoYes
Теги
неявное преобразование

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Будьте осторожны с RecordInsertList miklenew DAX: Программирование 6 20.05.2008 15:39
баг в 2.5. Будьте осторожнее с символом "_" подчеркивание levsha DAX: Программирование 5 07.12.2004 12:26
Заказы-склад комплектация AK-76 DAX: Функционал 2 05.11.2003 10:37
И еще раз о слоях PlasticinE DAX: Программирование 2 22.01.2002 22:44
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 02:33.