Runtime evaluation/In an environment
You are encouraged to solve this task according to the task description, using any language you may know.
Do so in a way which:
- does not involve string manipulation of the input source code
- is plausibly extensible to a runtime-chosen set of bindings rather than just x
- does not make x a global variable
or note that these are impossible.
[edit] See also
- For more general examples and language-specific details, see Eval.
- Dynamic variable names is a similar task.
[edit] ALGOL 68
Variable names are generally not visible at run time with classic compilers. However ALGOL 68G is an interpretor and it retains this ability. Note that evaluate returns a string.
PROC eval_with_x = (STRING code, INT a, b)STRING:
(INT x=a; evaluate(code) ) + (INT x=b; evaluate(code));
print((eval_with_x("2 ** x", 3, 5), new line))
Output:
+8 +32
[edit] AutoHotkey
AutoHotkey does not provide an API to the local symbol table. Local variables are also not supported within scopes outside functions. However, a local environment can be simulated by wrapping code in a temporary function.
msgbox % first := evalWithX("x + 4", 5)
msgbox % second := evalWithX("x + 4", 6)
msgbox % second - first
return
evalWithX(expression, xvalue)
{
global script
script =
(
expression(){
x = %xvalue% ; := would need quotes
return %expression%
}
)
renameFunction("expression", "") ; remove any previous expressions
gosub load ; cannot use addScript inside a function yet
exp := "expression"
return %exp%()
}
load:
DllCall(A_AhkPath "\addScript","Str",script,"Uchar",0,"Cdecl UInt")
return
renameFunction(funcName, newname){
static
x%newname% := newname ; store newname in a static variable so its memory is not freed
strput(newname, &x%newname%, strlen(newname) + 1)
if fnp := FindFunc(funcName)
numput(&x%newname%, fnp+0, 0, "uint")
}
[edit] BBC BASIC
expression$ = "x^2 - 7"
one = FN_eval_with_x(expression$, 1.2)
two = FN_eval_with_x(expression$, 3.4)
PRINT two - one
END
DEF FN_eval_with_x(expr$, x)
= EVAL(expr$)
[edit] Common Lisp
(defun eval-with-x (program a b)
(let ((at-a (eval `(let ((x ',a)) ,program)))
(at-b (eval `(let ((x ',b)) ,program))))
(- at-b at-a)))
(eval-with-x '(exp x) 0 1)
=> 1.7182817
This version ensures that the program is compiled, once, for more efficient execution:
(defun eval-with-x (program a b)
(let* ((f (compile nil `(lambda (x) ,program)))
(at-a (funcall f a))
(at-b (funcall f b)))
(- at-b at-a)))
[edit] E
# Constructing an environment has to be done by way of evaluation
#for historical reasons which will hopefully be entirely eliminated soon.
def bindX(value) {
def [resolver, env] := e` # bind x and capture its resolver and the
def x # resulting environment
`.evalToPair(safeScope)
resolver.resolve(value) # set the value
return env
}
def evalWithX(program, a, b) {
def atA := program.eval(bindX(a))
def atB := program.eval(bindX(b))
return atB - atA
}
? evalWithX(e`(x :float64).exp()`, 0, 1)
# value: 1.7182818284590455
[edit] Erlang
-module( runtime_evaluation ).
-export( [task/0] ).
task() ->
Form = form_from_string( "X." ),
Variable1 = evaluate_form( Form, {'X', 1} ),
io:fwrite( "~p~n", [Variable1] ),
Variable2 = evaluate_form( Form, {'X', 2} ),
io:fwrite( "~p~n", [Variable2] ),
io:fwrite( "~p~n", [Variable2 - Variable1] ).
evaluate_form( Form, {Variable_name, Value} ) ->
Bindings = erl_eval:add_binding( Variable_name, Value, erl_eval:new_bindings() ),
{value, Evaluation, _} = erl_eval:expr( Form, Bindings ),
Evaluation.
form_from_string( String ) ->
{ok, Tokens, _} = erl_scan:string( String ),
{ok, [Form]} = erl_parse:parse_exprs( Tokens ),
Form.
- Output:
14> runtime_evaluation:task(). 1 2 1
[edit] Forth
EVALUATE invokes the Forth interpreter on the given string.
: f-" ( a b snippet" -- )
[char] " parse ( code len )
2dup 2>r evaluate
swap 2r> evaluate
- . ;
2 3 f-" dup *" \ 5 (3*3 - 2*2)
This can be used to treat a data stream as code, or to provide a lightweight macro facility when used in an IMMEDIATE word.
: :macro ( "name <char> ccc<char>" -- )
: [CHAR] ; PARSE POSTPONE SLITERAL POSTPONE EVALUATE
POSTPONE ; IMMEDIATE
;
:macro times 0 do ;
: test 8 times ." spam " loop ;
see test
: test
8 0
DO .\" spam "
LOOP
; ok
[edit] Genyris
One way is to use a macro. In genyris, macros are lazy functions which execute twice, the return value is also evaluated in the caller's environment:
defmacro add100() (+ x 100)
var x 23
var firstresult (add100)
x = 1000
+ firstresult (add100)
This prints 1223.
Another way is to use dynamically scoped variables. In Genyris, symbols prefixed with a period are looked up in the caller's environment, not the lexical environment of the closure. When a dictionary is the first element of the expression, an environment is created and the &rest is evaluated.
def add100() (+ .x 100)
(dict) # create an environment capable of holding dynamic bindings
var .x 23 # create a binding in the dictionary
var firstresult (add100)
.x = 1000
+ firstresult (add100)
Dictionaries can hold bindings to dynamic symbols. To minimize the danger of dynamic scope there is no recursive ascent in the binding lookup.
(dict)
var .x 23
(dict)
print .x # fails
[edit] Go
package main
import (
"bitbucket.org/binet/go-eval/pkg/eval"
"fmt"
"go/parser"
"go/token"
)
func main() {
// an expression on x
squareExpr := "x*x"
// parse to abstract syntax tree
fset := token.NewFileSet()
squareAst, err := parser.ParseExpr(squareExpr)
if err != nil {
fmt.Println(err)
return
}
// create an environment or "world"
w := eval.NewWorld()
// allocate a variable
wVar := new(intV)
// bind the variable to the name x
err = w.DefineVar("x", eval.IntType, wVar)
if err != nil {
fmt.Println(err)
return
}
// bind the expression AST to the world
squareCode, err := w.CompileExpr(fset, squareAst)
if err != nil {
fmt.Println(err)
return
}
// directly manipulate value of variable within world
*wVar = 5
// evaluate
r0, err := squareCode.Run()
if err != nil {
fmt.Println(err)
return
}
// change value
*wVar--
// revaluate
r1, err := squareCode.Run()
if err != nil {
fmt.Println(err)
return
}
// print difference
fmt.Println(r0.(eval.IntValue).Get(nil) - r1.(eval.IntValue).Get(nil))
}
// int value implementation.
type intV int64
func (v *intV) String() string { return fmt.Sprint(*v) }
func (v *intV) Get(*eval.Thread) int64 { return int64(*v) }
func (v *intV) Set(_ *eval.Thread, x int64) { *v = intV(x) }
func (v *intV) Assign(t *eval.Thread, o eval.Value) {
*v = intV(o.(eval.IntValue).Get(t))
}
Output:
9
[edit] Groovy
The solution:
def cruncher = { x1, x2, program ->
Eval.x(x1, program) - Eval.x(x2, program)
}
Test Program:
def fibonacciProgram = '''
x < 1 ? 0 : x == 1 ? 1 : (2..x).inject([0,1]){i, j -> [i[1], i[0]+i[1]]}[1]
'''
println "F(${10}) - F(${5}) = ${Eval.x(10, fibonacciProgram)} - ${Eval.x(5, fibonacciProgram)} = " + cruncher(10, 5, fibonacciProgram)
Output:
F(10) - F(5) = 55 - 5 = 50
[edit] J
[edit] Explicit
The following satisfies the requirements:
EvalWithX=. monad : 0
'CODE V0 V1'=. y
(". CODE [ x=. V1) - (". CODE [ x=. V0)
)
EvalWithX '^x';0;1
1.71828183
[edit] Tacit
However, it is easier via point-free coding:
(0&({::) -~&>/@:(128!:2&.>) 1 2&{) '^';0;1
1.71828183
[edit] Explicit again
Or, using y as the free variable, instead of x:
EvalDiffWithY=: dyad define
-~/verb def x"_1 y
)
Example use:
'^y' EvalDiffWithY 0 1
1.71828
This can be extended to support a user declared argument name:
EvalDiffWithName=: adverb define
:
-~/m adverb def ('(m)=.y';x)"_1 y
)
This works by preceding the user provided expression with a statement which assigns the argument value to a local variable whose name was provided by the user. [Note that this implementation skirts the requirement that the implementation does not manipulate strings -- instead we manipulate a structure containing strings.]
Example use:
'^George' 'George' EvalDiffWithName 0 1
1.71828
'Z + 2^Z' 'Z' EvalDiffWithName 2 3
5
Of course this could be re-defined such that the free variable declaration appears to the left of the expression ('Z' 'Z + 2^Z' Example 2 3). However, J's currying and precedence rules might make that less convenient to use, if this were ever used in a real program.
[edit] Java
Java is compiled static language and expression evaluation is not intrinsic part of Java or the standard libraries. In scripting languages for example - it makes sense to have eval method, as interpreter can interpret string and include its contents as part of the surrounding methods, with complete access to local variables.
Clearly there are lots of ways to get around the problem, but as of Java 6, Java can contain scripting environments. For example Mozilla Rihno JavaScript engine is contained in JDK 6 Bean Scripting Framework.
Example:
ScriptEngine js = new ScriptEngineManager().getEngineByName("js");
System.out.println(js.eval("function D(x){return x*2;} var x=3; x=D(x);"));
Output:
6.0
[edit] JavaScript
eval uses the environment from the calling function.
function evalWithX(expr, a, b) {
var x = a;
var atA = eval(expr);
x = b;
var atB = eval(expr);
return atB - atA;
}
evalWithX('Math.exp(x)', 0, 1) // returns 1.718281828459045
[edit] Liberty BASIC
expression$ = "x^2 - 7"
Print (EvaluateWithX(expression$, 5) - EvaluateWithX(expression$, 3))
End
Function EvaluateWithX(expression$, x)
EvaluateWithX = Eval(expression$)
End Function
[edit] Lua
code = loadstring"return x^2" --this doesn't really need to be input, does it?
val1 = setfenv(code, {x = io.read() + 0})()
val2 = setfenv(code, {x = io.read() + 0})()
print(val2 - val1)
[edit] Mathematica
Input source code is "10 x" , X is locally bound to 3 & 2 and the resulting expressions evaluated.
(10 x /. x -> 3 ) - (10 x /. x -> 2 )
-> 10
[edit] Metafont
vardef evalit(expr s, va, vb) =
save x,a,b; x := va; a := scantokens s;
x := vb; b := scantokens s; a-b
enddef;
show(evalit("2x+1", 5, 3));
end
[edit] Octave
In Octave, undeclared variables are local.
function r = calcit(f, val1, val2)
x = val1;
a = eval(f);
x = val2;
b = eval(f);
r = b-a;
endfunction
p = "x .* 2";
disp(calcit(p, [1:3], [4:6]));
Output:
6 6 6
[edit] ooRexx
The ooRexx interpret instruction executes dynamically created ooRexx code in the current variable context.
say evalWithX("x**2", 2)
say evalWithX("x**2", 3.1415926)
::routine evalWithX
use arg expression, x
-- X now has the value of the second argument
interpret "return" expression
Output:
4 9.86960406
[edit] Oz
declare
fun {EvalWithX Program A B}
{Compiler.evalExpression Program env('X':B) _}
-
{Compiler.evalExpression Program env('X':A) _}
end
in
{Show {EvalWithX "{Exp X}" 0.0 1.0}}
[edit] PARI/GP
There are many ways of doing this depending on the particular interpretation of the requirements. This code assumes that f is a string representing a GP closure.
test(f,a,b)=f=eval(f);f(a)-f(b);
test("x->print(x);x^2-sin(x)",1,3)
[edit] Perl
sub eval_with_x
{my $code = shift;
my $x = shift;
my $first = eval $code;
$x = shift;
return eval($code) - $first;}
print eval_with_x('3 * $x', 5, 10), "\n"; # Prints "15".
[edit] Perl 6
sub eval_with_x($code, *@x) { [R-] @x.map: -> \x { eval $code } }
say eval_with_x('3 * x', 5, 10); # Says "15".
say eval_with_x('3 * x', 5, 10, 50); # Says "135".
[edit] PHP
<?php
function eval_with_x($code, $a, $b) {
$x = $a;
$first = eval($code);
$x = $b;
$second = eval($code);
return $second - $first;
}
echo eval_with_x('return 3 * $x;', 5, 10), "\n"; # Prints "15".
?>
[edit] PicoLisp
(let Expression '(+ X (* X X)) # Local expression
(println
(+
(let X 3
(eval Expression) )
(let X 4
(eval Expression) ) ) )
(let Function (list '(X) Expression) # Build a local function
(println
(+
(Function 3)
(Function 4) ) ) ) )
Output:
32 32
[edit] Pike
Pike can only compile complete classes. therefore binding a value to a variable is only possible by string manipulation. even Pikes own interactive mode which seemingly evaluates expressions wraps them into a class and replaces variable references before compiling:
> int x=10;
Result: 10
> x * 5;
Result: 50
> dump wrapper
Last compiled wrapper:
001: mapping(string:mixed) ___hilfe = ___Hilfe->variables;
002: # 1
003: mixed ___HilfeWrapper() { return (([mapping(string:int)](mixed)___hilfe)->x) * 5; ; }
004:
>
___Hilfe is an object which stores all created variables;
to solve the problem in the task i would create a function that can take arguments:
string payload = "x * 5";
program demo = compile_string("string eval(mixed x){ " + payload + "; }");
demo()->eval(10);
Result: 50
demo()->eval(20);
Result: 100
[edit] Python
>>> def eval_with_x(code, a, b):
return eval(code, {'x':b}) - eval(code, {'x':a})
>>> eval_with_x('2 ** x', 3, 5)
24
A slight change allows the evaluation to take multiple names:
>>> def eval_with_args(code, **kwordargs):
return eval(code, kwordargs)
>>> code = '2 ** x'
>>> eval_with_args(code, x=5) - eval_with_args(code, x=3)
24
>>> code = '3 * x + y'
>>> eval_with_args(code, x=5, y=2) - eval_with_args(code, x=3, y=1)
7
[edit] R
We can set up thing so that the "unbound" variable can be any accepted symbol for variables.
evalWithAB <- function(expr, var, a, b) {
env <- new.env() # provide a separate env, so that the choosen
assign(var, a, envir=env) # var name do not collide with symbols inside
# this function (e.g. it could be even "env")
atA <- eval(parse(text=expr), env)
# and then evaluate the expression inside this
# ad hoc env-ironment
assign(var, b, envir=env)
atB <- eval(parse(text=expr), env)
return(atB - atA)
}
print(evalWithAB("2*x+1", "x", 5, 3))
print(evalWithAB("2*y+1", "y", 5, 3))
print(evalWithAB("2*y+1", "x", 5, 3)) # error: object "y" not found
[edit] Racket
Same hack as the on in the CL/Scheme entries:
#lang racket
(define ns (make-base-namespace))
(define (eval-with-x code a b)
(define (with v) (eval `(let ([x ',v]) ,code) ns))
(- (with b) (with a)))
Better: a more direct use of eval with just the code (for example, this won't break if we use a namespace with a different meaning for let, which is very possible in Racket):
#lang racket
(define ns (make-base-namespace))
(define (eval-with-x code a b)
(define (with v)
(namespace-set-variable-value! 'x v #f ns)
(eval code ns))
(- (with b) (with a)))
[edit] REBOL
prog: [x * 2]
fn: func [x] [do bind prog 'x]
a: fn 2
b: fn 4
subtract b a
Result:
4
[edit] REXX
/*REXX program to demonstrate some run-time evaulations. */
a=fact(3)
b=fact(4)
say b-a
exit /*stick a fork in it, we're done.*/
/*───────────────────────────────────FACT subroutine────────────────────*/
fact: procedure; parse arg n; !=1; do j=2 to n; !=!*j; end; return !
output
18
[edit] Ruby
def bind_x_to_value(x)
binding
end
def eval_with_x(code, a, b)
eval(code, bind_x_to_value(b)) - eval(code, bind_x_to_value(a))
end
puts eval_with_x('2 ** x', 3, 5) # Prints "24"
The magic here is how the binding method works with the bind_x_to_value(x) method.
When bind_x_to_value is called, it sets its local variable x to the value passed.
The binding method then returns a reference to the current context (or stack frame) to the caller.
eval can then use the local variable x in this context.
[edit] Scheme
Almost identical to the Common Lisp version above.
(define (eval-with-x prog a b)
(let ((at-a (eval `(let ((x ',a)) ,prog)))
(at-b (eval `(let ((x ',b)) ,prog))))
(- at-b at-a)))
[edit] SNOBOL4
This program defines (at runtime) a function triple(), compiles it, and then executes it twice, with values x = 1 and then x = 3. The program subtracts the returned value from the first call from the value returned from the first call, and prints the result. In this example, the value x is passed as a parameter to the function triple().
compiled = code(' define("triple(x)") :(a);triple triple = 3 * x :(return)') :<compiled>
a x = 1
first = triple(x)
x = 3
output = triple(x) - first
end
Output:
6
If you specifically wanted to not pass x as a parameter but instead use it as a value from the environment, that's easy too:
compiled = code(' define("triple()") :(a);triple triple = 3 * x :(return)') :<compiled>
a x = 1
first = triple(x)
x = 3
output = triple(x) - first
end
The output is the same.
[edit] Tcl
proc eval_twice {func a b} {
set x $a
set 1st [expr $func]
set x $b
set 2nd [expr $func]
expr {$2nd - $1st}
}
puts [eval_twice {2 ** $x} 3 5] ;# ==> 24
Here's another take, similar to other answers. It passes a code block to be evaled, not just an expression for expr
proc eval_with_x {code val1 val2} {
expr {[set x $val2; eval $code] - [set x $val1; eval $code]}
}
eval_with_x {expr {2**$x}} 3 5 ;# ==> 24
[edit] TI-89 BASIC
evalx(prog, a, b)
Func
Local x,eresult1,eresult2
a→x
expr(prog)→eresult1
b→x
expr(prog)→eresult2
Return eresult2-eresult1
EndFunc
■ evalx("ℯ^x", 0., 1)
1.71828
There are no facilities for control over the environment; expr() evaluates in the same environment as the caller, including local variables. [Someone please verify this statement.]
[edit] UNIX Shell
The backquotes ` ... ` capture the standard output of a subshell. Changes to parameter x in the subshell will not affect its parent shell.
eval_with_x() {
set -- "`x=$2; eval "$1"`" "`x=$3; eval "$1"`"
expr "$2" - "$1"
}
eval_with_x '
# compute 2 ** $x
p=1
while test $x -gt 0; do
p=`expr $p \* 2`
x=`expr $x - 1`
done
echo $p
' 3 5
# Prints '24'
- Programming Tasks
- Solutions by Programming Task
- ALGOL 68
- AutoHotkey
- BBC BASIC
- Common Lisp
- E
- Erlang
- Forth
- Genyris
- Go
- Groovy
- J
- Java
- Java examples needing attention
- Examples needing attention
- JavaScript
- Liberty BASIC
- Lua
- Mathematica
- Metafont
- Octave
- OoRexx
- Oz
- PARI/GP
- Perl
- Perl 6
- PHP
- PicoLisp
- Pike
- Python
- R
- Racket
- REBOL
- REXX
- Ruby
- Scheme
- SNOBOL4
- Tcl
- TI-89 BASIC
- TI-89 BASIC examples needing attention
- UNIX Shell
- Ada/Omit
- C/Omit
- D/Omit
- Haskell/Omit
- GUISS/Omit