Dynamic variable names

From Rosetta Code
Revision as of 20:37, 2 November 2013 by Jono (talk | contribs) (→‎{{header|Lasso}}: Demonstrating dynamic variable names in Lasso)
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.

See also

AutoHotkey

<lang AutoHotkey>InputBox, Dynamic, Variable Name %Dynamic% = hello ListVars MsgBox % %dynamic%  ; says hello</lang>

BASIC

Works with: Beta BASIC version 3.0

,

Works with: SAM BASIC

<lang basic>10 INPUT "Enter a variable name", v$ 20 KEYIN "LET "+v$+"=42"</lang>

Batch File

<lang DOS>@echo off setlocal enableDelayedExpansion

set /p "name=Enter a variable name: " set /p "value=Enter a value: "

Create the variable and set its value

set "%name%=%value%"

Display the value without delayed expansion

call echo %name%=%%%name%%%

Display the value using delayed expansion

echo %name%=!%name%!</lang>

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>

Bracmat

<lang bracmat>( put$"Enter a variable name: " & get$:?name & whl

 ' ( put$"Enter a numeric value: "
   & get$:?numeric:~#
   )

& !numeric:?!name & put$(str$("Variable " !name " now has the value " !!name \n)) );</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| 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.

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

  1. value: [1, 2, 3]

? dynVarName("b")

  1. value: [1, "BOO!", 3]

? dynVarName("c")

  1. 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).

Erlang

This task uses functions from Runtime evaluation. <lang Erlang> -module( dynamic_variable_names ).

-export( [task/0] ).

task() ->

   {ok,[Variable_name]} = io:fread( "Variable name? ",	"~a" ),
   Form = runtime_evaluation:form_from_string( erlang:atom_to_list(Variable_name) ++ "." ),
   io:fwrite( "~p has value ~p~n", [Variable_name, runtime_evaluation:evaluate_form(Form, {Variable_name, 42})] ).

</lang>

Output:
12> dynamic_variable_names:task().
Variable name? Asd
'Asd' has value 42

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>

Groovy

Solution: <lang groovy>def varname = 'foo' def value = 42

new GroovyShell(this.binding).evaluate("${varname} = ${value}")

assert foo == 42</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>


Lasso

Thread vars in Lasso 9 can have dynamic names, but local variables cannot.

The example below outputs a random decimal that was assigned to the variable name entered as part of the GET params. <lang Lasso>local(thename = web_request->param('thename')->asString) if(#thename->size) => {^ var(#thename = math_random) var(#thename) else '<a href="?thename=xyz">Please give the variable a name!</a>' ^}</lang>

Logtalk

Logtalk objects can be create or compiled such that new predicates can be added at runtime. A simple example: <lang logtalk> | ?- create_object(Id, [], [set_logtalk_flag(dynamic_declarations,allow)], []),

    write('Variable name:  '), read(Name),
    write('Variable value: '), read(Value),
    Fact =.. [Name, Value],
    Id::assertz(Fact).

Variable name: foo. Variable value: 42. Id = o1, Name = foo, Value = 42, Fact = foo(42).

?- o1::current_predicate(foo/1). true.

| ?- o1::foo(X). X = 42. </lang>

Lua

<lang lua>_G[io.read()] = 5 --puts 5 in a global variable named by the user</lang>

<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%

Mathematica

<lang Mathematica>varname = InputString["Enter a variable name"]; varvalue = InputString["Enter a value"]; ReleaseHold[ Hold[Set["nameholder", "value"]] /. {"nameholder" -> Symbol[varname], "value" -> varvalue}]; Print[varname, " is now set to ", Symbol[varname]]</lang>

Example output:
-> testvar is now set to 86

Maxima

<lang maxima>/* Use :: for indirect assignment */ block([name: read("name?"), x: read("value?")], name :: x);</lang>

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, "@". <lang mumps>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</lang>

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>

Perl 6

It is not possible to change lexical variable names at run time, but package variables are fair game, include in the GLOBAL package: <lang perl6>my $vname = prompt 'Variable name: '; $GLOBAL::($vname) = 42; say $GLOBAL::($vname);</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>

ProDOS

<lang>editvar /newvar /value=a /userinput=1 /title=Enter a variable name: editvar /newvar /value=b /userinput=1 /title=Enter a variable title: editvar /newvar /value=-a- /title=-b-</lang>

Python

Works with: Python version 2.x

<lang python>>>> name = raw_input("Enter a variable name: ") Enter a variable name: X >>> globals()[name] = 42 >>> X 42</lang>

Works with: Python version 3.x

<lang python>>>> name = input("Enter a variable name: ") Enter a variable name: X >>> globals()[name] = 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 >")

  1. Make sure the name is valid for a variable

varname <- make.names(varname) message(paste("The variable being assigned is '", varname, "'"))

  1. Assign the variable (with value 42) into the user workspace (global environment)

assign(varname, 42)

  1. Check that the value has been assigned ok

ls(pattern=varname) get(varname)</lang>

Racket

This works on the Racket REPL:

<lang Racket> -> (begin (printf "Enter some name: ")

         (namespace-set-variable-value! (read) 123))

Enter some name: bleh -> bleh 123 </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>

REXX

<lang rexx>/*REXX program to show use of dynamic variable names. */

parse arg new value say 'Arguments as they were entered via the command line =' new value say call value new,value say 'The newly assigned value (as per the VALUE bif)------' new value(new)</lang> output for the input: abc 456

Arguments as they were entered via the command line = abc 45678.1

The newly assigned value (as per the VALUE bif)------ abc 45678.1

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>

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

Works with: Pharo

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>

TUSCRIPT

<lang tuscript> $$ MODE TUSCRIPT ASK "Enter variablename": name="" ASK "Enter value": value="" TRACE +@name @name=$value PRINT @name </lang> Output:

Enter variablename >test
Enter value >Hello World!
TRACING     Scratch-Datei -*TUSTEP.EDT
   5    00  TRACE +@name
test         = Hello World!
Hello World!

Zsh

<lang zsh>read name typeset $name=42</lang>