Есть ли способ сделать ассоциативные массивы в REXX?

У меня есть некоторый код Perl (для анализа производительности), сначала разработанный под Linux, который теперь нужно перенести на мейнфрейм. Очевидно, REXX является предпочтительным языком сценариев на этой платформе, но этот сценарий Perl в значительной степени зависит от ассоциативных массивов (в основном массивов, где индекс представляет собой строку).

Есть ли способ, что в REXX? Как бы я закодировал что-то вроде:

$arr{"Pax"} = "Diablo";
$arr{"Bob"} = "Dylan";
print $arr{"Pax"} . "\n";
if (defined $arr{"no"}) {
        print "Yes\n";
} else {
        print "No\n";
}

person paxdiablo    schedule 04.11.2010    source источник
comment
+1 за вопрос REXX. Не думал о REXX со времен OS/2.   -  person ggutenberg    schedule 04.11.2010


Ответы (2)


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

/* REXX */
NAME = PAX
ARRAY.NAME = "DIABLO"
NAME = BOB
ARRAY.NAME = "DYLAN"
NAME = 'PAX'
SAY "ARRAY.PAX " IS ARRAY.NAME
NAME = 'BOB'
SAY "ARRAY.BOB " IS ARRAY.NAME
NAME = 'SANDY'
SAY "ARRAY.SANDY " IS ARRAY.NAME
IF ARRAY.NAME = "ARRAY.SANDY" THEN SAY "ARRAY.SANDY IS EMPTY"

Вышеупомянутый Rexx будет печатать

ARRAY.PAX  IS DIABLO
ARRAY.BOB  IS DYLAN
ARRAY.SANDY  IS ARRAY.SANDY
ARRAY.SANDY IS EMPTY

Они также могут быть составными, например, a.b.c. Переменная основы, если она пуста, вернет себя. Невозможно выполнить итерацию стебля, который не использует последовательные числа в качестве индекса, о котором я знаю.

Руководство IBM со ссылкой на базовые переменные

Perl доступен как дополнительная бесплатная функция для ZOS IBM Ported Инструменты для z/OS

person Deuian    schedule 04.11.2010

Я просто хочу добавить немного больше к ответу, данному Deuian. Я согласен, базовые переменные REXX - это ответ.

Простые переменные REXX по умолчанию имеют собственное имя. Например:

/* REXX */
SAY X

будет печатать «X», пока X не будет присвоено другое значение:

/* REXX */
X = 'A'
SAY X

напечатает «А».

Пока нет большого сюрприза. Стеблевые переменные немного отличаются. Головка стебля никогда не оценивается, оценивается только бит после начальной точки.

Проиллюстрировать:

/* REXX */                                                           
X. = 'empty'   /* all unassigned stem values take on this value */
A. = 'nil'
B = 'A'        /* simple variable B is assigned value A */                                                      
X = 'A'        /* simple variable X is assigned value A */                                                      
SAY X.A        /* prints: empty */                                 
X.A = 'hello'  /* Stem X. associates value of A with 'hello' */
SAY X.A        /* prints: hello */                                   
SAY X.B        /* prints: hello */                                   
SAY X.X        /* prints: hello */                                   

Обратите внимание, что имена стволов X и A не оцениваются, однако переменные X и A, стоящие после них, вычисляются. Некоторые люди находят это немного запутанным — подумайте об этом некоторое время, и это обретет смысл.

Версия REXX для Z/OS не предоставляет естественного способа перебора основной переменной. Самый простой способ сделать это — создать свой собственный индекс. Например:

/* REXX */
X. = ''
DO I = 1 TO 10
  J = RANDOM(100, 500) /* Random # 100..500 */
  X.INDEX = X.INDEX J  /* concatinate J's with 1 space between */
  X.J = 'was picked'   /* Associate 'was picked' with whatever J evalauates to */
  END

DO I = 1 TO WORDS(X.INDEX) /* Number of blank delimited 'words' */
  J = WORD(X.INDEX, I)     /* Extract 1 'word' at a time */
  SAY J X.J                /* Print 'word' and its associated value */
  END

Довольно тривиально, но иллюстрирует идею. Просто убедитесь, что INDEX (или любое другое имя, которое вы выберете) для хранения имен индексации никогда не всплывает как ассоциативное значение! Если это возможно, используйте другую переменную для хранения индекса.

Последняя точка. Обратите внимание, что каждый из моих примеров начинается с /* REXX */, возможно, вы обнаружите, что это должна быть первая строка ваших REXX-программ под Z/OS.

person NealB    schedule 04.11.2010
comment
В дополнение к вышесказанному, вы можете узнать, установлена ​​ли переменная или нет, с помощью функции Symbol(): X=1; Say Symbol('X') /* -> 'VAR' /; Say Symbol('Y') / -› 'LIT' (для 'буквального') */ - person Ross Patterson; 12.11.2010
comment
Я заметил, что все примеры написаны полностью заглавными буквами. Рекс в курсе дела. Вы должны помнить, что неинициализированные переменные используют свое имя в ВЕРХНЕМ РЕГИСТРЕ в качестве значения. Таким образом, x.a = 1 фактически устанавливает x.A в 1. Однако, если c='a', то x.c задает x.a полностью отдельный лист стебля от x.A. - person Wes Miller; 08.06.2012
comment
@Wes Оценка составных символов работает следующим образом: 1) Имя основы преобразуется в верхний регистр, но не оценивается. 2) Элементы хвоста (разделенные точками) складывают в верхний регистр, а затем оценивают как отдельные символы. 3) Свернутое имя основы плюс оцениваемые символы хвоста образуют новый символ. 4) Оценить новый символ как есть (не свернутый). Эта оценка дает значение составного символа. Продолжая ваш пример, где c = 'a' и символ a не назначен, составные символы: x.c, x.C, X.c и X.C оцениваются как одно и то же, аналогично, x.a, x.A, X.a и X.A также оцениваются одинаково, но разные вещи. - person NealB; 08.06.2012