Dynamic variable names
From Rosetta Code
You are encouraged to solve this task according to the task description, using any language you may know.
Create a variable with a user-defined name. The variable name should not be written in the program text, but should be taken from the user dynamically.
[edit] See also
- Eval in environment is a similar task.
Contents |
[edit] AutoHotkey
InputBox, Dynamic, Variable Name
%Dynamic% = hello
ListVars
MsgBox % %dynamic% ; says hello
[edit] BASIC
Works with: Beta BASIC version 3.0, Works with: SAM BASIC
10 INPUT "Enter a variable name", v$ 20 KEYIN "LET "+v$+"=42"
[edit] Common Lisp
In Common Lisp, symbol objects name variables; symbols are produced from strings by way of read (general syntax) or intern (specificially retrieving or making a symbol).
Symbols are grouped into packages — roughly namespaces — and any time symbols are created at runtime it is usually good to explicitly specify what package they are created in, outside of user/developer tools for working from the REPL (interactive mode) where the current package *package* is appropriate.
Within the standard, every variable is either lexical or special (dynamic scope). There is no global lexical environment, so in order to "create a variable", we must either create our own mechanism to remember it for lexical binding in a later evaluation, or create a special variable. It is unspecified what happens when a symbol not lexically bound or declared special is used as a variable.
Every symbol has a value slot — a field which, roughly, contains its current value considered as a special variable.
Therefore, there are two parts to dynamically creating a variable: we must declare it special, and give it a value. The first part is accomplished by the proclaim function for making declarations at run-time. The second part is simply assigning to the value slot.
(defun rc-create-variable (name initial-value)
"Create a global variable whose name is NAME in the current package and which is bound to INITIAL-VALUE."
(let ((symbol (intern name)))
(proclaim `(special ,symbol))
(setf (symbol-value symbol) initial-value)
symbol))
CL-USER> (rc-create-variable "GREETING" "hello")
GREETING
CL-USER> (print greeting)
"hello"
Things to note:
- Once a symbol has been declared special, it cannot be used as a lexical variable. Because of this potentially-surprising behavior, it is conventional to give all symbols naming special variables distinguished names, typically by asterisks as in
*greeting*, so that lexical variables will not accidentally be given those names.
- Some implementations do, to some extent, support global non-special variables; in these, because of the preceding problem, it is better to simply set the value slot and not proclaim it special. However, this may provoke undefined-variable warnings since the compiler or interpreter has no information with which to know the symbol is intended to be a variable.
- Common Lisp, by default, is case-insensitive; however it accomplishes this by canonicalizing read input to uppercase; there is syntax to denote a lower or mixed-case symbol name,
|Foo|orF\o\o.interndoes not go through the input path (reader), so we must provide the name in uppercase to make an "ordinary" variable name.
[edit] E
In E, there are no global variables, and there is no modification of the local (lexical) environment. However, it is possible to construct a program which binds any given variable name.
def makeNounExpr := <elang:evm.makeNounExpr>
def dynVarName(name) {
def variable := makeNounExpr(null, name, null)
return e`{
def a := 1
def b := 2
def c := 3
{
def $variable := "BOO!"
[a, b, c]
}
}`.eval(safeScope)
}
? dynVarName("foo")
# value: [1, 2, 3]
? dynVarName("b")
# value: [1, "BOO!", 3]
? dynVarName("c")
# value: [1, 2, "BOO!"]
It is also possible to capture the environment object resulting from the evaluation of the constructed program and use it later; this is done by bindX in Eval in environment#E (except for the program being constant, which is independent).
[edit] Forth
s" VARIABLE " pad swap move
." Variable name: " pad 9 + 80 accept
pad swap 9 + evaluate
Of course, it is easier for the user to simply type VARIABLE name at the Forth console.
[edit] Genyris
The intern function creates a symbol from an arbitrary string. Defvar creates a binding. Weird symbols are quoted with pipe characters.defvar (intern 'This is not a pipe.') 42
define |<weird>| 2009
[edit] Haskell
data Var a = Var String a deriving Show
main = do
putStrLn "please enter you variable name"
vName <- getLine
let var = Var vName 42
putStrLn $ "this is your variable: " ++ show var
[edit] Icon and Unicon
[edit] Icon
procedure main(arglist)
if *arglist = 0 then stop("Provide the names of variables in the argument list")
&dump := 1 # dump program state information and variables after run
every variable(!arglist) := 1 # set each user specified variable name in arglist to 1
end
[edit] Unicon
This Icon solution works in Unicon. Note: that unicon extends variable to allow access to variables in other co-expressions and in calling procedures
[edit] J
require 'misc'
(prompt 'Enter variable name: ')=: 0
Or, if the name had been defined in the variable 'userDefined'
(userDefined)=: 0
[edit] JavaScript
var varname = 'foo'; // pretend a user input that
var value = 42;
eval('var ' + varname + '=' + value);
[edit] Lua
_G[io.read()] = 5 --puts 5 in a global variable named by the user
[edit] Logo
? make readword readword
julie
12
? show :julie
12
[edit] M4
Enter foo, please.
define(`inp',esyscmd(`echoinp'))
define(`trim',substr(inp,0,decr(len(inp))))
define(trim,42)
foo
DOS batch file echoinp.bat:
@echo off set /p Input= echo %Input%
[edit] MUMPS
This is done in immediate mode so you can see the variable is created, although you will have to reference it through the indirection operator, "@".
USER>KILL ;Clean up workspace USER>WRITE ;show all variables and definitions USER>READ "Enter a variable name: ",A Enter a variable name: GIBBERISH USER>SET @A=3.14159 USER>WRITE A="GIBBERISH" GIBBERISH=3.14159
[edit] Octave
varname = input ("Enter variable name: ", "s");
value = input ("Enter value: ", "s");
eval([varname " = " value]);
[edit] Perl
print "Enter a variable name: ";
$varname = <STDIN>; # type in "foo" on standard input
chomp($varname);
$$varname = 42; # when you try to dereference a string, it will be
# treated as a "symbolic reference", where they
# take the string as the name of the variable
print "$foo\n"; # prints "42"
If you are operating in a strict environment, this isn't possible. You need to use 'eval' in this case
use strict;
print "Enter a variable name: ";
my $foo;
my $varname = <STDIN>; # type in "foo" on standard input
chomp($varname);
my $varref = eval('\$' . $varname);
$$varref = 42;
print "$foo\n"; # prints "42"
[edit] PHP
<?php
$varname = rtrim(fgets(STDIN)); # type in "foo" on standard input
$$varname = 42;
echo "$foo\n"; # prints "42"
?>
[edit] PicoLisp
(de userVariable ()
(prin "Enter a variable name: ")
(let Var (line T) # Read transient symbol
(prin "Enter a value: ")
(set Var (read)) # Set symbol's value
(println 'Variable Var 'Value (val Var)) ) ) # Print them
Output:
Enter a variable name: Tom Enter a value: 42 Variable "Tom" Value 42 -> 42
[edit] PowerShell
$variableName = Read-Host
New-Variable $variableName 'Foo'
Get-Variable $variableName
[edit] Python
Works with: Python version 2.x
>>> n = raw_input("Enter a variable name: ")
Enter a variable name: X
>>> exec n + " = 42"
>>> X
42
Works with: Python version 3.x
>>> n = input("Enter a variable name: ")
Enter a variable name: X
>>> exec(n + " = 42")
>>> X
42
Note: most of the time when people ask how to do this on newsgroups and other forums, on investigation, it is found that a neater solution is to map name to value in a dictionary.
[edit] R
# Read the name in from a command prompt
varname <- readline("Please name your variable >")
# Make sure the name is valid for a variable
varname <- make.names(varname)
message(paste("The variable being assigned is '", varname, "'"))
# Assign the variable (with value 42) into the user workspace (global environment)
assign(varname, 42)
#Check that the value has been assigned ok
ls(pattern=varname)
get(varname)
[edit] REBOL
rebol [
Title: "Dynamic Variable Name"
Author: oofoe
Date: 2009-12-28
URL: http://rosettacode.org/wiki/Dynamic_variable_names
]
; Here, I ask the user for a name, then convert it to a word and
; assign the value "Hello!" to it. To read this phrase, realize that
; REBOL collects terms from right to left, so "Hello!" is stored for
; future use, then the prompt string "Variable name? " is used as the
; argument to ask (prompts user for input). The result of ask is
; converted to a word so it can be an identifier, then the 'set' word
; accepts the new word and the string ("Hello!") to be assigned.
set to-word ask "Variable name? " "Hello!"
Session output:
Variable name? glister == "Hello!" >> glister == "Hello!"
[edit] Ruby
p "Enter a variable name"
x = gets.chomp!
instance_variable_set "@" + x, 42
p "The value of #{x} is #{instance_variable_get "@" + x}"
Example output:
"Enter a variable name" hello "The value of hello is 42"
[edit] Scheme
=> (define (create-variable name initial-val)
(eval `(define ,name ,initial-val) (interaction-environment)))
=> (create-variable (read) 50)
<hello
=> hello
50
[edit] Slate
Slate symbols are objects that name methods and slots. "Variable definition" is like defining a method which holds the value of a slot, and "variable access" is just method-call to get that value back.
define: #name -> (query: 'Enter a variable name: ') intern. "X"
define: name -> 42.
X print.
[edit] SNOBOL4
Indirect string reference of variables is a basic feature of Snobol, using the $ operator. trim( ) is needed for Snobol4+.
* # Get var name from user
output = 'Enter variable name:'
invar = trim(input)
* # Get value from user, assign
output = 'Enter value:'
$invar = trim(input)
* Display
output = invar ' == ' $invar
end
Output:
Enter variable name: pi Enter value: 3.14159 pi == 3.14159
[edit] Tcl
puts "Enter a variable name:"
gets stdin varname
set $varname 42
puts "I have set variable $varname to [set $varname]"
Note that it is more normal to use the user's name to index into a Tcl associative array, as the syntax gets easier to work with in that case:
puts -nonewline "Enter an element name: "; flush stdout
gets stdin elemname
set ary($elemname) [expr int(rand()*100)]
puts "I have set element $elemname to $ary($elemname)"
[edit] TI-89 BASIC
Local varName,value
InputStr "Variable name", varName
Prompt value
value → #varName
[edit] Zsh
read name
typeset $name=42

