Dynamic variable names

From Rosetta Code

Jump to: navigation, search
Task
Dynamic variable names
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

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| or F\o\o. intern does 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
Personal tools
Support