2015-04-16 3 views
3

У меня есть переменная «name», значение которой является именем другой переменной. Так, например:Racket: получить значение переменной, имя которой хранится в другой переменной

(define name 'a) 
(define a 1) 

я тогда хочу сделать что-то вроде этого:

(set! ,name 10) 

Но это приводит к ошибке, так что я хотел бы, что «имя» заменяется на это значение (т. е. 'a). Таким образом, приведенный выше код устанавливает значение переменной «a» равным 10 и что переменная «name» остается неизменной.

Я знаю, что могу сделать это так:

(eval `(set! ,name 10)) 

Но это работает только если переменная, содержащаяся в «имя» является глобальной переменной, которая не так в моей программе.

В настоящее время я решил проблему, представив новое пространство имен, но это делает код немного уродливым, поэтому я бы избегал использования eval (и, следовательно, также не вводил новое пространство имен).

Если я не ошибаюсь в C++, это будет сделано путем разыменования дескриптора (указатель на указатель).

ответ

3

Причина, по которой (eval `(set! ,name 10)) не работает, заключается в том, что имена локальных переменных отсутствуют во время выполнения. Локальные переменные хранятся в стеке, поэтому ссылки и присваивание локальным переменным скомпилированы для «получения значения в переменной i'th (подсчитанной с вершины стека)» и «сохранить это значение в i-м слоте на стек ".

Однако переменные уровня модуля хранятся в пространстве имен, поэтому вы можете использовать решение eval для них.

А что делать с локальными переменными? Вероятно, было бы лучше использовать хэш-таблицу, вместо этого, но если вы действительно нужно, сделать что-то вроде этого:

(define (set-local-variable name val) 
    (match name 
    ['a (set! a val)] 
    ['b (set! b val)] 
    ...)) 

где а, Ь, ... являются локальными переменными. Разумеется, вам необходимо поместить определение в область рассматриваемых локальных переменных. Это также подразумевает, что вам нужно определить set-local-variable для каждой области.

Это быстро становится болью для поддержания, поэтому ищите альтернативное решение - например, одно из основанных на хэш-таблицах.

+0

Да, но на самом деле это не то, что я хочу. Моя программа работает на моем компьютере, а другая часть работает на чипе. Я поддерживаю «мир» на своем компьютере, поэтому я могу легко попросить его обновить. При этом я отправляю только данные, которые были изменены через TCP/IP, и после обновления мне больше не нужно отправлять сообщения TCP/IP. Так что на моем компьютере я получаю, например, «(скорость 5). Знание переменной имеет одно и то же имя на моем компьютере. Я не хочу проверять каждое возможное имя переменной. Я просто хочу сделать: (set! ReceivedName receivedValue). Вместо большой условной проверки для каждого возможного имени переменной. – HyperZ

+0

Вот почему я рекомендую вместо этого использовать хеш-таблицу. (Я говорю, что невозможно сделать решение на основе eval). – soegaard

+0

Извините, если я вас неправильно понял. Но я не понимаю, как это сделать с хэш-таблицей. – HyperZ

Смежные вопросы