Some of Sunday's edits have been lost. The edits from Saturday that were reverted have been restored. Site is now hosted on prgmr.com. Thank you for your patience. This notice will be removed one week from posting. --Michael Mol 18:12, 7 March 2010 (UTC)

Runtime evaluation/In an environment

From Rosetta Code

Jump to: navigation, search
Runtime evaluation/In an environment 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
Given a program in the language (as a string or AST) with a free variable named x (or another name if that is not valid syntax), evaluate it with x bound to a provided value, then evaluate it again with x bound to another provided value, then subtract the result of the first from the second and return or print it.

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

Contents

[edit] ALGOL 68

Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386 - this implementation is an interpretor, and evaluate is an extension to the standard

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

Some lines in this example are too long (more than 80 characters). Please fix the code if it's possible and remove this message.
# 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`
def x # bind x and capture its resolver and the 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] 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
print
+ 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
print
+ 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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.]

Personal tools
Google AdSense