Какие типы языков позволяют программно создавать имена переменных? - PullRequest
2 голосов
/ 04 марта 2011

Этот вопрос возникает исключительно из интеллектуального любопытства.

Просматривая раздел Python относительно часто, я видел ряд вопросов, похожих на this , где кто-то спрашивает о программном способе определения глобальных переменных. Некоторые из них знают о подводных камнях exec, другие нет.

Однако я недавно программировал в Stata, где распространено следующее:

local N = 100
local i = 1

foreach x of varlist x1 - x`N' {
    local `x' = `i' * `i'
    ++i 
}

На языке Stata создается локальный макрос с именем N, а N оценивается как 100. На каждой итерации цикла foreach значение от x1 до x100 присваивается локальный макрос x. Затем строка внутри цикла присваивает квадрат i расширению x, локальный макрос с тем же окончанием, что и i. То есть после этого цикла x4 расширяется до 4 ^ 2, а x88 расширяется до 88 ^ 2.

В Python способ сделать что-то похожее будет:

squares = {}

for x in range(1,101):
    squares[x] = x**2

Тогда squares[7] равно 7 ^ 2.

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

local r1 "regress"
local r2 "corr"

foreach r of varlist r1-r2 {
     ``r'' y x
}

Двойные отметки вокруг r расширяют этот макрос дважды, сначала до r1 / r2, затем до regress / corr, в результате чего выполняется линейная регрессия с y в качестве зависимого и x в качестве независимой переменной, а затем показывает корреляцию между y и x. Возможны и более сложные вещи.

Мой вопрос в основном: попадает ли stata в какую-то большую категорию языков, где присваивание / вычисление переменной принимает эту форму "макропредставления / расширения"? Бонусные баллы за любое объяснение того, почему язык должен быть сконструирован таким образом, и / или примеры подобных конструкций на других языках.

Ответы [ 4 ]

3 голосов
/ 04 марта 2011

(Извините, это «ответ», а не комментарий ... люди не оценивают мои ответы, поэтому у меня недостаточно баллов, чтобы комментировать вопрос.)

Во-первых,позвольте мне указать, что в Stata странно то, что она переводит макрос перед выполнением этой строки кода.Например:

Скажите, что вы печатаете.

local x3 = 20 
local y = 3 
display "I am `x`y'' years old"

Внутренне Stata собирается преобразовать локальные данные (от внутренней к внешней), а затем выполнить команду display.То есть Stata переведет команду

display "I am `x3' years old"

, затем

display "I am 20 years old"

, а затем , Stata фактически выполнит эту последнюю строку кода.Вы можете посмотреть все это, выполнив сначала эту команду: set trace on.

Есть небольшая разница.Скобки ` ' изменяют команду .Я думаю, что это на самом деле отличается от других языков программирования.В Stata часто можно что-то сделать с одной строкой кода, тогда как для других языков потребуются две строки кода (одна для «расширения» макроса; другая для выполнения строки кода).

Что полезно в этом, так это то, что Stata также может вычислять все виды выражений в скобках ` ' (при условии, что они возвращают число или строку ... например, ничего, что не возвращает матрицу)

display "I am `= 2011 - 1991' years old"
display "I am `= floor(uniform()*`x`y'')' years old"

Это очень полезно, когда вы привыкнете к нему.Макросы в Stata way делают вещи более чистыми, чем, например, в SAS.%let заявления SAS не так гибки.

Я также собирался указать на несколько ошибок.

(1) В этих примерах петля настроена неправильно.x1, x2, ... , x100 - макросы (локальные), а не переменные.Вы не можете сказать foreach x of varlist x1 - x100, потому что x1-x100 не является списком переменных.Если бы я пытался это сделать, я бы, вероятно, использовал:

local N = 100
forvalues i = 1/`N' {
    local x`i' = `i' * `i'
}

Та же ошибка сделана во втором примере.r1 и r2 не являются переменными.Вы можете сделать это:

local mycommands regress corr 
foreach r in `mycommands' {
     `r' y x
}

(хотя я на самом деле набрал бы эквивалент, foreach r of local mycommands { ... }, который, предположительно, выполняется быстрее).

(2) Во-вторых, ++i недопустимо.Вы, вероятно, хотели сказать local ++i.

3 голосов
/ 04 марта 2011

Вопрос в том, сколько там синтаксического сахара. На любом языке, достойном внимания, вы можете использовать структуру данных карты или словаря для создания имен переменных (ключей) во время выполнения с некоторым значением. Некоторые языки могут более прозрачно интегрировать это с обычными идентификаторами переменных, чем другие.

2 голосов
/ 04 марта 2011

Я не знаю, если это то, что вы ищете, но в PHP вы можете сделать:

for ($i=0; $i<10; $i++) {
    ${x.$i} = $i*$i;
}

print $x3; // prints 9
print $x4; // prints 16

Мне лично это очень неприятно.

1 голос
/ 04 марта 2011

Javascript является очевидным примером, хотя механизм похож на Python, а не на Stata.

for(var i = 0; i < 100; i++)
    this["var" + i] = i * i;

alert(var8); // 64
...