Dynamic variable names: Difference between revisions
m ({{omit from|GUISS}}) |
|||
Line 475: | Line 475: | ||
{{omit from|Fortran}} |
{{omit from|Fortran}} |
||
{{omit from|Go}} |
{{omit from|Go}} |
||
{{omit from|GUISS}} |
|||
{{omit from|Java}} |
{{omit from|Java}} |
||
{{omit from|Metafont}} |
{{omit from|Metafont}} |
Revision as of 20:24, 5 September 2011
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.
See also
- Eval in environment is a similar task.
AutoHotkey
<lang AutoHotkey>InputBox, Dynamic, Variable Name %Dynamic% = hello ListVars MsgBox % %dynamic% ; says hello</lang>
BASIC
,
10 INPUT "Enter a variable name", v$ 20 KEYIN "LET "+v$+"=42"
Batch File
@echo off setlocal enabledelayedexpansion echo Choose between those variables: echo. set a=0 echo A set b=1 echo B set c=2 echo C set mustard=4 echo MUSTARD echo. set /p choice=Which one ? : cls echo %%%choice%%%=!%choice%! endlocal pause exit
The whole thing is in the "setlocal enabledelayedexpansion"
CF: setlocal /?, cmd /? and set /?
BBC BASIC
<lang bbcbasic> INPUT "Enter a variable name: " name$
INPUT "Enter a numeric value: " numeric$ dummy% = EVAL("FNassign("+name$+","+numeric$+")") PRINT "Variable " name$ " now has the value "; EVAL(name$) END DEF FNassign(RETURN n, v) : n = v : = 0</lang>
Clojure
<lang clojure>(eval `(def ~(symbol (read)) 42))</lang>
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.
<lang lisp>(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))</lang>
<lang lisp>CL-USER> (rc-create-variable "GREETING" "hello") GREETING
CL-USER> (print greeting) "hello"</lang>
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
.intern
does not go through the input path (reader), so we must provide the name in uppercase to make an "ordinary" variable name.
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.
<lang e>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!"]</lang>
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).
Forth
<lang forth>s" VARIABLE " pad swap move ." Variable name: " pad 9 + 80 accept pad swap 9 + evaluate</lang> Of course, it is easier for the user to simply type VARIABLE name at the Forth console.
GAP
<lang gap># As is, will not work if val is a String Assign := function(var, val) Read(InputTextString(Concatenation(var, " := ", String(val), ";"))); end;</lang>
Genyris
The intern function creates a symbol from an arbitrary string. Defvar creates a binding. Weird symbols are quoted with pipe characters.<lang genyris>defvar (intern 'This is not a pipe.') 42 define |<weird>| 2009</lang>
Haskell
<lang 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</lang>
Icon and Unicon
<lang 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</lang> Note: that Unicon extends variable to allow access to variables in other co-expressions and in calling procedures
J
<lang j>require 'misc' (prompt 'Enter variable name: ')=: 0</lang>
For example: <lang j> require 'misc'
(prompt 'Enter variable name: ')=: 0
Enter variable name: FOO
FOO
0</lang>
Or, if the name had been defined in the variable 'userDefined'
<lang j>(userDefined)=: 0</lang>
JavaScript
<lang javascript>var varname = 'foo'; // pretend a user input that var value = 42; eval('var ' + varname + '=' + value);</lang>
Lua
<lang lua>_G[io.read()] = 5 --puts 5 in a global variable named by the user</lang>
Logo
<lang logo>? make readword readword julie 12 ? show :julie 12</lang>
M4
<lang M4>Enter foo, please. define(`inp',esyscmd(`echoinp')) define(`trim',substr(inp,0,decr(len(inp)))) define(trim,42) foo</lang>
DOS batch file echoinp.bat:
@echo off set /p Input= echo %Input%
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
Octave
<lang octave>varname = input ("Enter variable name: ", "s"); value = input ("Enter value: ", "s"); eval([varname,"=",value]);</lang>
PARI/GP
<lang parigp>eval(Str(input(), "=34"))</lang>
Perl
<lang 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"</lang>
If you are operating in a strict environment, this isn't possible. You need to use 'eval' in this case
<lang perl>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"</lang>
PHP
<lang php><?php $varname = rtrim(fgets(STDIN)); # type in "foo" on standard input $$varname = 42; echo "$foo\n"; # prints "42" ?></lang>
PicoLisp
<lang 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</lang>
Output:
Enter a variable name: Tom Enter a value: 42 Variable "Tom" Value 42 -> 42
PowerShell
<lang powershell>$variableName = Read-Host New-Variable $variableName 'Foo' Get-Variable $variableName</lang>
Python
<lang python>>>> n = raw_input("Enter a variable name: ") Enter a variable name: X >>> exec n + " = 42" >>> X 42</lang>
<lang python>>>> n = input("Enter a variable name: ") Enter a variable name: X >>> exec(n + " = 42") >>> X 42</lang>
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.
R
<lang 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)</lang>
REBOL
<lang 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!"</lang>
Session output:
Variable name? glister == "Hello!" >> glister == "Hello!"
Retro
<lang Retro>: newVariable: ( "- )
getToken header 0 , ;
newVariable: foo</lang>
Or:
<lang Retro>: newVariable: ( "- )
create 0 , ;
newVariable: foo</lang>
RLaB
In RLaB all the objects are located in a global list $$. To create a variable dynamically, one writes a new entry into the global list. Consider the following example: <lang RLaB> >> s = "myusername" myusername >> $$.[s] = 10; >> myusername
10
</lang>
REXX
<lang rexx> parse arg new value say 'argument=' new value
call value new,value
/*to show the variable, we have to hardcode it here.*/
say 'abc=' abc
</lang>
Output when the following was specified:
abc 456
argument= abc 456 abc= 456
Ruby
<lang ruby>p "Enter a variable name" x = gets.chomp! instance_variable_set "@" + x, 42 p "The value of #{x} is #{instance_variable_get "@" + x}" </lang>
Example output:
"Enter a variable name" hello "The value of hello is 42"
Scheme
<lang scheme> => (define (create-variable name initial-val)
(eval `(define ,name ,initial-val) (interaction-environment)))
=> (create-variable (read) 50) <hello
=> hello 50 </lang>
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. <lang slate>define: #name -> (query: 'Enter a variable name: ') intern. "X" define: name -> 42. X print.</lang>
Smalltalk
Define a block-temporary variable with name specified by user input. Set that variable to 42. Print that variable's name and value. <lang smalltalk> | varName | varName := FillInTheBlankMorph request: 'Enter a variable name'. Compiler evaluate: '| ', varName, ' | ', varName, ' := 42. Transcript show: value of ', varName, '; show: is ; show: ', varName. </lang>
SNOBOL4
Indirect string reference of variables is a basic feature of Snobol, using the $ operator. trim( ) is needed for Snobol4+.
<lang 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</lang>
Output:
Enter variable name: pi Enter value: 3.14159 pi == 3.14159
Tcl
<lang Tcl>puts "Enter a variable name:" gets stdin varname set $varname 42 puts "I have set variable $varname to [set $varname]"</lang> 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: <lang tcl>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)"</lang> Another common method for working with dynamic variables is to make an alias to the variable with a fixed name: <lang tcl>puts -nonewline "Enter a variable name: "; flush stdout gets stdin varname upvar 0 $varname v; # The ‘0’ for “current scope” set v [expr int(rand()*100)] puts "I have set variable $varname to $v (see for yourself: [set $varname])"</lang>
TI-89 BASIC
<lang ti89b>Local varName,value InputStr "Variable name", varName Prompt value value → #varName</lang>
Zsh
<lang zsh>read name typeset $name=42</lang>
- Programming Tasks
- Programming environment operations
- AutoHotkey
- BASIC
- Batch File
- BBC BASIC
- Clojure
- Common Lisp
- E
- Forth
- GAP
- Genyris
- Haskell
- Icon
- Unicon
- J
- JavaScript
- Lua
- Logo
- M4
- MUMPS
- Octave
- PARI/GP
- Perl
- PHP
- PicoLisp
- PowerShell
- Python
- R
- REBOL
- Retro
- RLaB
- REXX
- Ruby
- Scheme
- Slate
- Smalltalk
- SNOBOL4
- Tcl
- TI-89 BASIC
- Zsh
- Ada/Omit
- AmigaE/Omit
- AWK/Omit
- ALGOL 68/Omit
- C/Omit
- C++/Omit
- D/Omit
- Fortran/Omit
- Go/Omit
- GUISS/Omit
- Java/Omit
- Metafont/Omit
- Octave/Omit
- Pascal/Omit
- PureBasic/Omit
- ZX Spectrum Basic/Omit