2017-01-20 18 views
1

Задача состоит в том, чтобы заполнить глубину структуры макросом, где имена структурных компонентов схожи и могут быть построены простым циклом с индексом. Например, структура корня level1-level2-level3-level4Передача параметров макросу с контуром

Я хочу заполнить его со следующими вложенными макросов

DEFINE iterate_menges. 
do &4 times. 
    fill &1 &2 sy-index level4. 
enddo. 
END-OF-DEFINITION. 

DEFINE fill. 
cs_root-sheet&1-&2-level&3-&4 = 'some_value'. 
END-OF-DEFINITION. 

Но эта концепция не работает и sy-index рассматривается как текст. Ошибка

компонент cs_root-sheet1-level2- levelsy-индекс-level4 не найден

показан, однако числовые литералы работают замечательно.

Какой синтаксис следует использовать здесь?

ADDITION: вот пример фрагмента, который я нашел на SCN, и он отлично работает. Почему так?

DEFINE ADD_MAPPING. 
p_c = &1. 
CONDENSE p_c. 
CONCATENATE 'p_old' p_c INTO p_c. 
ASSIGN (p_c) TO <fs>. 
WRITE <fs>. 
END-OF-DEFINITION. 

DO 14 TIMES. 
ADD_MAPPING sy-index. 
ENDDO. 

P.S. Да, я знаю, что макросы являются неразрешимыми, небезопасными и полностью не должны использоваться, но меня интересует эта конкретная проблема, а не рекомендации по лучшей практике.

+0

PS: Я не вижу, что вы используете этот 5-й параметр (level4) в макросе 'fill' ... – Marius

ответ

0

Использование динамического программирования, изменить ваш fill макрос:

DATA l_field TYPE string. 
    FIELD-SYMBOLS <l_value> TYPE any. 
    DEFINE fill. 
    l_field = &3. 
    CONDENSE l_field. 
    CONCATENATE 'cs_root-sheet&1-&2-level' l_field '-&4' INTO l_field. 
    ASSIGN (l_field) TO <l_value>. 
    IF sy-subrc = 0. 
     <l_value> = 'some_value'. 
    ELSE. 
     " TODO: error handling? 
    ENDIF. 
    END-OF-DEFINITION. 

Это будет работать, хотя вы можете проверить sy-subrc после ASSIGN потому, что параметр является инвариантом (единственным известным во время выполнения) и таким образом, не будет возникать ошибки во время компиляции, как и у другого параметра.

Вы также можете добавить проверку времени компиляции для верхней границы вашего цикла DO, так как вы, таким образом, знаете максимальное значение sy-index.Для этого, вы можете добавить, не выполняющуюся ссылку в iterate_menges макро:

DEFINE iterate_menges. 
    IF 1 = 0. " compile-time boundary validation test 
     cs_root-sheet&1-&2-level&4-level4 = ''. 
    ENDIF. 
    DO &4 TIMES. 
    fill &1 &2 sy-index level4. 
    ENDDO. 
    END-OF-DEFINITION. 

Второй способ заключается в добавлении дела заявления. Это можно использовать, только если вы знаете, что в этой части всегда будет определенное количество полей (конечно, всегда должно быть хотя бы одно ...). Так что, если вы знаете, нижнюю границу вашего DO цикла, то вы можете написать следующее как оптимизация:

CASE &3. 
    WHEN 1. " set 1 
    WHEN 2. " set 2 
    WHEN 3. " set 3 
    " ... 

    WHEN OTHERS. 
     " dynamic set 
    ENDCASE. 

Поскольку динамический набор медленнее, оптимизируя жесткие петли всегда хорошая идея.

+1

Хорошо, это работает! Я немного скорректировал ваш фрагмент, так как * sy-index * - это третий параметр * fill * macro, а не 1-й. Кроме того, 'CONDENSE' следует применять к * l_field *, поскольку' ASSIGN' попадает в короткий дамп, если не обрезать лишнее пространство перед счетчиком циклов. – Suncatcher

+0

Спасибо, пропустил это! Мне пришлось делать слепое печатание, поскольку у меня не было типов исходной структуры, на которые вы ссылались. Также работала над проблемой параметра, которую я обнаружил в исходном сообщении. – Marius

1

Система выполняет именно то, что указано в documentation. К сожалению, в этом случае на английском переводе отсутствуют некоторые детали, в отличие от немецкого оригинального текста, что более важно, ИМХО. Использование макроса не является вызовом , это текстовая замена , которая происходит до компиляции. Параметры заменяются, не оцениваются - они не могут оцениваться, потому что в большинстве случаев это значение неизвестно во время компиляции, только во время выполнения. Чтобы сделать то, что вы хотите сделать, вам придется использовать методы динамического доступа, такие как ASSIGN COMPONENT ... OF ...

+0

Возможно, какое-то встроенное преобразование может быть проведено или что-то еще? Задача, которая требует однострочного макроса, должна быть переписана десятками строк, если мы используем динамический подход :) – Suncatcher

+0

BTW, как вы можете объяснить макрос из моего добавления к вопросу? – Suncatcher

+0

Просто гадать, но, возможно, этот фрагмент кода из SDN работает, потому что там нет вложенных макросов? – Jagger

-2

То, что вы пытаетесь сделать, невозможно, поскольку макросы известны только во время компиляции. Они не являются частью средств модуляции в ABAP.

Можно даже написать собственную версию Brainfuck. Посмотрите на следующий пример.

REPORT zzz. 

TYPES: BEGIN OF t1, 
     sheet1 TYPE c, 
     sheet2 TYPE c, 
     END OF t1. 

DATA: 
    cs_root TYPE t1. 

DEFINE test. 
    cs_root-sheet&1 = 'costam'. 
END-OF-DEFINITION. 

DEFINE brainfuck. 
    &4=>&1&3 &2. 
END-OF-DEFINITION. 

START-OF-SELECTION. 
    brainfuck IF_SYSTEM_UUID_STATIC~CREATE_UUID_X16) (CL_SYSTEM_UUID. 
    test sy-index. 

Отвечая на ваш комментарий по другому вопросу. Решение может выглядеть так.

REPORT zzz. 

TYPES: BEGIN OF t4, 
    level4 TYPE c, 
    END OF t4. 

TYPES: BEGIN OF t3, 
    level1 TYPE t4, 
    level2 TYPE t4, 
    END OF t3. 

TYPES: BEGIN OF t2, 
    level1 TYPE t3, 
    level2 TYPE t3, 
    END OF t2. 

TYPES: BEGIN OF t1, 
    sheet1 TYPE t2, 
    sheet2 TYPE t2, 
    END OF t1. 

CLASS lcl_test DEFINITION FINAL. 
    PUBLIC SECTION. 
    CLASS-METHODS: 
     test 
     IMPORTING 
      i_1 TYPE i 
      i_2 TYPE i 
      i_3 TYPE i 
     CHANGING 
      cs_root TYPE t1. 
ENDCLASS. 

CLASS lcl_test IMPLEMENTATION. 
    METHOD test. 
    ASSIGN COMPONENT |sheet{ i_1 }| OF STRUCTURE cs_root TO FIELD-SYMBOL(<fs_sheet>). 
    IF sy-subrc = 0. 
     ASSIGN COMPONENT |level{ i_2 }| OF STRUCTURE <fs_sheet> TO FIELD-SYMBOL(<fs_level1>). 
     IF sy-subrc = 0. 
     ASSIGN COMPONENT |level{ i_3 }| OF STRUCTURE <fs_level1> TO FIELD-SYMBOL(<fs_level2>). 
     IF sy-subrc = 0. 
      ASSIGN COMPONENT 'level4' OF STRUCTURE <fs_level2> TO FIELD-SYMBOL(<fs_level3>). 
      IF sy-subrc = 0. 
      <fs_level3> = 'some_value'. 
      ENDIF. 
     ENDIF. 
     ENDIF. 
    ENDIF. 
    ENDMETHOD. 
ENDCLASS. 

DEFINE test. 
    lcl_test=>test(
    EXPORTING 
     i_1 = &1 
     i_2 = &2 
     i_3 = &3 
    CHANGING 
     cs_root = &4 
). 
END-OF-DEFINITION. 

DATA: gs_root TYPE t1. 

START-OF-SELECTION. 
    DO 14 TIMES. 
    test 1 2 sy-index gs_root. 
    ENDDO. 
+0

Любые комментарии о причинах downvotes? – Jagger