Dynamic variable names: Difference between revisions
(→{{header|Common Lisp}}: expand, pedantically) |
(-Java, the TOC will show up when it has four examples you don't need to add it yourself) |
||
Line 1: | Line 1: | ||
{{task}} |
{{task}} |
||
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. |
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. |
||
__TOC__ |
|||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
<lang AutoHotkey> |
<lang AutoHotkey> |
||
Line 92: | Line 92: | ||
{{omit from|C}} |
{{omit from|C}} |
||
{{omit from|Java}} |
Revision as of 19:12, 3 June 2009
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.
AutoHotkey
<lang AutoHotkey> InputBox, Dynamic, Variable Name %Dynamic% = hello ListVars MsgBox % %dynamic% ; says hello </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.
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.
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>
PHP
<lang php><?php $varname = rtrim(fgets(STDIN)); # type in "foo" on standard input $$varname = 42; echo "$foo\n"; # prints "42" ?></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>
Tcl
<lang Tcl>puts "Enter a variable name:" gets stdin varname set $varname 0</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>