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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 28.05.2007, 13:44   #1  
Андре is offline
Андре
Moderator
Сотрудники компании GMCS
 
2,375 / 464 (20) +++++++
Регистрация: 03.12.2001
ContainerIterator
Мелочь, а приятно.

Код, который ранее выглядел так:

X++:
static void test(Args _args)
{
    container   con = [1, 12.5, 'test', 2, 3, 'tetst'];
    int         i;
    ;
    for (i=1; i<=conlen(con); i++)
                info(conpeek(con, i));
}
можно записать так:

X++:
static void test4(Args _args)
{
    container               con = [1, 12.5, 'test', 2, 3, 'tetst'];
    gm_containerIterator    iterator = new gm_ContainerIterator(con);
    ;
    while(iterator.more())
    {
        info(iterator.value());
        iterator.next();
    }
}
Вложения
Тип файла: xpo gm_containerIterator.xpo (1.7 Кб, 631 просмотров)
За это сообщение автора поблагодарили: Gustav (6).
Старый 28.05.2007, 14:07   #2  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Итератор мастдай, енумератор - форева.

X++:
while(enumerator.moveNext())
        info(enumerator.current());
Старый 28.05.2007, 14:09   #3  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
mfp и соавторы рекомендуют пользоваться энумераторами потому, что:
  • нельзя забыть позвать некст
  • нельзя (ну правда в этом случае не важно, но лучше безобразно, но единообразно, как говорил подполковник Схаба) создать энумератор на другом звене нежели енумерируемое.
Старый 28.05.2007, 14:28   #4  
Андре is offline
Андре
Moderator
Сотрудники компании GMCS
 
2,375 / 464 (20) +++++++
Регистрация: 03.12.2001
Цитата:
Итератор мастдай, енумератор - форева.
Вопрос привычки. Сделать enumerator - еще 5 минут

Цитата:
mfp и соавторы рекомендуют пользоваться энумераторами потому, что:
А кто это?

Цитата:
нельзя забыть позвать некст
После while() автоматом пишу next().

Меня гораздо больше расстраивает отсутсвие возможности перебрать элеименты любой "коллекции" посредством for each ... in ...
Старый 28.05.2007, 14:35   #5  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от Андре Посмотреть сообщение
А кто это?
авторы Inside Microsoft Dynamics(TM) AX 4.0

Цитата:
Меня гораздо больше расстраивает отсутсвие возможности перебрать элеименты любой "коллекции" посредством for each ... in ...
или так:
Код:
[1, 2, 3, 4].each{ x | info(int2str(x));}
Старый 28.05.2007, 15:29   #6  
Deep Dreamer is offline
Deep Dreamer
Участник
 
76 / 24 (1) +++
Регистрация: 05.03.2004
Адрес: Москва
Цитата:
или так:
Код:
[1, 2, 3, 4].each{ x | info(int2str(x));}
Браво!
__________________
Бесполезно говорить: «Мы делаем все, что можем». Надо сделать то, что необходимо.
Старый 29.05.2007, 08:48   #7  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
C не причем, с натяжкой - С++
Старый 29.05.2007, 17:18   #8  
Андре is offline
Андре
Moderator
Сотрудники компании GMCS
 
2,375 / 464 (20) +++++++
Регистрация: 03.12.2001
Кстати, классический аксаптовский enumerator как раз и не получается, ибо он не предусматривает публичного контейнера и пораждается исключительно методом коллекции getEnumerator(), коего контейнер, естественно, не предоставляет.
Старый 29.05.2007, 17:36   #9  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Для пуристов сожно сделать так:
X++:
class ContainerCollection
{  
    container contents;
    Enumerator getEnumerator();
}
Старый 29.05.2007, 17:49   #10  
Андре is offline
Андре
Moderator
Сотрудники компании GMCS
 
2,375 / 464 (20) +++++++
Регистрация: 03.12.2001
А ContainerCollection инициализировать через new() конейнером? Фи... То еще решение....
Хотя.... Можно релизовать методы insert(), delete(), pop(), push() как обертки на conpeek(), conpoke() (которые я постоянно путаю) и получить неплохой класс
Старый 31.05.2007, 10:55   #11  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Еще два энумератора:
*для выбранных строк датасурса
*для файлов в папке
Вложения
Тип файла: zip Sys_FormDataSourceSelectionEnumerator.zip (750 байт, 199 просмотров)
Тип файла: zip SYS_FileEnumerator.zip (919 байт, 195 просмотров)
Старый 31.05.2007, 12:04   #12  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от belugin Посмотреть сообщение
Еще два энумератора
А можно ли попросить написать краткую статью для недогадливых (типа меня) чем отличается енумератор от итератора и зачем они нужны?
__________________
полезное на axForum, github, vk, coub.
Старый 31.05.2007, 13:23   #13  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от mazzy Посмотреть сообщение
А можно ли попросить написать краткую статью ... чем отличается енумератор от итератора и зачем они нужны?
Ее уже написали mfp сотоварищи

With reference to:
Inside Microsoft Dynamics™ AX 4.0 \Chapter 15. System Classes \The Collection Classes \Traversal


Traversal

You can traverse your collections by using either an enumerator or an iterator. When the collection classes were first introduced in Dynamics AX, the iterator was the only option. But because of a few obscure drawbacks that appear as hard-to-find errors, enumerators were added, and iterators were kept for backward compatibility. To highlight the subtle differences, the following code shows how to traverse a collection with both approaches.

X++:
List list = new List(Types::Integer);
ListIterator iterator;
ListEnumerator enumerator;
;
//Populate list.
...

//Traverse using an iterator.
iterator = new ListIterator(list);
while (iterator.more())
{
    print iterator.value();
    iterator.next();
}

//Traverse using an enumerator.
enumerator = list.getEnumerator();
while (enumerator.moveNext())
{
    print enumerator.current();
}

The first difference is the way in which the iterator and enumerator instances are created. For the iterator, you call new, and for the enumerator, you get an instance from the collection class by calling the getEnumerator method. In most cases, both approaches will work equally well. However, when the collection class resides on the opposite tier from the tier on which it is traversed, the situation is quite different. For example, if the collection resides on the client tier and is traversed on the server tier, the iterator approach fails because the iterator does not support cross-tier referencing. The enumerator does not support cross-tier referencing either, but it doesn't have to because it is instantiated on the same tier as the collection class. Traversing on the server tier using the client tier enumerator is quite network intensive, but the result is logically correct. Because some code is marked as Called From, meaning that it can run on either tier, depending on where it is called from, you could have broken logic if you use iterators, even if you test one execution path. In many cases, hard-to-track bugs such as this surface only when an operation is executed in batch mode.

NOTE: In earlier versions of Dynamics AX, this problem was even more pronounced because development and testing sometimes took place in two-tier environments, and this issue surfaces only in three-tier environments.

The second difference between iterators and enumerators is the way in which the traversing pointer moves forward. In the iterator approach, you must explicitly call both more and next; in the enumerator approach, the moveNext method handles these needs. Most developers have inadvertently implemented an endless loop at least once, simply because they forgot to move a pointer. This is not a significant problem, but it does cause an annoying interruption during the development phase.

If you always use the enumerator, you will not encounter either of the preceding issues. The only situation in which you cannot avoid using the iterator is when you must remove elements from a List collection. The following code shows how this is accomplished.

X++:
List list = new List(Types::Integer);
ListIterator iterator;
;
list.addEnd(100);
list.addEnd(200);
list.addEnd(300);

iterator = new ListIterator(list);
while (iterator.more())
{
    if (iterator.value() == 200)
        iterator.delete();
    iterator.next();
}
print list.toString(); //{100, 300}
pause;
P.S. Перевод Гугла
За это сообщение автора поблагодарили: MikeR (2).
Старый 31.05.2007, 13:38   #14  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Я, кстати, в одной модификашке, чтобы не использовать итераторы (пообащлся на досуге с Максимом) удалял элементы из объекта класса List не чере итераторы, а через контейнеры (преобразование в контейнер, и изменение его содержимого с последующей инициализацей объекта класса List). Кстати, подход заслуживает внимания, так как дает приемущество в скорости удаления.
Старый 31.05.2007, 13:54   #15  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Gustav Посмотреть сообщение
Интересный сервис...
А может сделать нормальный перевод?

Т.е. главных проблем две:
1. передача данных между клиентом и сервером
2. удаление элементов в энумераторе?
__________________
полезное на axForum, github, vk, coub.
Старый 31.05.2007, 13:55   #16  
MikeR is offline
MikeR
MCT
Аватар для MikeR
MCBMSS
Лучший по профессии 2015
Лучший по профессии 2014
 
1,628 / 627 (24) +++++++
Регистрация: 28.11.2005
Адрес: просто землянин
Попробую внести свою лепту. Вот вкратце отличия
1 для того чтоб пользовать iterator его надо инициализить через new() а для enumerator этого не требуется, он использует текущую сущность
2 iterator плохо переносит клиент - серверные пересылы, впрочем как и enumerator но последнему не нужно инициализиться. Поэтому если пользовать iterator могут возникнуть проблемы.
3 это перебор значений в iterator и enumerator. Для enumerator достаточно moveNext() и пойдет перебор а для iterator нужно переводить курсор iterator.next() а многие это пропускают и получается бесконечный цикл.
4 но чтобы удалить значение из списка вам не обойтись без iterator
Старый 31.05.2007, 13:56   #17  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Цитата:
Сообщение от mazzy
Т.е. главных проблем две:
Еще необходимость вызова next для iterator'ов.

Сам натыкался на бесконечные циклы из-за этого множество раз.
Лечится конечно легко и быстро, но раздражает изрядно.
Старый 13.02.2008, 17:00   #18  
Андре is offline
Андре
Moderator
Сотрудники компании GMCS
 
2,375 / 464 (20) +++++++
Регистрация: 03.12.2001
Кстати, если к containerEnumerator добавить один метод:
X++:
public container enumerate()
{
    return [idx, conpeek(con, idx)];
}
то можно имитировать Python - ий enumerate():
X++:
items = ['a','b']
for i,thing in enumerate(items):
     print 'index',i,'contains',thing
То есть, вместо громоздкого:
X++:
int  idx;
;
while(enumerator.moveNext())
{
     idx++;
     value = enumerator.current();
}
писать изящное:
X++:
int  idx;
;
while(enumerator.moveNext())
{
     [idx, value] = enumerator.enumerate();
}
Вложения
Тип файла: xpo gm_containerEnumerator.xpo (1.5 Кб, 575 просмотров)
Старый 13.02.2008, 17:23   #19  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
"You put lipstick on a pig, it's still a pig"
Старый 18.06.2008, 18:36   #20  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
Цитата:
Сообщение от Gustav Посмотреть сообщение
The only situation in which you cannot avoid using the iterator is when you must remove elements from a List collection. The following code shows how this is accomplished.
X++:
List list = new List(Types::Integer);
ListIterator iterator;
;
list.addEnd(100);
list.addEnd(200);
list.addEnd(300);

iterator = new ListIterator(list);
while (iterator.more())
{
    if (iterator.value() == 200)
        iterator.delete();
    iterator.next();
}
print list.toString(); //{100, 300}
pause;
В коде логическая ошибка. Перед iterator.next() необходим else.
За это сообщение автора поблагодарили: Gustav (2).
Теги
enumerator, iterator, x++, контейнер, полезное

 


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

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

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