Dynamic variable names

From Rosetta Code

Jump to: navigation, search
Dynamic variable names is a programming task. Visitors like you are encouraged to solve it according to the task description, using any language they may happen to know.
Add to BlogMarksAdd to del.icio.usAdd to diggAdd to NewsvineAdd to redditAdd to Slashdot

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] 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] 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"

[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

irb(main):001:0> varname = gets
foo
=> "foo\n"
irb(main):002:0> varname.chomp!
=> "foo"
irb(main):003:0> eval "#{varname} = 42"
=> 42
irb(main):004:0> foo
=> 42
irb(main):005:0> puts "the value of #{varname} is #{eval varname}"
the value of foo is 42
=> nil

However, the dynamic variable is bound to the current context. Consider:

irb(main):006:0> def deref(v)
irb(main):007:1> eval v
irb(main):008:1> end
=> nil
irb(main):009:0> deref varname
NameError: undefined local variable or method `foo' for main:Object
from (irb):7:in `
deref'
from (irb):9:in `eval'

from (irb):7:in `deref'
from (irb):9
from :0

Ruby lets you pass around the context as an object though:

irb(main):010:0> binding
=> #<Binding:0x7ff7d954>
irb(main):011:0> def deref(v,b)
irb(main):012:1> eval v, b
irb(main):013:1> end
=> nil
irb(main):014:0> deref varname, binding
=> 42
irb(main):015:0> puts "the value of #{varname} is #{deref varname, binding}"
the value of foo is 42
=> nil


[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] 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
Personal tools
Google AdSense