Вот если бы ещё динамически создавать переменные…

Вот если бы ещё динамически создавать переменные…
Да все так-же, через RTL Клариона!
1. Выделяем память под новую переменную.
Для этого лучше воспользоваться этими процедурами:

!   Выделяет память и инициализирует ее двоичными нулями
  RTL::NewMem(UNSIGNED _Size),ULONG,NAME('Cla$NewMemZ')
!   Выделяет память и инициализирует ее пробелами
  RTL::NewStr(UNSIGNED _Size),ULONG,NAME('Cla$NewMemB')

_Size — размер выделяемой памяти, определяешь сам по типу переменной.
Возвращает адрес выделенного блока памяти.

ВНИМАНИЕ!!!
Надо иметь в виду, что выделяемая память не регистрируется в RTL Клариона (напрямую берется у Виндового менеджера памяти). Поэтому эта память не будет освобождена автоматом после завершения программы. Для ее освобождения надо использовать:
RTL::FreeMem(ULONG _Addr),NAME(‘_free’)
_Addr — адрес блока памяти, полученный из предыдущих функций выделения
памяти.
Итак — память под новую переменную есть! Теперь:
2. Промежуточный этап — создание так называемой UFO-переменной. Что-то типа оболочки вокруг блока памяти, которая содержит всю необходимую информацию о перменной. Необходимо для правильной обработки новой переменной в RTL Клариона. Для этого воспользуемся такой вот функцией:

  RTL::Mem2UfoAddr(ULONG _VarAddr,BYTE _VarType,ULONG _DecFloat=0, |
                   UNSIGNED _VarSize,BYTE=0),ULONG,RAW,NAME('Cla$Mem2Ufo')

_VarAddr -  адрес блока памяти для новой переменной
_VarType -  тип создаваемой переменной
            Номера типов можно взять из INC-файла моей библиотеки
            DynaLib, фриварный вариант которой можно взять на:
            http://dynalIb.narod.ru
            Например: BYTE-1, LONG-6, DECIMAL-10, STRING-18
_DecFloat - Если создаем переменную типа DECIMAL/PDECIMAL,
            то здесь надо задать кол-во дробных разрядов.
            DECIMAL(9,2) - _DecFloat = 2
_VarSize  - размер новой переменной в байтах. Для переменных
            типа DECIMAL/PDECIMAL он составляет ~половину от
            общего кол-ва цифр.
            DECIMAL(9,2) - _VarSize = Int(9/2)+1 = 5
            С определением размеров других типов, думаю проблем
            не будет? Практически все это есть в доке.

Возвращает адрес созданной UFO-переменной. Если более понятно, то возвращает значение, которое, обычно, содержиться в переменных типа ANY. Ну, как и с памятью, в конце программы эти UFO-переменные надо-бы освободить, т.к. они отьедают виндовую память. И немаленькую! Для этого используем такую функцию:

  RTL::FreeUfo(ULONG _UFOAddr),RAW,NAME('Cla$FreeUfo')

_UFOAddr — адрес UFO-переменной, полученный из RTL::Mem2UfoAddr() Можно, кстати, остановиться уже на данном этапе, если получать от данной функции не адрес UFO-переменной, а сразу понятный всем ANY. Для этого запишем эту функцию так:

  RTL::Mem2Ufo(ULONG _VarAddr,BYTE _VarType,ULONG _DecFloat=0, |
               UNSIGNED _VarSize,BYTE=0),*?,RAW,NAME('Cla$Mem2Ufo')

Естественно, что освобождать такие UFO-оболочки надо уже по-другому:

Var1  ANY
...
Var1 = RTL::Mem2Ufo(....)       ! Создали UFO-переменную
...
Var1 &= Null                    ! "Убили" ее

Ну, и наконец:
3. Биндим новую переменную, что-бы с ней было удобно работать. Для этого воспользуемся еще одной RTL-функцией:

  RTL::Bind(ULONG _UFOAddr,STRING _Name),NAME('Cla$BindV')

_UFOAddr — адрес UFO-переменной, полученный из RTL::Mem2UfoAddr()
_Name    — строковое имя новой переменной
Обращаю внимание, что _Name имеет тип ОБЫЧНОЙ STRING, а не CSTRING! И, кстати, CLIP() делать не обязательно — эта функция сама обрежет конечные пробелы. И, опять-же, как и с памятью, в конце программы не надо забыть освободить память, занятую новым именем:

  RTL::UnBind(STRING _Name),NAME('Cla$UnbindV')

_Name — строковое имя освобождаемой переменной
Вот, пожалуй, и все!
Маленький примерчик. Так сказать — для усвоения темы:) Сразу предупреждаю — пример простейший и скелетный. Поэтому нет никаких проверок типа дублирования имен и пр. Предположим, есть очередь, в которой содержаться имена новых переменных, которые необходимо создать для дальнейшего использования:

  MAP
    MODULE('Clarion RTL')
      RTL::NewMem(UNSIGNED _Size),ULONG,NAME('Cla$NewMemZ')
      RTL::NewStr(UNSIGNED _Size),ULONG,NAME('Cla$NewMemB')
      RTL::FreeMem(ULONG _Addr),NAME('_free')
      RTL::Mem2UfoAddr(ULONG _VarAddr,BYTE _VarType,ULONG _DecFloat=0, |
                       UNSIGNED _VarSize,BYTE=0),ULONG,RAW,NAME('Cla$Mem2Ufo')
      RTL::FreeUfo(ULONG _UFOAddr),RAW,NAME('Cla$FreeUfo')
      RTL::Bind(ULONG _UFOAddr,STRING _Name),NAME('Cla$BindV')
      RTL::UnBind(STRING _Name),NAME('Cla$UnbindV')
      RTL::GetBindVar(STRING _cVarName),*?,RAW,NAME('Cla$EvaluateVariable')
    END
  END

Var1         ANY
sVar1        STRING(40)
Var2         ANY
sVar2        STRING(40)

VarNamesQue  QUEUE,PRE(VAR)
Name           STRING(40) ! Имя переменной
Type           LONG       ! Тип
Size           LONG       ! Размер
DecFloat       BYTE       ! Для DECIMAL/PDECIMAL
Addr           LONG       ! Здесь будет адрес блока памяти
UFOAddr        LONG       ! Здесь будет адрес UFO-оболочки для переменной
             END
!
! Последние два поля при создании очереди инициализируются нулями.
!

  CODE
  ...
  Loop Var# = 1 to Records(VarNameQue)
    Get(VarNameQue,Var#)
    if ~VAR:Name OR ~VAR:Type OR ~VAR:Size then Cycle.
    if VAR:Type = TYPE:STRING
       VAR:Addr = RTL::NewStr(VAR:Size)
    else
       VAR:Addr = RTL::NewMem(VAR:Size)
    .
    if ~VAR:Addr then Cycle.         ! Память не выделена
    VAR:UFOAddr = RTL::Mem2UfoAddr(VAR:Addr,VAR:Type,VAR:DecFloat,VAR:Size)
    if ~VAR:UFOAddr                  ! UFO-оболочка не создана
       RTL::FreeMem(VAR:Addr)
       Cycle
    .
    RTL::Bind(VAR:UFOAddr,VAR:Name)
    Put(VarNameQue)
  .

  Get(VarNameQue,1); sVar1 = VAR:Name
  Get(VarNameQue,2); sVar2 = VAR:Name
  Message(Evaluate(Clip(sVar1) &'+'& Clip(sVar2)))   ! Var1 + Var2

!   или

  Get(VarNameQue,1); Var1 &= RTL::GetBindVar(Clip(VAR:Name)&'<0>')
  Get(VarNameQue,2); Var2 &= RTL::GetBindVar(Clip(VAR:Name)&'<0>')
!   ВНИМАНИЕ!!! Если какая-либо переменная не найдена и ANY &= Null,
!               без проверки на Message() получим GPF.
  if ~(Var1 &= Null) AND ~(Var2 &= Null)
     Message(Var1 + Var2)                            ! Var1 + Var2
  .
Небольшое, но довольно важное дополнение к примеру.
В конце надо освобождать за собой занятую память:
  Loop Var# = 1 to Records(VarNameQue)
    Get(VarNameQue,Var#)
    if ~VAR:Addr then Cycle.
    RTL::FreeMem(VAR:Addr); Clear(VAR:Addr)
    if ~VAR:UFOAddr then Cycle.
    RTL::FreeUfo(VAR:UFOAddr); Clear(VAR:UFOAddr)
    RTL::UnBind(Clip(VAR:Name))
  .

Вообщем, вот в таком вот русле. Так что, как видишь , Кларион позволяет делать очень многое из того, что другим языкам и не снилось! Надо только уметь им пользоваться.
Еще-бы, правда, более дружественное отношение разработчиков к нам — простым трудягам, а не только к приближенным 3rdParty! Вообще-бы кайф был!